You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中如何实现Navmesh Agent追踪最近玩家及多玩家适配

Unity NavMesh Agent 多玩家追踪实现方案

原代码存在两个核心问题:一是GameObject.FindWithTag("Player")仅会返回第一个匹配标签的玩家对象,无法适配多玩家场景;二是每帧调用Find方法会额外消耗性能。以下是针对两个问题的具体解决方案:

一、实现追踪最近玩家的逻辑

  1. 维护当前活跃玩家的列表,避免每帧重复查找玩家对象
  2. 遍历玩家列表,计算每个玩家与敌人的距离,筛选出距离最近的目标
  3. 将最近玩家的位置设置为NavMesh Agent的导航目标

二、适配多玩家的完整追踪逻辑

除了筛选最近玩家,还需要处理目标玩家离开场景(被销毁/切换场景)的情况:

  • 每帧检查当前追踪目标是否有效,若无效则重新选择最近玩家
  • 通过手动调用或事件监听的方式,实时更新活跃玩家列表

修改后的完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class EnemyFollow : MonoBehaviour
{
    private NavMeshAgent navMeshAgent;
    // 存储当前活跃的玩家对象
    private List<Transform> playerTransforms = new List<Transform>();
    // 当前追踪的目标玩家
    private Transform currentTarget;

    private void Awake()
    {
        navMeshAgent = GetComponent<NavMeshAgent>();
        // 初始化获取所有玩家
        UpdatePlayerList();
    }

    private void Update()
    {
        if (playerTransforms.Count == 0) return;

        // 如果当前目标为空或者已被销毁,重新选择最近玩家
        if (currentTarget == null)
        {
            currentTarget = FindClosestPlayer();
        }

        // 更新导航目标
        navMeshAgent.destination = currentTarget.position;
    }

    // 更新玩家列表,可在玩家加入/离开时调用
    public void UpdatePlayerList()
    {
        playerTransforms.Clear();
        GameObject[] players = GameObject.FindGameObjectsWithTag("Player");
        foreach (GameObject player in players)
        {
            playerTransforms.Add(player.transform);
        }
    }

    // 寻找距离最近的玩家
    private Transform FindClosestPlayer()
    {
        Transform closestPlayer = null;
        float closestDistance = Mathf.Infinity;
        Vector3 enemyPosition = transform.position;

        foreach (Transform player in playerTransforms)
        {
            if (player == null) continue;

            float distance = Vector3.Distance(enemyPosition, player.position);
            if (distance < closestDistance)
            {
                closestDistance = distance;
                closestPlayer = player;
            }
        }

        return closestPlayer;
    }

    // 可选:监听玩家销毁事件,实时更新列表
    private void OnEnable()
    {
        // 假设玩家对象销毁时会触发自定义事件,可根据游戏逻辑调整
        // Player.OnPlayerDestroyed += UpdatePlayerList;
    }

    private void OnDisable()
    {
        // Player.OnPlayerDestroyed -= UpdatePlayerList;
    }
}

代码关键点说明

  • 用List<Transform>缓存活跃玩家,避免每帧调用FindGameObjectsWithTag带来的性能损耗
  • FindClosestPlayer方法通过遍历计算距离,精准筛选出最近的玩家目标
  • 每帧校验当前目标的有效性,确保目标玩家离开后能自动切换追踪对象
  • 提供UpdatePlayerList方法,可结合玩家加入/离开的游戏逻辑手动调用,或通过事件监听实现自动更新

内容的提问来源于stack exchange,提问作者BlastHardCheese

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 01:37:40