一、物理响应函数(碰撞检测)
用于处理刚体间的物理碰撞,要求双方均有 Collider,且至少一方有 Rigidbody。双方 Collider 均不能勾选 Is Trigger
。
OnCollisionEnter(Collision collision)
- 触发时机:碰撞发生的第一帧(接触瞬间)
- 典型场景:球撞击地面时播放音效
void OnCollisionEnter(Collision collision) { if (collision.gameObject.tag == "Ground") { PlaySound("impact"); } }
OnCollisionStay(Collision collision)
- 触发时机:碰撞持续期间每帧调用(除首尾帧)
- 典型场景:物体在斜坡上滑动时持续施加摩擦力
void OnCollisionStay(Collision collision) { ApplyFriction(collision.contacts[0].normal); }
OnCollisionExit(Collision collision)
- 触发时机:碰撞结束的分离瞬间
- 典型场景:玩家离开平台时取消特殊状态
void OnCollisionExit(Collision collision) { if (collision.gameObject.name == "MovingPlatform") { player.ResetState(); } }
二、触发器响应函数
用于检测物体进入特定区域,要求:
- 至少一方 Collider 勾选
Is Trigger
- 至少一方有 Rigidbody(可为 Kinematic)
OnTriggerEnter(Collider other)
- 触发时机:另一物体进入触发器区域的第一帧
- 典型场景:玩家拾取道具
void OnTriggerEnter(Collider other) { if (other.CompareTag("Coin")) { Destroy(other.gameObject); // 销毁金币 AddCoins(1); } }
OnTriggerStay(Collider other)
- 触发时机:物体停留在触发器内每帧调用
- 典型场景:持续区域伤害(如毒圈)
void OnTriggerStay(Collider other) { if (other.CompareTag("Player")) { other.GetComponent<Player>().TakeDamage(1); // 每帧扣血 } }
OnTriggerExit(Collider other)
- 触发时机:物体离开触发器区域的第一帧
- 典型场景:离开安全区警告
void OnTriggerExit(Collider other) { if (other.CompareTag("Player")) { ShowWarning("离开安全区域!"); } }
三、触发条件对比分析
条件 | 碰撞响应 (OnCollision* ) |
触发器响应 (OnTrigger* ) |
---|---|---|
Collider 要求 | 双方均非 Trigger | 至少一方为 Trigger |
Rigidbody 要求 | 至少一方有 Rigidbody | 至少一方有 Rigidbody |
物理效果 | 产生物理力(反弹/摩擦) | 无物理效果(直接穿透) |
性能消耗 | 较高(需计算物理反馈) | 较低(仅检测重叠) |
典型应用场景 | 物理交互(弹跳、推箱子) | 逻辑检测(收集品、陷阱) |
四、关键注意事项
刚体运动类型影响
- Kinematic Rigidbody:可触发碰撞/触发器事件,但不受物理力影响
- Dynamic Rigidbody:参与完整物理模拟
静态碰撞体限制
- 无 Rigidbody 的静态 Collider 可参与碰撞,但无法触发
OnTriggerEnter
等事件
- 无 Rigidbody 的静态 Collider 可参与碰撞,但无法触发
执行顺序
所有物理响应均在FixedUpdate()
后执行,与渲染帧无关优化建议
- 避免在
Stay
函数中执行复杂计算 - 使用 Layer 过滤不必要的碰撞检测:
void OnCollisionEnter(Collision collision) { if (collision.gameObject.layer != LayerMask.NameToLayer("Enemy")) return; // 跳过非敌人层 }
- 避免在
通过合理选择碰撞/触发器响应,可高效实现物理交互与游戏逻辑检测。