Unity 2D A*寻路项目:如何让AI对象循环巡逻至随机点?
Unity A*寻路:实现敌人随机循环巡逻功能
我之前做迷宫游戏的敌人AI时,刚好也用A*寻路包实现过随机循环巡逻的功能,给你分享下具体的实现思路和代码,应该能解决你的问题:
核心思路
简单来说,就是让敌人不断生成迷宫范围内的可行走随机点,用A寻路到该点,到达后停留片刻再生成下一个目标,循环往复。关键是要确保生成的点是敌人实际能走到的,这里用A自带的寻路数据校验比射线检测更靠谱,当然也可以结合射线检测做双重验证。
具体实现步骤
1. 初始化与随机点生成(带合法性校验)
首先给敌人挂载Seeker和AIPath组件(你应该已经按教程配置好了),然后写一个脚本实现巡逻逻辑:
using Pathfinding; using UnityEngine; using System.Collections; public class EnemyRandomPatrol : MonoBehaviour { private AIPath _aiPath; private GridGraph _gridGraph; void Start() { _aiPath = GetComponent<AIPath>(); // 获取场景中的GridGraph(如果有多个Graph,要指定对应实例) _gridGraph = AstarPath.active.data.gridGraph; // 启动巡逻循环 StartCoroutine(ContinuousPatrol()); } // 生成迷宫范围内的可行走随机点 private Vector3 GenerateValidRandomPoint() { Vector3 randomPoint; do { // 在GridGraph的边界内生成随机坐标 float randomX = Random.Range(_gridGraph.bounds.min.x, _gridGraph.bounds.max.x); float randomZ = Random.Range(_gridGraph.bounds.min.z, _gridGraph.bounds.max.z); randomPoint = new Vector3(randomX, transform.position.y, randomZ); // 用A*的API判断该点是否在可行走网格上 GraphNode targetNode = AstarPath.active.GetNearest(randomPoint).node; } while (!PathUtilities.IsPathable(targetNode)); // 直到找到合法点 return randomPoint; }
如果你坚持要用射线检测(比如需要确认点在地面上),可以加个辅助校验函数:
// 射线检测验证点是否在可行走地面 private bool IsPointOnWalkableGround(Vector3 point) { if (Physics.Raycast(point + Vector3.up * 2f, Vector3.down, out RaycastHit hit, 4f)) { // 替换成你迷宫地面的Layer名称 return hit.collider.gameObject.layer == LayerMask.NameToLayer("Ground"); } return false; }
然后在生成点的循环里加上这个判断即可。
2. 循环巡逻逻辑
用协程实现持续的巡逻流程,让敌人到达目标后自动切换下一个点:
private IEnumerator ContinuousPatrol() { while (true) { // 获取合法随机目标点 Vector3 target = GenerateValidRandomPoint(); // 设置A*寻路目标 _aiPath.destination = target; // 等待敌人到达目标(加超时防止寻路失败卡住) float waitTimer = 0f; float maxWaitTime = 10f; // 可根据你的游戏节奏调整 while (!_aiPath.reachedEndOfPath && waitTimer < maxWaitTime) { waitTimer += Time.deltaTime; yield return null; } // 到达目标后停留随机时长,再继续巡逻 yield return new WaitForSeconds(Random.Range(0.5f, 2f)); } } }
3. 实用优化建议
- 限制巡逻范围:如果不想让敌人跑遍整个迷宫,可以在生成随机点时,限制在敌人当前位置的一定半径内,比如用
Random.insideUnitSphere * patrolRadius来生成局部随机点 - 动态障碍物适配:如果迷宫有可移动的障碍物,记得在障碍物移动后调用
AstarPath.active.Scan()更新寻路网格(注意不要频繁调用,避免性能问题) - 更灵活的到达判断:如果
reachedEndOfPath判断不够精准,可以改用_aiPath.remainingDistance < 0.5f来判断敌人是否接近目标
关于你提到的未解决问题
你说当前还有个未解决的问题,但没具体说明是什么。如果是寻路卡顿、目标点不可达、巡逻逻辑异常这类情况,可以补充下具体现象和相关代码片段,这样能更精准地帮你排查~
内容的提问来源于stack exchange,提问作者user1656528




