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

Unity C# 如何让NPC鱼不在玩家身上或过近位置生成

问题根因

你的NPC鱼生成在玩家身上的核心问题是Start方法执行顺序写反:

  • 你在Start中先调用了Spawn()方法,之后才给minDistance赋值为5f
  • C#中float值类型默认值为0,Spawn()运行时minDistance实际等于0,判断条件两点距离 < 0永远不可能成立,用于过滤过近生成点的while循环完全不会执行,生成点完全随机,自然会刷在玩家位置。

代码另外还有3个问题:

  • quaternion.identity拼写错误,Unity四元数类名首字母需大写,正确写法为Quaternion.identity,会直接导致编译不通过
  • 每次循环都调用GameObject.FindGameObjectWithTag("Player")查找玩家,存在不必要的性能开销,玩家未及时加载时还会触发空引用报错
  • while循环没有设置重试上限,若玩家位置覆盖了绝大多数生成区域,循环会无限运行导致游戏卡死
  • 距离计算混用Vector2和Vector3类型,写法不严谨
修正后完整代码
public class Spawner : MonoBehaviour
{
    [Header("生成配置")]
    public GameObject[] itemsToPickFrom;
    public int numberToSpawn;
    public float minDistance = 5f; // 直接在字段处初始化,避免执行顺序错误

    private Transform _playerTrans;
    // 生成范围常量,方便统一调整
    private const float RangeMinX = -10f;
    private const float RangeMaxX = 9f;
    private const float RangeMinY = -4f;
    private const float RangeMaxY = 4f;
    private const int MaxRetry = 50; // 最大重试次数,防止死循环

    void Start()
    {
        // 启动时一次性缓存玩家位置引用,不用每次生成都查找
        _playerTrans = GameObject.FindGameObjectWithTag("Player").transform;
        Spawn();
    }
 
    void Spawn()
    {
        for (int i = 0; i < numberToSpawn; i++)
        {
            int randomFishIndex = Random.Range(0, itemsToPickFrom.Length);
            Vector3 spawnPos = Vector3.zero;
            bool findValidPos = false;
            int retryCount = 0;

            while (retryCount < MaxRetry)
            {
                float randX = Random.Range(RangeMinX, RangeMaxX);
                float randY = Random.Range(RangeMinY, RangeMaxY);
                spawnPos = new Vector3(randX, randY, 0);
                // 统一用Vector3计算距离,避免隐式类型转换
                if (Vector3.Distance(_playerTrans.position, spawnPos) >= minDistance)
                {
                    findValidPos = true;
                    break;
                }
                retryCount++;
            }

            // 找到合法位置才生成鱼,重试超限则跳过该次生成,避免卡死
            if (findValidPos)
            {
                Instantiate(itemsToPickFrom[randomFishIndex], spawnPos, Quaternion.identity);
            }
        }
    }
}
优化说明
  • 把minDistance设为可在Inspector面板直接调整的公开字段,后续改距离不用修改代码
  • 启动时一次性缓存玩家Transform组件,减少重复查找的性能消耗
  • 增加最大重试次数兜底,彻底避免while死循环导致的游戏无响应
  • 统一距离计算的向量类型,消除隐式转换的不稳定问题
  • 生成范围抽成常量,后续调整地图边界不用逐行找数值修改

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:09:19