碰撞体
了解为实体提供 3D 形状和碰撞的不同组件。
带有碰撞体的实体会占据空间并阻挡玩家路径,没有碰撞体的实体可以被玩家头像穿过。
碰撞体也是使实体可点击所必需的。按钮事件基于实体的碰撞体形状,而不是其可见形状。
用于与玩家物理交互或与指针事件交互的碰撞层是分开的,碰撞体可以配置为只与其中一种交互。它们也可以配置为与自定义层交互,这些自定义层可以与 射线投射 一起使用,以处理场景中最合适的情况。
使用场景编辑器
管理实体碰撞体最简单的方法是使用 场景编辑器.
你可以向实体添加一个 Mesh Collider 组件,为实体指定一个基础形状(立方体、平面、球体、圆柱体或圆锥体)。然后你就可以从下拉菜单中选择 碰撞层 。
你也可以在一个 GLTF 组件上配置碰撞层,以更改默认值 碰撞层 ,该默认值用于模型的碰撞几何体或可见几何体。参见 添加组件.

基础形状上的碰撞体
该 MeshCollider 组件会根据基础形状(盒体、球体、平面、圆柱体或圆锥体)为实体提供一个简单的碰撞体。
拥有一个 MeshRenderer 组件以赋予它们一个 基础形状 默认没有碰撞体。你还必须为实体提供一个 MeshCollider 组件。
以下碰撞体形状可用于 MeshCollider。其中一些形状包含仅适用于该形状的可选附加字段。
盒体:
使用
MeshCollider.setBox(),传入实体。平面:
使用
MeshCollider.setPlane(),传入实体。球体:
使用
MeshCollider.setSphere(),传入实体。圆柱体:
使用
MeshCollider.setCylinder(),传入实体。传入radiusTop和radiusBottom作为额外的可选字段,以修改圆柱体。
此示例定义了一个无法穿过的盒体实体。
碰撞体所使用的形状 MeshCollider 不一定需要与另一处所使用的形状相匹配 MeshRenderer。你也可以添加一个 MeshCollider 到一个具有来自 GltfContainer 组件的 3D 模型实体上,或者到一个完全没有可见形状的实体上。
3D 模型上的碰撞体
3D 模型可以在两个不同的几何层级上分配碰撞体:
visibleMeshesCollisionMask:指模型的可见几何体。默认情况下,这种几何体没有碰撞体。invisibleMeshesCollisionMask:指碰撞网格,其名称以_collider结尾。默认情况下,这种几何体会被视为同时用于物理和指针事件的碰撞体。
作为 3D 模型一部分嵌入的任何网格,如果其名称以 _collider 结尾,则会被视为 invisibleMeshesCollisionMask 层的一部分,并默认被解释为碰撞体。
将碰撞几何体定义为单独的不可见层,可以带来更强的控制力,而且比使用可见几何体对系统的要求低得多,因为碰撞对象通常比原始模型简单得多(顶点更少)。
如果模型没有任何碰撞几何体,而你又想让它影响物理或指针事件系统,你可以选择:
:将碰撞层直接分配给可见几何体,通过
visibleMeshesCollisionMask.
给实体添加一个
MeshCollider组件,为其赋予一个基础形状碰撞体。叠加一个具有……的不可见实体
MeshCollider组件。在 Blender 等外部工具中编辑模型,以包含一个 碰撞网格。该碰撞体必须命名为 x_collider,其中 x 是模型名称。因此,对于名为 house,其碰撞体必须命名为 house_collider.
你也可能想将指针事件碰撞层分配给 visibleMeshesCollisionMask ,以便悬停提示和指针事件能更准确地响应实体轮廓。请注意,这对性能要求更高。
参见 3D 模型 ,了解如何向 3D 模型添加碰撞体不可见几何体的更多细节。
import { GltfContainer, ColliderLayer } from "@dcl/sdk/ecs"
动画模型
当将碰撞体设置为使用包含 基于骨架的动画的模型可见几何体时,动画不会被碰撞体跟随。碰撞网格会保持其原始形状。如果动画涉及改变网格的几何形状,那么在动画播放时,碰撞网格会保留未动画化的形状。
当播放涉及移动整个网格但不改变其形状的动画时,这些变化会被碰撞体准确反映。例如,如果平台作为动画的一部分移动,那么平台的碰撞体也会随动画移动。
碰撞层
场景可以处理具有不同行为的独立碰撞层。
你可以配置一个 MeshCollider 组件或 GltfContainer 组件,使其只对一种交互、几种交互或不对任何交互作出响应。为此,在 MeshCollider 设置 collisionMask 属性,并在 GltfContainer 设置 visibleMeshesCollisionMask 或 invisibleMeshesCollisionMask 属性设置为以下一个或多个值:
ColliderLayer.CL_PHYSICS:阻挡玩家移动(场景墙壁、地板、平台)。不影响指针事件。ColliderLayer.CL_POINTER:仅响应指针事件。不阻挡玩家移动。ColliderLayer.CL_PLAYER:将该碰撞体标记为头像标记。射线投射和目标为CL_PLAYER的触发区域会检测到它,但玩家胶囊体会直接穿过它(没有物理阻挡)。在场景网格上,这用于仅将某个网格标记为“类似头像的目标”,仅供检测。ColliderLayer.CL_MAIN_PLAYER:类似于CL_PLAYER,但仅针对本地玩家。其掩码中带有CL_MAIN_PLAYER的射线投射和触发区域会检测到它;远程头像的射线投射/触发区域不会。ColliderLayer.CL_CUSTOM1到CL_CUSTOM8:可与射线投射和触发区域一起使用,以仅检测特定自定义层上的碰撞。ColliderLayer.CL_NONE:不响应任何类型的碰撞。
单个碰撞掩码可以响应多个碰撞层。使用 | 字符作为一个 或,以包含你需要的任意多个层。MeshCollider 的默认值是 ColliderLayer.CL_PHYSICS | ColliderLayer.CL_POINTER.
你可以将这 8 个不同的自定义层用于最适合场景的任何用途,例如一个可以用于 NPC 的视线计算,而另一个可以用于估算下落物体的轨迹。为不同系统使用不同的层可以让你使用更少的资源,因为在每种情况下,你只需要检查与相关实体的碰撞。
参见 射线投射 ,了解如何使用自定义碰撞层的更多信息。
摄像机与碰撞体
当玩家的摄像机以第三人称模式移动时,摄像机可能会被碰撞体阻挡,也可能不会,这取决于分配给实体的碰撞层。在设计场景时要注意这一点,你可能会希望阻止摄像机穿过墙壁或其他实体。
为了避免摄像机穿过墙壁,你必须同时将这两个 ColliderLayer.CL_PHYSICS 和 ColliderLayer.CL_POINTER 层分配给你想要阻挡摄像机的实体。重要的是,这两个层都要分配到实体上的同一几何体上。因此,如果你将 ColliderLayer.CL_PHYSICS 层分配给实体的可见层,你还必须将 ColliderLayer.CL_POINTER 层分配给同一几何体。
例如,在 Creator Hub 中,以下设置组合将防止摄像机穿过墙壁:

这两个 ColliderLayer.CL_PHYSICS 和 ColliderLayer.CL_POINTER 层都分配给了实体几何体的同一个不可见层。如果它们都分配给可见层,结果也会相同。这是默认行为,无论是通过 Creator Hub 还是通过代码添加实体都是如此。

在第二个示例中,摄像机可以穿过墙壁,因为 ColliderLayer.CL_PHYSICS 层被分配到了实体的不可见层,而 ColliderLayer.CL_POINTER 层被分配到了实体的可见层,即使这两个几何体具有相同的整体形状。
指针阻挡
只有带有碰撞体的形状才能通过 指针事件激活。实体还需要有碰撞体来阻止指针事件穿过它,并防止命中其后方的实体。例如,如果箱子周围有碰撞体,玩家就无法拾取锁在箱子里的东西。玩家的指针事件只会受到在 ColliderLayer.CL_POINTER 层。
默认情况下,MeshCollider 会同时影响物理层和指针层,但你可以将该值改为只影响其中一个,或者都不影响,并改为影响自定义层。
默认情况下,一个 GltfContainer 不会映射到任何碰撞层,但不可见几何体会同时影响物理层和指针层。你可以将该值改为只影响其中一个,或者都不影响,并改为影响自定义层。你也可以用同样的方式配置可见几何体层。
高级 MeshCollider 语法
创建一个 MeshCollider 组件的完整语法,不使用任何简化辅助函数时,看起来如下:
基础协议就是这样解释 MeshCollider 组件的。辅助函数会将其抽象掉并提供更友好的语法,但在底层它们输出的仍是这种语法。
该 $case 字段允许你指定一种允许的类型。每种类型都支持一组不同的参数。
支持的 $case 如下:
盒体平面球体圆柱体
根据 $case的值,可以为对应的形状定义对象,并传入任何相关属性。
最后更新于