刚体概述
关节

碰撞体

碰撞体 (Collider) 组件定义对象的形状以便用于物理碰撞。碰撞体是不可见的,其形状不需要与对象的网格完全相同,事实上,粗略近似方法通常更有效,在游戏运行过程中难以察觉。

最简单(并且也是处理器开销最低)的碰撞体是所谓的_原始_碰撞体类型。在 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 函数。

Collision callbacks for scripts

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

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

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

碰撞体相互作用

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

静态碰撞体

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

物理引擎假定静态碰撞体永远不会移动或改变,并且可以基于此假设进行有用的优化。因此,在游戏运行过程中不应禁用/启用、移动或缩放静态碰撞体。如果更改静态碰撞体,则会导致物理引擎进行额外的内部重新计算,从而导致性能大幅下降。更糟糕的是,这些更改有时会使碰撞体处于不明的状态,从而产生错误的物理计算。例如,针对已更改的静态碰撞体的射线投射可能无法检测到静态碰撞体,或在空间中的随机位置检测到静态碰撞体。此外,移动的静态碰撞体碰到的刚体不一定会“被唤醒”,静态碰撞体也不会施加任何摩擦力。由于这些原因,只应更改刚体碰撞体。如果希望碰撞体对象不受靠近的刚体影响,但仍然可以通过脚本来移动该对象,则应为其附加一个_运动_刚体组件附加,而非不附加任何刚体。

刚体碰撞体

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

运动刚体碰撞体

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

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

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

这方面的一个常见例子是“布娃娃”效果;在这种效果中,角色通常在动画下移动,但在爆炸或猛烈碰撞时被真实抛出。角色的四肢可被赋予自己的刚体组件,并在默认情况下启用 IsKinematic。肢体将通过动画正常移动,直到所有这些肢体关闭 IsKinematic 为止,然后它们立即表现为物理对象。此时,碰撞或爆炸力将使角色飞出,使肢体以令人信服的方式被抛出。

碰撞操作矩阵

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

发生碰撞检测并在碰撞后发送消息
静态碰撞体 刚体碰撞体 运动刚体碰撞体 静态触发碰撞体 刚体触发碰撞体 运动刚体触发碰撞体
静态碰撞体          
刚体碰撞体      
运动刚体碰撞体          
静态触发碰撞体            
刚体触发碰撞体            
运动刚体触发碰撞体            
碰撞后发送触发器消息
静态碰撞体 刚体碰撞体 运动刚体碰撞体 静态触发碰撞体 刚体触发碰撞体 运动刚体触发碰撞体
静态碰撞体        
刚体碰撞体      
运动刚体碰撞体      
静态触发碰撞体    
刚体触发碰撞体
运动刚体触发碰撞体
刚体概述
关节