主要参照 Unity 官方文档的以下几篇文章,重新进行了整理。
https://docs.unity3d.com/Manual/PhysicsOverview.html
https://docs.unity3d.com/Manual/class-Rigidbody2D.html
https://docs.unity3d.com/Manual/class-Rigidbody.html
Unity 物理系统中,刚体用于接受各种力的作用,具有速度,来控制物体的移动。
碰撞体用于各个物体之间的交互、碰撞,从而影响物体的移动。
刚体通常和碰撞体一起使用,模拟现实中的世界。
刚体
- 会受到重力等力的作用,而产生移动,但是不会发生形变。
- 加了刚体的物体,不应该通过 Transform 来 move、rotate、scale。应该通过 Rigidbody.MovePosition、Rigidbody.MoveRotation、Rigidbody2D.MovePosition、Rigidbody2D.MoveRotation 来移动。
刚体类型 BodyType
刚体类型是刚体的一个重要属性。
- 决定移动的行为(位置、翻转)
- (如果有碰撞体组件的话)决定碰撞交互的方式
- 改变 BodyType 是一个很消耗性能的操作
动态 Dynamic
- 默认类型
- 受重力和附加力的影响,进而改变速度。
- 性能消耗最高的类型。
- 可通过 MovePosition、MoveRotation 来移动。
- 可通过 velocity 来改变速度。
-
运动学 Kinematic
不受力的影响。
- 性能消耗比 Dynamic 少,比 Static 多。
- 可通过 MovePosition MoveRotation 来移动。
- 可通过 velocity 来改变速度。
-
静态 Static
不受力的影响,物理系统不会对该物体进行计算。
- 性能消耗最低的类型。
- 不可通过 MovePosition MoveRotation 来移动。
- 不可通过 velocity 来改变速度。
- 用来模拟从不移动的物体。
在 Physics2D 中设置刚体类型
Physics2D 中 Rigidbody2D 组件有 BodyType 属性,没有 IsKinematic 属性。
- Dynamic:添加 Rigidbody2D,设置 BodyType 为 Dynamic。
- Kinematic:添加 Rigidbody2D,设置 BodyType 为 Kinematic。
Static:
Dynamic:添加 Rigidbody,不勾选 IsKinematic。
- Kinematic:添加 Rigidbody,勾选 IsKinematic。
- Static:不添加 Rigidbody,但是有 Collider 组件。
碰撞体
- 会发生碰撞,并因为碰撞而移动。
- 定义 GameObject 的形状以用于碰撞检测,会触发相应的碰撞体回调函数。
- 碰撞体是不可见的,碰撞体的形状不用和实际的网格(mesh)形状一致。
与 3 种类型的刚体对应,碰撞体根据添加的刚体类型,也有 3 种类型的碰撞体。
静止刚体的碰撞体 Static Rigidbody Collider
- 有碰撞体
- 没有刚体
- 或者刚体类型为 Static。
- 不受力和碰撞的影响
- 可以和其他碰撞体发生碰撞,但是自己不会移动。物理系统会做优化。
- 游戏过程中尽量避免 enable、disable、move、scale,否则会有大的性能消耗,甚至出现错误。
如果大部分时候是静止的,但是某些情况下需要移动,那么应该使用 Kinematic Rigidbody Collider。
动态刚体的碰撞体 Dynamic Rigidbody Collider
有碰撞体,有刚体,刚体类型是 Dynamic。
-
运动学刚体的碰撞体 Kinematic Rigidbody Collider
有碰撞体,有刚体,刚体类型是 Kinematic。
- 可以通过 Transform 来移动位置
- 不受力和碰撞的影响
- 偶尔会被 move、enable、disable,大多数时候和 Static Collider 一致。
触发器
- 碰撞体勾选 isTrigger 后成为触发器
- 与碰撞体的主要区别
- 其他碰撞体可以穿过该(触发器)碰撞体,不会受到阻挡。
- 穿过该碰撞体时,会触发相应的触发器回调函数。
- 与 3 种类型的碰撞体对应,勾选 isTrigger 后对应 3 种类型的触发器。
碰撞体碰撞规则
- Dynamic 刚体的碰撞体和其他碰撞体,会有回调。
Collision detection occurs and messages are sent upon collision | ||||||
---|---|---|---|---|---|---|
Static Rigidbody Collider | Dynamic Rigidbody Collider | Kinematic Rigidbody Collider | Static Rigidbody Trigger Collider | Dynamic Rigidbody Trigger Collider | Kinematic Rigidbody Trigger Collider | |
Static Rigidbody Collider | Y | |||||
Dynamic Rigidbody Collider | Y | Y | Y | |||
Kinematic Rigidbody Collider | Y | |||||
Static Rigidbody Trigger Collider | ||||||
Dynamic Rigidbody Trigger Collider | ||||||
Kinematic Rigidbody Trigger Collider |
碰撞体相关回调函数
- MonoBehaviour
- OnCollisionEnter2D(Collider2D)
- OnCollisionStay2D(Collider2D)
- OnCollisionExit2D(Collider2D)
- OnCollisionEnter(Collider)
- OnCollisionStay(Collider)
- OnCollisionExit(Collider)
触发器触发规则
- Dynamic、Kinematic 刚体的触发器,和任何碰撞体、触发器都会有回调。
- Static 刚体的触发器碰撞体,只能和 Dynamic、Kinematic 刚体的碰撞体、触发器有回调。
Trigger messages are sent upon collision | ||||||
---|---|---|---|---|---|---|
Static Rigidbody Collider | Dynamic Rigidbody Collider | Kinematic Rigidbody Collider | Static Rigidbody Trigger Collider | Dynamic Rigidbody Trigger Collider | Kinematic Rigidbody Trigger Collider | |
Static Rigidbody Collider | Y | Y | ||||
Dynamic Rigidbody Collider | Y | Y | Y | |||
Kinematic Rigidbody Collider | Y | Y | Y | |||
Static Rigidbody Trigger Collider | Y | Y | Y | Y | ||
DynamicRigidbody Trigger Collider | Y | Y | Y | Y | Y | Y |
Kinematic Rigidbody Trigger Collider | Y | Y | Y | Y | Y | Y |
触发器相关回调函数
- MonoBehaviour
- OnTriggerEnter2D(Collider2D)
- OnTriggerStay2D(Collider2D)
- OnTriggerExit2D(Collider2D)
- OnTriggerEnter(Collider)
- OnTriggerStay(Collider)
- OnTriggerExit(Collider)
其他细节
休眠
- 当刚体移动速度小于一个特定值后,就会进入休眠状态(Sleeping)。以降低性能消耗。
- 休眠状态下,
- 不会参与物理系统的计算。
- 发生碰撞或者受到力的作用,会重新参与物理系统的计算。
- 如果有静态碰撞体通过 Transform 来移动,并接触/离开一个 Sleeping 的刚体,该刚体不会重新参与计算,可能会悬浮在空中,发生不可预知的错误。此时需要通过 WakeUp 来唤醒。理论上不应该移动静态碰撞体,也就不会出现这种情况。