Unity2D的碰撞检测响应处理细节

Table of Contents

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com

Unity中的2D碰撞/触发回调的触发规则遵循一下的规则

详细的触发规则

首先明确两个核心概念的区别:

  • 碰撞(Collision):需要两个Collider2D都勾选Is Trigger = false,且满足物理交互条件
  • 触发(Trigger):至少一个Collider2D勾选Is Trigger = true

1. 碰撞回调(OnCollisionEnter2D/Stay2D/Exit2D)的触发条件

要接收到碰撞回调,必须满足:

  • 两个Collider2D都未勾选Is Trigger
  • 至少其中一个 GameObject拥有 非静态 的Rigidbody2D组件(注意:Rigidbody2D不能设为Kinematic+Is Kinematic且另一个也无Rigidbody2D,这种情况不会触发)
  • 两个Collider2D的Layer层碰撞矩阵允许交互

2. 触发回调(OnTriggerEnter2D/Stay2D/Exit2D)的触发条件

要接收到触发回调,规则更宽松:

  • 至少一个Collider2D勾选Is Trigger
  • 满足以下任一条件即可:
    • 其中一个GameObject有 非静态 的Rigidbody2D(可以是动态/运动学)
    • 其中一个GameObject是 运动的静态物体(Static GameObject,且通过代码主动改变位置/旋转)
    • 注意:两个纯静态(Static)且无Rigidbody2D的物体碰撞,不会触发任何回调

常见场景示例

为了让你更直观理解,这里列出几个典型场景:

场景 A物体(Collider2D) B物体(Collider2D) 是否触发回调
1 有Rigidbody2D(动态) 无Rigidbody2D ✅(碰撞/触发都可)
2 无Rigidbody2D 有Rigidbody2D(动态) ✅(碰撞/触发都可)
3 无Rigidbody2D(静态) 无Rigidbody2D(静态) ❌(无任何回调)
4 有Rigidbody2D(运动学) 无Rigidbody2D ✅(触发可,碰撞需B也有非运动学Rigidbody2D)

关键补充

  1. 回调函数(如OnCollisionEnter2D必须写在有Collider2D的GameObject所挂载的脚本中,且脚本所在的GameObject需满足上述Rigidbody2D条件,否则接收不到回调。
  2. Rigidbody2D的Body Type影响:
    • Dynamic(动态):受物理力影响,是最常用的能触发回调的类型
    • Kinematic(运动学):不受物理力影响,但主动移动时能触发触发回调
    • Static(静态):等同于无Rigidbody2D的静态物体

总结

  1. 核心规则:要接收2D碰撞/触发回调,不能两个物体都没有Rigidbody2D且都是静态的,至少一个物体要有非静态的Rigidbody2D(触发回调允许运动学Rigidbody2D)。
  2. 简化记忆:日常开发中,给需要检测碰撞/触发的物体(或其中一个)挂载Rigidbody2D(动态类型),就能稳定接收到回调。
  3. 触发vs碰撞:触发回调规则更宽松(运动学Rigidbody2D也可),碰撞回调要求更严格(至少一个动态Rigidbody2D)。

3D的Collider和Rigidbody也是遵循一样的规则吗

你问的这个问题很关键,3D的Collider和Rigidbody的碰撞/触发回调规则核心逻辑和2D一致,但在细节上有一些专属的差异,并不是完全一模一样。

3D vs 2D 核心规则对比

先明确最核心的共性,再讲差异:

1. 核心共性(和2D一致)

  • 要接收到OnCollisionEnter/Stay/Exit(碰撞)或OnTriggerEnter/Stay/Exit(触发)回调,不能两个物体都是“纯静态无刚体”
    • 至少一个物体挂载非静态的Rigidbody(3D)/Rigidbody2D(2D);
    • 两个纯静态(Static勾选)且无Rigidbody的物体碰撞,无论是否勾选Is Trigger,都不会触发任何回调

2. 3D独有的关键差异

维度 2D(Rigidbody2D) 3D(Rigidbody)
刚体类型 有3种:Dynamic/Kinematic/Static 只有2种:Dynamic/Kinematic(无Static类型,Static是物体的属性)
静态物体处理 Rigidbody2D设为Static ≈ 无刚体的静态物体 3D中“Static”是GameObject的勾选属性,而非Rigidbody的类型
运动学刚体碰撞规则 Kinematic刚体+无刚体物体,碰撞回调不触发 Kinematic刚体+无刚体物体,碰撞回调也不触发(和2D一致),但触发回调可触发
特殊限制 无额外限制 Rigidbody的Is Kinematic勾选后,若要触发碰撞回调,需开启Collision Detection为Continuous(高版本Unity)
静态碰撞器优化 自动归为静态碰撞器 勾选Static的物体,其Collider会被Unity优化为“静态碰撞器”,不参与物理模拟,仅用于检测

3D碰撞/触发回调的具体规则

1. 碰撞回调(OnCollisionXXX,Is Trigger=false)

触发条件(比2D略严格):

  • 两个Collider都未勾选Is Trigger
  • 至少一个物体挂载Dynamic类型的Rigidbody(3D的Kinematic刚体和无刚体物体碰撞,不会触发碰撞回调);
  • 层碰撞矩阵允许交互。

2. 触发回调(OnTriggerXXX,Is Trigger=true)

触发条件(和2D几乎一致):

  • 至少一个Collider勾选Is Trigger
  • 满足以下任一条件:
    • 其中一个物体有Dynamic/Kinematic类型的Rigidbody;
    • 其中一个静态物体(勾选Static)被代码主动移动/旋转(无Rigidbody也可);
  • 注意:两个纯静态(Static勾选)且无Rigidbody的物体,即使勾选Is Trigger,也不会触发回调。

3D专属的重要补充

  1. Static属性的影响: 3D中GameObject的Static勾选后,其Collider会被Unity标记为“静态碰撞器”,用于烘焙导航网格、优化物理检测,但静态碰撞器无法主动触发碰撞/触发回调,必须靠动态刚体(Dynamic)的物体碰撞它才能触发。
  2. Rigidbody的Sleep状态: 3D的Rigidbody如果处于Sleep(休眠)状态(静止无受力),碰撞检测会被优化,可能暂时接收不到回调,唤醒后恢复(2D也有但3D更明显)。
  3. 碰撞检测模式: 3D的Rigidbody有Collision Detection选项(Discrete/Continuous/Continuous Dynamic),用于解决高速物体穿模问题,2D的Rigidbody2D也有类似但选项更少。

示例:3D常见场景验证

场景 A物体(Collider) B物体(Collider) 是否触发回调
1 有Dynamic Rigidbody 无Rigidbody(Static勾选) ✅(碰撞/触发都可)
2 有Kinematic Rigidbody 无Rigidbody ❌(碰撞)/✅(触发,A主动移动时)
3 无Rigidbody(Static) 无Rigidbody(Static) ❌(无任何回调)

总结

  1. 核心逻辑一致:3D和2D的本质规则相同——“不能两个都是纯静态无刚体”,至少一个物体有非静态刚体才能触发回调。
  2. 关键差异:3D的Rigidbody无Static类型(Static是物体属性),且碰撞回调要求至少一个Dynamic刚体(2D碰撞回调也有此要求,但表述上2D有Static刚体类型易混淆)。
  3. 简化记忆:日常开发中,3D场景给需要检测碰撞/触发的物体挂载Rigidbody(设为Dynamic),和2D一样能稳定接收到回调,无需纠结细节差异。
kumakoko avatar
kumakoko
pure coder
comments powered by Disqus