Unity3D如何在OnCollisionEnter碰撞判定逻辑中添加等待延迟
解决方案
你之前协程实现失败通常是没有处理重复触发、或者没有做对象判空导致的,以下是可直接运行的修正实现:
using UnityEngine; using System.Collections; public class SwordDetection : MonoBehaviour { // 防重复触发的标记,避免同一碰撞多次执行逻辑 private bool _hasCollided = false; void OnCollisionEnter(Collision collision) { // 优先用CompareTag做标签判断,性能比直接==更好无GC if (collision.gameObject.CompareTag("Enemy") && !_hasCollided) { _hasCollided = true; // 启动协程,传入目标刚体和延迟时长,示例为1秒可自行调整 StartCoroutine(DelayedRemoveConstraints(collision.rigidbody, 1f)); } } IEnumerator DelayedRemoveConstraints(Rigidbody enemyRb, float delay) { // 等待指定时长 yield return new WaitForSeconds(delay); // 必须判空,避免等待过程中敌人对象被销毁导致空引用报错 if (enemyRb != null) { enemyRb.constraints = RigidbodyConstraints.None; } // 如果需要支持后续再次触发碰撞逻辑就保留这行,不需要可以删除 _hasCollided = false; } }
核心注意点
- 协程不会阻塞主线程,
yield return new WaitForSeconds(x)是按游戏时间计时,受Time.timeScale影响,如果需要不受时间缩放的延迟,可以替换为WaitForSecondsRealtime(x) - 布尔标记是必须的,否则剑同时碰到多个碰撞点、或者多个敌人时,会重复执行逻辑
- 如果等待期间持有的刚体对象可能被销毁,必须加判空防护
相关学习技术点
- Unity协程的生命周期与执行规则
- 碰撞检测事件的触发机制与高频触发问题处理
- Unity空引用异常的防护方案
- 游戏时间与真实时间的差异对计时逻辑的影响
替代方案(非协程实现)
如果场景不适合用协程,也可以通过Update计时实现延迟:
using UnityEngine; public class SwordDetection : MonoBehaviour { private bool _isCounting = false; private float _timer; private Rigidbody _targetRb; [SerializeField] private float delayTime = 1f; void OnCollisionEnter(Collision collision) { if (collision.gameObject.CompareTag("Enemy") && !_isCounting) { _isCounting = true; _targetRb = collision.rigidbody; _timer = delayTime; } } private void Update() { if (_isCounting) { _timer -= Time.deltaTime; if (_timer <= 0) { _isCounting = false; if (_targetRb != null) { _targetRb.constraints = RigidbodyConstraints.None; } _targetRb = null; } } } }
内容的提问来源于stack exchange,提问作者Lucas Coates
相关产品推荐
相关产品推荐

