Unity中Physics.OverlapSphere系列接口无法稳定检测Player的问题求助
Unity中Physics.OverlapSphere系列接口无法稳定检测Player的问题求助
我最近碰到个头疼的Unity Bug:当操控Player反复进出Enemy的sightRadius范围几次后,Enemy就再也没法正确检测到Player了——哪怕Player明明在检测范围内,Enemy也不会去追,只有重启游戏才能恢复正常。这个问题在Unity 2020和2022版本里都能复现。
问题具体表现
- 正常状态下:Player在Enemy的
sightRadius范围内时,FoundPlayer()方法里的numColliders会打印3;Player在范围外时,打印2。 - 异常状态下:多次进出范围后,就算Player回到Enemy的检测范围内,
numColliders只会打印2,Enemy不再识别Player,也不会触发追踪逻辑。
核心检测代码
这是负责检测Player的关键方法:
bool FoundPlayer() { int numColliders = Physics.OverlapSphereNonAlloc(transform.position, sightRadius, colliders); Debug.Log(numColliders); for (int i = 0; i < numColliders; i++) { var target = colliders[i]; if (target.CompareTag("Player")) { attackTarget = target.gameObject; return true; } } attackTarget = null; return false; }
Enemy完整代码
using UnityEngine; using UnityEngine.AI; enum EnemyStatus { GURAD, PATROL, CHASE, DEAD } [RequireComponent(typeof(NavMeshAgent))] [RequireComponent(typeof(BoxCollider))] public class EnemyController : MonoBehaviour { private EnemyStatus enemyStates; private NavMeshAgent agent; private Animator animator; [Header("Basic Settings")] public float sightRadius; private GameObject attackTarget; // 单次检测最多获取10个碰撞体 const int maxColliders = 10; private Collider[] colliders = new Collider[maxColliders]; // 基础移动速度,巡逻/追踪状态会调整 private float speed; // 是否为守卫模式(无目标时原地警戒) public bool isGuard; [Header("Patrol State")] public float patrolRange; private Vector3 wayPoint; private Vector3 centerPosition; // 动画控制参数 bool isWalk; bool isChase; bool isFollow; private void Awake() { agent = GetComponent<NavMeshAgent>(); animator = GetComponent<Animator>(); speed = agent.speed; wayPoint = centerPosition = transform.position; } private void Start() { enemyStates = isGuard ? EnemyStatus.GURAD : EnemyStatus.PATROL; } private void Update() { SwitchStates(); SwitchAnimation(); } void SwitchAnimation() { animator.SetBool("Walk", isWalk); animator.SetBool("ChaseState", isChase); animator.SetBool("Follow", isFollow); } private void SwitchStates() { if (FoundPlayer()) { enemyStates = EnemyStatus.CHASE; } switch(enemyStates) { case EnemyStatus.GURAD: break; case EnemyStatus.PATROL: isChase = false; isFollow = false; if (Vector3.Distance(transform.position, wayPoint) <= agent.stoppingDistance ) { wayPoint = GetNewWayPoint(); agent.destination = wayPoint; agent.speed = speed * 0.5f; isWalk = false; } else { isWalk = true; } break; case EnemyStatus.CHASE: isWalk = false; isChase = true; if (FoundPlayer()) { agent.destination = attackTarget.transform.position; agent.speed = speed; isFollow = true; } else { isFollow = false; agent.destination = transform.position; } break; case EnemyStatus.DEAD: break; } } bool FoundPlayer() { int numColliders = Physics.OverlapSphereNonAlloc(transform.position, sightRadius, colliders); Debug.Log(numColliders); for (int i = 0; i < numColliders; i++) { var target = colliders[i]; if (target.CompareTag("Player")) { attackTarget = target.gameObject; return true; } } attackTarget = null; return false; } Vector3 GetNewWayPoint () { Vector3 wayPoint = new Vector3(centerPosition.x + Random.Range(-patrolRange, patrolRange), centerPosition.y, centerPosition.z + Random.Range(-patrolRange, patrolRange)); NavMeshHit hit; // 采样最近的可导航点,避免巡逻点无法到达 wayPoint = NavMesh.SamplePosition(wayPoint, out hit, patrolRange, 1) ? hit.position : transform.position; return wayPoint; } private void OnDrawGizmosSelected() { Gizmos.color = Color.blue; Gizmos.DrawWireSphere(transform.position, sightRadius); Vector3 size = new Vector3(patrolRange, patrolRange, patrolRange); Gizmos.DrawWireCube(centerPosition, size); } }
相关组件配置
- Player组件:挂载Capsule Collider、Rigidbody,Tag设置为
Player,Layer为Default。 - Plane组件:挂载Mesh Collider,Layer为Default,作为地面使用。
排查到的线索
我试过把OverlapSphereNonAlloc换成OverlapSphere接口,结果问题依然存在。后来偶然发现:只要开启Player的Rigidbody组件上的Use gravity选项,就会触发这个问题;而且Player的transform位置显示正常(站在Plane上),但Rigidbody面板里的Position的y值一直在持续减小,像是在不断往下掉一样。
备注:内容来源于stack exchange,提问作者undefined
相关产品推荐
相关产品推荐

