You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Unity 2D A*寻路项目:如何让AI对象循环巡逻至随机点?

Unity A*寻路:实现敌人随机循环巡逻功能

我之前做迷宫游戏的敌人AI时,刚好也用A*寻路包实现过随机循环巡逻的功能,给你分享下具体的实现思路和代码,应该能解决你的问题:

核心思路

简单来说,就是让敌人不断生成迷宫范围内的可行走随机点,用A寻路到该点,到达后停留片刻再生成下一个目标,循环往复。关键是要确保生成的点是敌人实际能走到的,这里用A自带的寻路数据校验比射线检测更靠谱,当然也可以结合射线检测做双重验证。

具体实现步骤

1. 初始化与随机点生成(带合法性校验)

首先给敌人挂载SeekerAIPath组件(你应该已经按教程配置好了),然后写一个脚本实现巡逻逻辑:

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

火山引擎 最新活动