Unity中Physics.OverlapBox导致列表重复添加Target问题求助
问题排查与解决方案
你的问题核心是Update方法每帧都会执行一次TrySelectTarget,每次执行都会重新检测到那2个Target,然后重复添加到availableTargets列表里,所以列表会积累大量重复实例。
方案1:每次检测前清空列表(最简单直接)
在获取碰撞体数组前,先清空availableTargets,这样每帧的列表都是当前范围内的最新目标,不会有重复:
private void TrySelectTarget(bool switchInput) { availableTargets.Clear(); // 清空旧列表 targetArray = Physics.OverlapBox(transform.position, range, Quaternion.identity, targetLayer, QueryTriggerInteraction.Ignore); for (int i = 0; i < targetArray.Length ; i++) { if (targetArray[i].TryGetComponent<Target>(out Target target)) { availableTargets.Add(target); } } }
方案2:添加前检查目标是否已存在
如果不想清空列表(比如需要保留历史目标但避免重复),可以在添加前判断目标是否已经在列表中:
private void TrySelectTarget(bool switchInput) { targetArray = Physics.OverlapBox(transform.position, range, Quaternion.identity, targetLayer, QueryTriggerInteraction.Ignore); for (int i = 0; i < targetArray.Length ; i++) { if (targetArray[i].TryGetComponent<Target>(out Target target)) { // 仅当目标不在列表中时添加 if (!availableTargets.Contains(target)) { availableTargets.Add(target); } } } }
注意:这种方式需要额外处理目标离开范围后从列表移除的逻辑,否则列表会一直保留已经离开的目标。
方案3:用触发器事件替代每帧检测(更高效)
如果你的玩家对象有Collider(设置为Is Trigger)和Rigidbody(必须添加,否则触发器不生效),可以用OnTriggerEnter和OnTriggerExit事件来监听目标的进入和离开,自动添加/移除,不需要每帧调用检测:
private void OnTriggerEnter(Collider other) { // 检查是否是目标层且带有Target组件 if (other.gameObject.layer == targetLayer && other.TryGetComponent<Target>(out Target target)) { if (!availableTargets.Contains(target)) { availableTargets.Add(target); } } } private void OnTriggerExit(Collider other) { if (other.TryGetComponent<Target>(out Target target)) { availableTargets.Remove(target); } }
这种方式性能更好,因为只有当目标进入/离开范围时才会触发逻辑,不用每帧执行检测。
内容的提问来源于stack exchange,提问作者ImposterDev
相关产品推荐
相关产品推荐

