Version: 2023.1
Collision
连续碰撞检测 (CCD)

Introduction to collision

Unity handles collision between GameObjects with colliders, which attach to GameObjects and define the shape of a GameObject for the purposes of physical collisions. A collider is invisible, and does not need to be the exact same shape as the GameObject’s mesh. A rough approximation of the mesh is often more efficient and indistinguishable in gameplay.

最简单(并且也是处理器开销最低)的碰撞体是__原始__碰撞体类型。在 3D 中,这些碰撞体为盒型碰撞体球形碰撞体胶囊碰撞体。在 2D 中,可以使用 2D 盒型碰撞体2D 圆形碰撞体。可以将任意数量的上述碰撞体添加到单个游戏对象以创建__复合碰撞体__。

复合碰撞体

复合碰撞体可以模拟游戏对象的形状,同时保持较低的处理器开销。为了获得更多灵活性,可以在子游戏对象上添加额外的碰撞体。例如,可以相对于父游戏对象的本地轴来旋转盒体。在创建像这样的复合碰撞体时,层级视图中的根游戏对象上应该只使用一个刚体组件。

原始碰撞体无法正常处理剪切变换。如果在变换层级视图中组合使用旋转和非均匀比例,从而使产生的形状不再是原始形状,则原始碰撞体无法正确表示这个形状。

网格碰撞体

然而,在某些情况下,即使复合碰撞体也不够准确。在 3D 中,可以使用网格碰撞体精确匹配游戏对象网格的形状。在 2D 中,2D 多边形碰撞体不能完美匹配精灵图形的形状,但您可以将形状细化到所需的任何细节级别。

这些碰撞体比原始类型具有更高的处理器开销,因此请谨慎使用以保持良好的性能。此外,网格碰撞体无法与另一个网格碰撞体碰撞(即,当它们进行接触时不会发生任何事情)。在某些情况下,可以通过在 Inspector 中将网格碰撞体标记为 Convex 来解决此问题。此设置会产生“凸面外壳”形式的碰撞体形状,类似于原始网格,但填充了底切。

这样做的好处是,凸面网格碰撞体可与其他网格碰撞体碰撞,因此,当有一个包含合适形状的移动角色时,便可以使用此功能。但是,一条适用的规则是将网格碰撞体用于场景几何体,并使用复合原始碰撞体近似得出移动游戏对象的形状。

静态碰撞体

可将碰撞体添加到没有刚体组件的游戏对象,从而创建场景的地板、墙壁和其他静止元素。这些被称为_静态_碰撞体。相反,具有刚体的游戏对象上的碰撞体称为_动态_碰撞体。静态碰撞体可与动态碰撞体相互作用,但由于没有刚体,因此不会通过移动来响应碰撞。

物理材质

When colliders interact, their surfaces need to simulate the properties of the material they are supposed to represent. For example, a sheet of ice will be slippery while a rubber ball will offer a lot of friction and be very bouncy. Although the shape of colliders is not deformed during collisions, their friction and bounce can be configured using Physics Materials. Getting the parameters just right can involve a bit of trial and error. A slippery material like ice, for example, has zero (or very low) friction. A grippy material like rubber has high friction and near-perfect bounciness. See the reference pages for Physic Material and Physics Material 2D for further details on the available parameters. Note that for historical reasons, the 3D asset is actually called Physic Material (without the S) but the 2D equivalent is called Physics Material 2D (with the S).

触发器

脚本系统可以使用 OnCollisionEnter 函数检测何时发生碰撞并启动操作。但是,也可以直接使用物理引擎检测碰撞体何时进入另一个对象的空间而不会产生碰撞。配置为__触发器__(使用 Is Trigger 属性)的碰撞体不会表现为实体对象,只会允许其他碰撞体穿过。当碰撞体进入其空间时,触发器将在触发器对象的脚本上调用 OnTriggerEnter 函数。

脚本碰撞回调

发生碰撞时,物理引擎会在附加到相关对象的所有脚本上调用特定名称的函数。可以在这些函数中放置所需的任何代码来响应碰撞事件。例如,当汽车撞到障碍物时,可以播放碰撞音效。

在第一个检测到碰撞的物理更新中,将调用 OnCollisionEnter 函数。在保持接触的更新期间,将调用 OnCollisionStay,最后由 OnCollisionExit 指示接触已经中断。触发碰撞体会调用模拟的 OnTriggerEnterOnTriggerStayOnTriggerExit 函数。请注意,对于 2D 物理,可使用在名称中附加了 2D 字样的等效函数,例如 OnCollisionEnter2D。有关这些函数和代码示例的完整详细信息,请参阅关于 MonoBehaviour 类的脚本参考页面。

对于正常的非触发碰撞,还有一个额外的细节,即所涉及的对象中至少有一个对象必须具有非运动刚体(即,必须关闭 _Is Kinematic_)。如果两个对象都是运动刚体,则不会调用 OnCollisionEnter 等函数。对于触发碰撞,此限制不适用,因此运动和非运动刚体都会在进入触发碰撞体时提示调用 OnTriggerEnter

碰撞体相互作用

碰撞体彼此之间的相互作用根据刚体组件的配置不同而不同。三个重要的配置是_静态碰撞体 (Static Collider)(即完全没有附加任何刚体)、刚体碰撞体 (Rigidbody Collider)_ 和_运动刚体碰撞体 (Kinematic Rigidbody Collider)_。

静态碰撞体

静态碰撞体是具有碰撞体而没有刚体的游戏对象。静态碰撞体在大多数情况下用于表示始终停留在同一个地方而永远不会四处移动的关卡几何体。靠近的刚体对象会与静态碰撞体发生碰撞,但不会移动静态碰撞体。

在特殊情况下,物理引擎针对永远不会移动的静态碰撞体进行优化。例如,即使您移动静态碰撞体,停在静态碰撞体上的车辆也会保持睡眠状态。您可以在运行时启用、禁用或移动静态碰撞体,而不会特别影响物理引擎的计算速度。另外,只要缩放比例是统一的(无偏差),就可以安全地缩放静态网格碰撞体。

刚体碰撞体

这是一种附加了碰撞体和普通非运动刚体的游戏对象。刚体碰撞体完全由物理引擎模拟,并可响应通过脚本施加的碰撞和力。刚体碰撞体可与其他对象(包括静态碰撞体)碰撞,是使用物理组件的游戏中最常用的碰撞体配置。

运动刚体碰撞体

这是一种附加了碰撞体和_运动_刚体(即启用了刚体的 IsKinematic 属性)的游戏对象。可使用脚本来移动运动刚体对象(通过修改对象的变换组件),但该对象不会像非运动刚体一样响应碰撞和力。运动刚体应该用于符合以下特征的碰撞体:偶尔可能被移动或禁用/启用,除此之外的行为应该像静态碰撞体一样。这方面的一个例子是滑动门,这种门通常用作不可移动的物理障碍物,但必要时可以打开。与静态碰撞体不同,移动的运动刚体会对其他对象施加摩擦力,并在双方接触时“唤醒”其他刚体。

即使处于不动状态,运动刚体碰撞体也会对静态碰撞体产生不同的行为。例如,如果将碰撞体设置为触发器,则还需要向其添加刚体以便在脚本中接收触发器事件。如果不希望触发器在重力作用下跌落或在其他方面受物理影响,则可以在其刚体上设置 IsKinematic 属性。

可使用 IsKinematic 属性随时让刚体组件在正常和运动行为之间切换。

A common example of this is the “ragdoll” effect where a character normally moves under animation but is thrown physically by an explosion or a heavy collision. The character’s limbs can each be given their own Rigidbody component with IsKinematic enabled by default. The limbs move normally by animation until IsKinematic is switched off for all of them and they immediately behave as physics objects. At this point, a collision or explosion force will send the character flying with its limbs thrown in a convincing way.

碰撞操作矩阵

当两个对象碰撞时,可能会发生许多不同的脚本事件,具体取决于碰撞对象的刚体配置。以下图表详细列出了根据附加到对象的组件来调用的事件函数。某些组合仅会使两个对象之中的一个对象受到碰撞的影响,但一般规则是物理特性不会应用于没有附加刚体组件的对象。

发生碰撞检测并在碰撞后发送消息
静态碰撞体 刚体碰撞体 运动刚体碰撞体 静态触发碰撞体 刚体触发碰撞体 运动刚体触发碰撞体
静态碰撞体          
刚体碰撞体      
运动刚体碰撞体          
静态触发碰撞体            
刚体触发碰撞体            
运动刚体触发碰撞体            
碰撞后发送触发器消息
静态碰撞体 刚体碰撞体 运动刚体碰撞体 静态触发碰撞体 刚体触发碰撞体 运动刚体触发碰撞体
静态碰撞体        
刚体碰撞体      
运动刚体碰撞体      
静态触发碰撞体    
刚体触发碰撞体
运动刚体触发碰撞体
Collision
连续碰撞检测 (CCD)