Files
Main/Assets/Plugins/Code/UniScene/PathGrid/PathGridSystem.cs

462 lines
14 KiB
C#
Raw Normal View History

2025-01-25 04:38:09 +08:00
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<int, PathBlocker> 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<PathItemMonoBehaviour>();
if (script == null)
{
script = navObj.AddComponent<PathItemMonoBehaviour>();
}
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<int, PathBlocker>();
}
_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<int, int, bool, bool> 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<Vector2> SearchPlayerPath(Vector3 startPosition, Vector3 endPosition)
{
return null;
}
//其他怪物的寻路
public virtual List<Vector2> SearchOtherPath(Vector3 startPosition, Vector3 endPosition)
{
return null;
}
//寻路到某个物体
public virtual List<Vector2> SearchTargetPath(Vector3 startPosition, Vector3 endPosition, float targetRadius)
{
return null;
}
//评价路径,返回-1表示无法寻路到达返回距离表示到目标点的实际距离
public virtual float EvaluatePath(Vector3 startPosition, Vector3 endPosition)
{
return -1f;
}
}
}