碰撞体组件可定义用于物理碰撞的游戏对象的形状。碰撞体是不可见的,其形状不需要与游戏对象的网格完全相同。网格的粗略近似方法通常更有效,在游戏运行过程中难以察觉。
最简单(并且也是处理器开销最低)的碰撞体是__原始__碰撞体类型。在 3D 中,这些碰撞体为盒型碰撞体、球形碰撞体和胶囊碰撞体。在 2D 中,可以使用 2D 盒型碰撞体 和 2D 圆形碰撞体。可以将任意数量的上述碰撞体添加到单个游戏对象以创建__复合碰撞体__。
复合碰撞体可以模拟游戏对象的形状,同时保持较低的处理器开销。为了获得更多灵活性,可以在子游戏对象上添加额外的碰撞体。例如,可以相对于父游戏对象的本地轴来旋转盒体。在创建像这样的复合碰撞体时,层级视图中的根游戏对象上应该只使用一个刚体组件。
原始碰撞体无法正常处理剪切变换。如果在变换层级视图中组合使用旋转和非均匀比例,从而使产生的形状不再是原始形状,则原始碰撞体无法正确表示这个形状。
然而,在某些情况下,即使复合碰撞体也不够准确。在 3D 中,可以使用网格碰撞体精确匹配游戏对象网格的形状。在 2D 中,2D 多边形碰撞体不能完美匹配精灵图形的形状,但您可以将形状细化到所需的任何细节级别。
这些碰撞体比原始类型具有更高的处理器开销,因此请谨慎使用以保持良好的性能。此外,网格碰撞体无法与另一个网格碰撞体碰撞(即,当它们进行接触时不会发生任何事情)。在某些情况下,可以通过在 Inspector 中将网格碰撞体标记为 Convex 来解决此问题。此设置会产生“凸面外壳”形式的碰撞体形状,类似于原始网格,但填充了底切。
这样做的好处是,凸面网格碰撞体可与其他网格碰撞体碰撞,因此,当有一个包含合适形状的移动角色时,便可以使用此功能。但是,一条适用的规则是将网格碰撞体用于场景几何体,并使用复合原始碰撞体近似得出移动游戏对象的形状。
可将碰撞体添加到没有刚体组件的游戏对象,从而创建场景的地板、墙壁和其他静止元素。这些被称为_静态_碰撞体。相反,具有刚体的游戏对象上的碰撞体称为_动态_碰撞体。静态碰撞体可与动态碰撞体相互作用,但由于没有刚体,因此不会通过移动来响应碰撞。
当碰撞体相互作用时,它们的表面需要模拟所应代表的材质的属性。例如,一块冰将是光滑的,而橡胶球将提供大量摩擦力并且弹性很好。虽然碰撞时碰撞体的形状不会变形,但可以使用 Physics Materials(物理材质)__配置碰撞体的摩擦力和弹力。可能需要进行多次试验和纠错后才能获得正确参数,比如冰材质将具有零(或非常低的)摩擦力,而橡胶材质则具有高摩擦力和近乎完美的弹性。有关可用参数的更多详细信息,请参阅物理材质和 2D 物理材质的参考页面。请注意,由于历史原因,3D 资源实际上称为 Physic Material(物理材质)__(_不带_ s),而等效的 2D 资源则称为 _Physics Material 2D(2D 物理材质)__(_带 s)。
脚本系统可以使用 OnCollisionEnter
函数检测何时发生碰撞并启动操作。但是,也可以直接使用物理引擎检测碰撞体何时进入另一个对象的空间而不会产生碰撞。配置为__触发器__(使用 Is Trigger 属性)的碰撞体不会表现为实体对象,只会允许其他碰撞体穿过。当碰撞体进入其空间时,触发器将在触发器对象的脚本上调用 OnTriggerEnter
函数。
发生碰撞时,物理引擎会在附加到相关对象的所有脚本上调用特定名称的函数。可以在这些函数中放置所需的任何代码来响应碰撞事件。例如,当汽车撞到障碍物时,可以播放碰撞音效。
在第一个检测到碰撞的物理更新中,将调用 OnCollisionEnter
函数。在保持接触的更新期间,将调用 OnCollisionStay
,最后由 OnCollisionExit
指示接触已经中断。触发碰撞体会调用模拟的 OnTriggerEnter
、OnTriggerStay
和 OnTriggerExit
函数。请注意,对于 2D 物理,可使用在名称中附加了 2D 字样的等效函数,例如 OnCollisionEnter2D
。有关这些函数和代码示例的完整详细信息,请参阅关于 MonoBehaviour 类的脚本参考页面。
对于正常的非触发碰撞,还有一个额外的细节,即所涉及的对象中至少有一个对象必须具有非运动刚体(即,必须关闭 _Is Kinematic_)。如果两个对象都是运动刚体,则不会调用 OnCollisionEnter
等函数。对于触发碰撞,此限制不适用,因此运动和非运动刚体都会在进入触发碰撞体时提示调用 OnTriggerEnter
。
碰撞体彼此之间的相互作用根据刚体组件的配置不同而不同。三个重要的配置是_静态碰撞体 (Static Collider)(即完全没有附加任何刚体)、刚体碰撞体 (Rigidbody Collider)_ 和_运动刚体碰撞体 (Kinematic Rigidbody Collider)_。
静态碰撞体是具有碰撞体而没有刚体的游戏对象。静态碰撞体在大多数情况下用于表示始终停留在同一个地方而永远不会四处移动的关卡几何体。靠近的刚体对象会与静态碰撞体发生碰撞,但不会移动静态碰撞体。
在特殊情况下,物理引擎针对永远不会移动的静态碰撞体进行优化。例如,即使您移动静态碰撞体,停在静态碰撞体上的车辆也会保持睡眠状态。您可以在运行时启用、禁用或移动静态碰撞体,而不会特别影响物理引擎的计算速度。另外,只要缩放比例是统一的(无偏差),就可以安全地缩放静态网格碰撞体。
这是一种附加了碰撞体和普通非运动刚体的游戏对象。刚体碰撞体完全由物理引擎模拟,并可响应通过脚本施加的碰撞和力。刚体碰撞体可与其他对象(包括静态碰撞体)碰撞,是使用物理组件的游戏中最常用的碰撞体配置。
这是一种附加了碰撞体和_运动_刚体(即启用了刚体的 IsKinematic 属性)的游戏对象。可使用脚本来移动运动刚体对象(通过修改对象的变换组件),但该对象不会像非运动刚体一样响应碰撞和力。运动刚体应该用于符合以下特征的碰撞体:偶尔可能被移动或禁用/启用,除此之外的行为应该像静态碰撞体一样。这方面的一个例子是滑动门,这种门通常用作不可移动的物理障碍物,但必要时可以打开。与静态碰撞体不同,移动的运动刚体会对其他对象施加摩擦力,并在双方接触时“唤醒”其他刚体。
即使处于不动状态,运动刚体碰撞体也会对静态碰撞体产生不同的行为。例如,如果将碰撞体设置为触发器,则还需要向其添加刚体以便在脚本中接收触发器事件。如果不希望触发器在重力作用下跌落或在其他方面受物理影响,则可以在其刚体上设置 IsKinematic 属性。
可使用 IsKinematic 属性随时让刚体组件在正常和运动行为之间切换。
这方面的一个常见例子是“布娃娃”效果;在这种效果中,角色通常在动画下移动,但在爆炸或猛烈碰撞时被真实抛出。角色的四肢可被赋予自己的刚体组件,并在默认情况下启用 IsKinematic。肢体将通过动画正常移动,直到所有这些肢体关闭 IsKinematic 为止,然后它们立即表现为物理对象。此时,碰撞或爆炸力将使角色飞出,使肢体以令人信服的方式被抛出。
当两个对象碰撞时,可能会发生许多不同的脚本事件,具体取决于碰撞对象的刚体配置。以下图表详细列出了根据附加到对象的组件来调用的事件函数。某些组合仅会使两个对象之中的一个对象受到碰撞的影响,但一般规则是物理特性不会应用于没有附加刚体组件的对象。
发生碰撞检测并在碰撞后发送消息 | ||||||
---|---|---|---|---|---|---|
静态碰撞体 | 刚体碰撞体 | 运动刚体碰撞体 | 静态触发碰撞体 | 刚体触发碰撞体 | 运动刚体触发碰撞体 | |
静态碰撞体 | 是 | |||||
刚体碰撞体 | 是 | 是 | 是 | |||
运动刚体碰撞体 | 是 | |||||
静态触发碰撞体 | ||||||
刚体触发碰撞体 | ||||||
运动刚体触发碰撞体 |
碰撞后发送触发器消息 | ||||||
---|---|---|---|---|---|---|
静态碰撞体 | 刚体碰撞体 | 运动刚体碰撞体 | 静态触发碰撞体 | 刚体触发碰撞体 | 运动刚体触发碰撞体 | |
静态碰撞体 | 是 | 是 | ||||
刚体碰撞体 | 是 | 是 | 是 | |||
运动刚体碰撞体 | 是 | 是 | 是 | |||
静态触发碰撞体 | 是 | 是 | 是 | 是 | ||
刚体触发碰撞体 | 是 | 是 | 是 | 是 | 是 | 是 |
运动刚体触发碰撞体 | 是 | 是 | 是 | 是 | 是 | 是 |