using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using PathEditor.Proxy.Plugin; using Thousandto.Core.Base; using SimpleAI.Navigation; using SimpleAI.Planning; using Thousandto.Plugins.Common.UniScene; using UnityEngine; using FFileReader = UnityEngine.Gonbest.MagicCube.FFileReader; namespace Thousandto.Plugins.PathGrid { //路径网格寻路系统 public class PathGridSystem { #region//常量 private const int PlannerRowCount = 128; private const int PlannerColCount = 128; #endregion #region //私有变量 private GameObject navObj = null; //从文件中读取路径的网格数据 private static PathGirdData _pathGridData = null; //陆地寻路系统 private static PathLandSystem _pathLandSystem = null; //动态阻挡 public Dictionary dynamicBlockers = null; //处于的场景 private BaseScene _owner = null; //上次载入的文件名,用以判断是否重新加载 private string _frontLoadFile = string.Empty; #endregion #region //公共变量 public PathWorld _pathWorld = null; public static PathPlanner _pathPlannder = new PathPlanner(PlannerRowCount * PlannerColCount, PreSearchSize); public const int PreSearchSize = 20 * 20; public static PathType PathType = PathType.Land; #endregion #region //属性 public PathGirdData PathGridData { get { return _pathGridData; } } public float CellSize { get { return _pathGridData.CellSize; } } public BaseScene Owner { get { return _owner; } } public static PathGridSystem instance { get { if (PathType == PathType.Land) { if (_pathLandSystem == null) { _pathLandSystem = new PathLandSystem(); } return _pathLandSystem; } return null; } } #endregion #region//构造函数 //私有构造函数,防止外部new protected PathGridSystem() { } #endregion //初始化寻路系统 public virtual void Initialize(BaseScene scene) { #if UNITY_EDITOR FProfiler.Begin("PathGridSystem.Navigator"); if(navObj == null) { navObj = new GameObject("[Navigator]"); } navObj.transform.parent = AppRoot.Transform; PathItemMonoBehaviour script = navObj.GetComponent(); if (script == null) { script = navObj.AddComponent(); } script.m_mergedPathGrid = PathGridData.MergedData; script.m_mergedWeightPathGrid = PathGridData.MergeWeightData; script.m_heightMap = PathGridData.HeightMap; script.m_numberOfRows = PathGridData.NumberOfRows; script.m_numberOfColumns = PathGridData.NumberOfColumns; script.m_cellSize = PathGridData.CellSize; FProfiler.End(); #endif FProfiler.Begin("PathGridSystem.Initialize"); int nodeNum = PathGridData.NumberOfRows * PathGridData.NumberOfColumns; _pathWorld = new PathWorld(PathGridData); _pathWorld.Awake(); _pathPlannder.Awake(); _pathPlannder.Start(_pathWorld); if(dynamicBlockers == null) { dynamicBlockers = new Dictionary(); } _owner = scene; FProfiler.End(); } //卸载寻路系统 public virtual void Uninitialize() { _pathGridData = null; if (dynamicBlockers != null) { dynamicBlockers.Clear(); dynamicBlockers = null; } } //从地图路径网格文件中读出数据 public void LoadPathGridData(String fileName) { var filePath = FileUtils.MapInfoDirPath + '/' + fileName; if(_pathGridData == null || filePath != _frontLoadFile) { _frontLoadFile = filePath; if (_pathGridData == null) { _pathGridData = new PathGirdData(); } FFileReader.ReadBytesAsync(filePath,x=> { if (x != null) { _pathGridData.Load(x); } }); } } //获取路径网格的长和宽 public Vector2 Get2DSize() { Vector2 size = new Vector2(0.0f, 0.0f); if (PathGridData != null) { size.x = PathGridData.NumberOfColumns * PathGridData.CellSize; size.y = PathGridData.NumberOfRows * PathGridData.CellSize; } return size; } //移除动态阻挡 public bool RemoveBlocker(ref int id) { PathBlocker blocker = null; if (dynamicBlockers.TryGetValue(id, out blocker)) { if (dynamicBlockers.Remove(id)) { blocker.Disable(); id = 0; } return true; } return false; } //开启指定动态阻挡 public bool EnableBlocker(int id) { PathBlocker blocker = null; if (dynamicBlockers != null && dynamicBlockers.TryGetValue(id, out blocker)) { return blocker.Enable(); } return false; } //关闭指定动态阻挡 public bool DisableBlocker(int id) { PathBlocker blocker = null; if (dynamicBlockers != null && dynamicBlockers.TryGetValue(id, out blocker)) { return blocker.Disable(); } return false; } //增加动态圆圈阻挡 public int AddCircleBlocker(ref Vector2 center, float radius, int instId = 0) { var blocker = PathBlocker.CreateCircle(PathGridData, ref center, radius, instId); if (!dynamicBlockers.ContainsKey(blocker.instId)) { dynamicBlockers.Add(blocker.instId, blocker); return blocker.instId; } return 0; } //增加四个方格的阻挡 public int AddAABBBlocker(ref Vector2 center, ref Vector2 size, int instId = 0) { var blocker = PathBlocker.CreateAABB(PathGridData, ref center, ref size, instId); if (!dynamicBlockers.ContainsKey(blocker.instId)) { dynamicBlockers.Add(blocker.instId, blocker); return blocker.instId; } return 0; } //增加指定方向上的阻挡 public int AddOBBBlocker(ref Vector2 center, ref Vector2 size, ref Vector2 dir, int instId = 0) { var blocker = PathBlocker.CreateOBB(PathGridData, ref center, ref size, ref dir, instId); if (!dynamicBlockers.ContainsKey(blocker.instId)) { dynamicBlockers.Add(blocker.instId, blocker); return blocker.instId; } return 0; } //判断两点之间是否有阻挡单元,有的话,找到离玩家最近的那个阻挡点 public bool Raycast2d(Vector2 start, Vector2 end, out Vector2 hit) { return PathGridData.Raycast2d(start, end, out hit); } //判断两点之间是否有安全单元,有的话,找到离玩家最近的那个阻挡点 public bool Raycast2dSafe(Vector2 start, Vector2 end, out Vector2 hit) { return PathGridData.Raycast2dSafe(start, end, out hit); } public bool RayCastJumpBlock(Vector2 start, Vector2 end, out Vector2 hit) { return PathGridData.Raycast2dJumpBlock(start, end,out hit); } public bool RaycastEx2d(Vector2 start, Vector2 end, out Vector2 hit, Func func) { return PathGridData.RaycastEx2d(start, end, out hit, func); } //判断两点之间是否有跳跃单元,有的话,找到离玩家最近的跳跃点 public bool Raycast2dJump(Vector2 start, Vector2 end, out Vector2 hit) { return PathGridData.Raycast2dJump(start, end, out hit); } //判断一个位置到另一个位置是否可以直走 public bool CanGoDirect(Vector2 startPos, Vector2 endPos) { Vector2 hit; return !PathGridData.Raycast2d(startPos, endPos, out hit); } //判断一个位置到另一个位置是否经过了安全区 public bool CanGoDirectSafe(Vector2 startPos, Vector2 endPos) { Vector2 hit; return !PathGridData.Raycast2dSafe(startPos, endPos, out hit); } //获取指定单元格的类型 public PathGridType GetCellType(Vector2 position) { int cellIndex = _pathWorld.GetCellIndex(ref position); return _pathWorld.GetCellType(cellIndex); } //指定位置是否可以跳跃 public bool IsJump(Vector2 position) { int cellIndex = _pathWorld.GetCellIndex(ref position); return _pathWorld.IsJump(cellIndex); } //指定位置是否可以跳跃 public bool IsJump(Vector3 position) { int cellIndex = _pathWorld.GetCellIndex(ref position); return _pathWorld.IsJump(cellIndex); } //指定位置是否可以跳跃 public bool IsJump(ref Vector2 position) { int cellIndex = _pathWorld.GetCellIndex(ref position); return _pathWorld.IsJump(cellIndex); } //指定位置是否可以跳跃 public bool IsJump(ref Vector3 position) { int cellIndex = _pathWorld.GetCellIndex(ref position); return _pathWorld.IsJump(cellIndex); } //指定位置是否能跳指定高度 public bool CanJump(ref Vector2 position, float height) { int cellIndex = _pathWorld.GetCellIndex(ref position); return _pathWorld.CanJump(cellIndex, height); } //指定位置是否阻挡 public bool IsBlocked(Vector2 position) { int cellIndex = _pathWorld.GetCellIndex(ref position); return _pathWorld.IsBlocked(cellIndex); } //指定位置是否阻挡 public bool IsBlocked(Vector3 position) { int cellIndex = _pathWorld.GetCellIndex(ref position); return _pathWorld.IsBlocked(cellIndex); } //指定位置是否是安全区 public bool IsSafe(Vector3 position) { int cellIndex = _pathWorld.GetCellIndex(ref position); return _pathWorld.IsSafe(cellIndex); } //指定位置是否阻挡 public bool IsBlocked(ref Vector2 position) { int cellIndex = _pathWorld.GetCellIndex(ref position); return _pathWorld.IsBlocked(cellIndex); } //指定位置是否阻挡 public bool IsBlocked(ref Vector3 position) { int cellIndex = _pathWorld.GetCellIndex(ref position); return _pathWorld.IsBlocked(cellIndex); } //获取指定位置的路径网格的单元格索引 public int GetCellIndex(Vector2 position) { return _pathWorld.GetCellIndex(ref position); } public Vector2 CalculationRayCastPos2d(Vector2 start, Vector2 end) { if (start == end) return start; var dis = Vector2.Distance(end, start); var whileCount = (int)(dis / CellSize + 1); var tmpPos = Vector2.zero; var result = start; var lerpValue = 0f; for (int i = 0; i <= whileCount; ++i) { lerpValue = i / (float)whileCount; tmpPos = Vector2.Lerp(start, end, lerpValue); if (IsBlocked(tmpPos)) { break; } else { result = tmpPos; } } return result; } //开始点到目标点是否通畅 public bool IsNotBlockRayCast2d(Vector2 start, Vector2 end) { if (start == end) return true; var dis = Vector2.Distance(end, start); var whileCount = (int)(dis / CellSize + 1); var tmpPos = Vector2.zero; var result = start; var lerpValue = 0f; for (int i = 0; i <= whileCount; ++i) { lerpValue = i / (float)whileCount; tmpPos = Vector2.Lerp(start, end, lerpValue); if (IsBlocked(tmpPos)) { return false; } else { result = tmpPos; } } return true; } //开始点到目标点是否通畅 public bool IsNotBlockRayCast(Vector3 start, Vector3 end) { return IsNotBlockRayCast2d(new Vector2(start.x, start.z), new Vector2(end.x, end.z)); } //玩家角色寻路 public virtual List SearchPlayerPath(Vector3 startPosition, Vector3 endPosition) { return null; } //其他怪物的寻路 public virtual List SearchOtherPath(Vector3 startPosition, Vector3 endPosition) { return null; } //寻路到某个物体 public virtual List SearchTargetPath(Vector3 startPosition, Vector3 endPosition, float targetRadius) { return null; } //评价路径,返回-1表示无法寻路到达,返回距离表示到目标点的实际距离 public virtual float EvaluatePath(Vector3 startPosition, Vector3 endPosition) { return -1f; } } }