A* Pathfinding Project的获取A* Pathfinding Project是一个实用的寻路工具包,可在其官网获取免费版A* Pathfinding Project本教程为基于2D样例场景的入门教程, 3D 寻路用法请查看官方文档开始使用网格图 - A*寻路项目 --- Get started with grid graphs - A* Pathfinding Project导入安装包后可查看2D样例场景在样例中,寻路对象会移动到鼠标点击的位置寻路对象以样例为例,寻路对象需要挂载AIPath或AILerp脚本,Seeker脚本随AIPath/Lerp脚本自动添加.区别在于,AIPath 脚本会对路线使用一些平滑效果;AILerp 会精确地沿着路径移动没有任何偏移。AIPath配置参考其中,如果希望寻路对象不可以旋转,请勾选Enable Rotation网格图网格图需要挂载Pathfinder脚本,点击底部的扫描按钮后,场景中可行走区域显示为蓝色可以展开Pathfinder脚本中的Graphs,设置障碍物的Layer层级障碍物1.障碍物需要挂载2D碰撞体组件2.障碍物的层级要和Graphs中保持一致3.障碍物移动、修改后,网格图要重新扫描样例脚本 中文注释参考挂载在寻路对象上的 Al Destination Setterpublic class AIDestinationSetter : VersionedMonoBehaviour { /// summaryAI 需要前往的目标物体/summary public Transform target; // AI寻路接口实例 IAstarAI ai; // 组件启用时执行 void OnEnable() { // 获取当前物体上的AI寻路接口组件 ai GetComponentIAstarAI(); // 在开始寻路前同步更新目标点。 // 理论上仅这一处更新就足够但由于目标点会用于调试也可能被其他脚本调用 // 因此脚本会每帧同步目标位置保证数据始终为最新状态。 if (ai ! null) ai.onSearchPath Update; } // 组件禁用时执行 void OnDisable() { // 移除事件订阅避免报错 if (ai ! null) ai.onSearchPath - Update; } /// summary每帧更新AI的移动目标点/summary void Update() { // 目标物体和AI组件都存在时赋值AI终点坐标 if (target ! null ai ! null) ai.destination target.position; } }挂载在Target上的TargetMoverpublic class TargetMover : MonoBehaviour { /// summary射线检测的层级遮罩仅检测指定层级物体/summary public LayerMask mask; // 被移动的目标点Transform组件 public Transform target; // 场景中所有实现了A*寻路AI接口的对象数组 IAstarAI[] ais; /// summary控制目标点更新方式true仅双击鼠标更新false每帧实时更新/summary public bool onlyOnDoubleClick; // 是否启用2D模式寻路/坐标计算 public bool use2D; // 场景主相机 Camera cam; public void Start() { // 缓存主相机避免重复查找 cam Camera.main; // 这种查找所有AI的方式效率偏低但本脚本仅作示例无需优化 // 遗憾的是 FindObjectsOfType 原生不支持直接查找接口类型 // 查找场景所有MonoBehaviour对象筛选出实现IAstarAI接口的对象并转为数组 ais FindObjectsOfTypeMonoBehaviour().OfTypeIAstarAI().ToArray(); // 关闭自动GUI布局 useGUILayout false; } // Unity IMGUI界面绘制/鼠标事件监听方法 public void OnGUI() { // 开启双击模式、相机有效、当前事件为鼠标按下、且点击次数为2双击 if (onlyOnDoubleClick cam ! null Event.current.type EventType.MouseDown Event.current.clickCount 2) { // 更新目标点位置 UpdateTargetPosition(); } } /// summary每帧执行一次/summary void Update() { // 非双击模式 相机存在持续更新目标位置 if (!onlyOnDoubleClick cam ! null) { UpdateTargetPosition(); } } /// summary更新目标点坐标的核心方法/summary public void UpdateTargetPosition() { // 定义新坐标初始化为原点 Vector3 newPosition Vector3.zero; // 标记是否成功获取到有效坐标 bool positionFound false; // 2D模式逻辑 if (use2D) { // 将鼠标屏幕坐标转为世界坐标 newPosition cam.ScreenToWorldPoint(Input.mousePosition); // 2D场景固定Z轴为0 newPosition.z 0; positionFound true; } else { // 3D模式从相机向鼠标位置发射射线射线落点即为目标位置 RaycastHit hit; // 发射射线无限射程仅检测指定层级 if (Physics.Raycast(cam.ScreenPointToRay(Input.mousePosition), out hit, Mathf.Infinity, mask)) { newPosition hit.point; // 赋值射线碰撞点坐标 positionFound true; } } // 成功获取坐标 且 新位置与原位置不一致时更新目标点 if (positionFound newPosition ! target.position) { target.position newPosition; // 双击模式下手动让所有寻路AI重新计算路径 if (onlyOnDoubleClick) { for (int i 0; i ais.Length; i) { if (ais[i] ! null) ais[i].SearchPath(); } } } } }
Unity 2D A*寻路
A* Pathfinding Project的获取A* Pathfinding Project是一个实用的寻路工具包,可在其官网获取免费版A* Pathfinding Project本教程为基于2D样例场景的入门教程, 3D 寻路用法请查看官方文档开始使用网格图 - A*寻路项目 --- Get started with grid graphs - A* Pathfinding Project导入安装包后可查看2D样例场景在样例中,寻路对象会移动到鼠标点击的位置寻路对象以样例为例,寻路对象需要挂载AIPath或AILerp脚本,Seeker脚本随AIPath/Lerp脚本自动添加.区别在于,AIPath 脚本会对路线使用一些平滑效果;AILerp 会精确地沿着路径移动没有任何偏移。AIPath配置参考其中,如果希望寻路对象不可以旋转,请勾选Enable Rotation网格图网格图需要挂载Pathfinder脚本,点击底部的扫描按钮后,场景中可行走区域显示为蓝色可以展开Pathfinder脚本中的Graphs,设置障碍物的Layer层级障碍物1.障碍物需要挂载2D碰撞体组件2.障碍物的层级要和Graphs中保持一致3.障碍物移动、修改后,网格图要重新扫描样例脚本 中文注释参考挂载在寻路对象上的 Al Destination Setterpublic class AIDestinationSetter : VersionedMonoBehaviour { /// summaryAI 需要前往的目标物体/summary public Transform target; // AI寻路接口实例 IAstarAI ai; // 组件启用时执行 void OnEnable() { // 获取当前物体上的AI寻路接口组件 ai GetComponentIAstarAI(); // 在开始寻路前同步更新目标点。 // 理论上仅这一处更新就足够但由于目标点会用于调试也可能被其他脚本调用 // 因此脚本会每帧同步目标位置保证数据始终为最新状态。 if (ai ! null) ai.onSearchPath Update; } // 组件禁用时执行 void OnDisable() { // 移除事件订阅避免报错 if (ai ! null) ai.onSearchPath - Update; } /// summary每帧更新AI的移动目标点/summary void Update() { // 目标物体和AI组件都存在时赋值AI终点坐标 if (target ! null ai ! null) ai.destination target.position; } }挂载在Target上的TargetMoverpublic class TargetMover : MonoBehaviour { /// summary射线检测的层级遮罩仅检测指定层级物体/summary public LayerMask mask; // 被移动的目标点Transform组件 public Transform target; // 场景中所有实现了A*寻路AI接口的对象数组 IAstarAI[] ais; /// summary控制目标点更新方式true仅双击鼠标更新false每帧实时更新/summary public bool onlyOnDoubleClick; // 是否启用2D模式寻路/坐标计算 public bool use2D; // 场景主相机 Camera cam; public void Start() { // 缓存主相机避免重复查找 cam Camera.main; // 这种查找所有AI的方式效率偏低但本脚本仅作示例无需优化 // 遗憾的是 FindObjectsOfType 原生不支持直接查找接口类型 // 查找场景所有MonoBehaviour对象筛选出实现IAstarAI接口的对象并转为数组 ais FindObjectsOfTypeMonoBehaviour().OfTypeIAstarAI().ToArray(); // 关闭自动GUI布局 useGUILayout false; } // Unity IMGUI界面绘制/鼠标事件监听方法 public void OnGUI() { // 开启双击模式、相机有效、当前事件为鼠标按下、且点击次数为2双击 if (onlyOnDoubleClick cam ! null Event.current.type EventType.MouseDown Event.current.clickCount 2) { // 更新目标点位置 UpdateTargetPosition(); } } /// summary每帧执行一次/summary void Update() { // 非双击模式 相机存在持续更新目标位置 if (!onlyOnDoubleClick cam ! null) { UpdateTargetPosition(); } } /// summary更新目标点坐标的核心方法/summary public void UpdateTargetPosition() { // 定义新坐标初始化为原点 Vector3 newPosition Vector3.zero; // 标记是否成功获取到有效坐标 bool positionFound false; // 2D模式逻辑 if (use2D) { // 将鼠标屏幕坐标转为世界坐标 newPosition cam.ScreenToWorldPoint(Input.mousePosition); // 2D场景固定Z轴为0 newPosition.z 0; positionFound true; } else { // 3D模式从相机向鼠标位置发射射线射线落点即为目标位置 RaycastHit hit; // 发射射线无限射程仅检测指定层级 if (Physics.Raycast(cam.ScreenPointToRay(Input.mousePosition), out hit, Mathf.Infinity, mask)) { newPosition hit.point; // 赋值射线碰撞点坐标 positionFound true; } } // 成功获取坐标 且 新位置与原位置不一致时更新目标点 if (positionFound newPosition ! target.position) { target.position newPosition; // 双击模式下手动让所有寻路AI重新计算路径 if (onlyOnDoubleClick) { for (int i 0; i ais.Length; i) { if (ais[i] ! null) ais[i].SearchPath(); } } } } }