报名参加即将到来的黑客马拉松大赛!奖金为总额超过 25 万美元的 MANA 和 LAND 。
X
你好,请选择
语言:
关闭

形状组件

Decentraland 中的三维场景是基于实体 - 组件模型开发的,场景中的所有内容都是 entity(实例),每个实体都可以包含形成其特征和功能的_components(组件)_。

实体渲染的形状由它使用的组件来决定。每个实体只能分配一个形状组件。

nested entities

基本形状

有几个基本形状可以将添加到实体中。

有以下几种基本形状组件:

  • BoxShape
  • SphereShape
  • PlaneShape
  • CylinderShape
  • ConeShape

这些组件中的每一个都具有特定于该形状的某些属性,例如 cylinder 圆柱形状具有arc, radiusTop, radiusBottom 等属性。

有关组件属性的更多详细信息,请参阅组件参考

要将组件应用于实体,可以在一个操作中实例化一个新组件并将其分配到实例:

myEntity.addComponent(new SphereShape())

也可以先创建组件实例,然后将其分配给实体。

let shpere = new SphereShape()
myEntity.addComponent(sphere)

基本形状不包括材质。要为其指定颜色或纹理,可以将材质组件 添加给同一实体。

3D 模型

对于更复杂的形状,您可以使用 Blender 等外部软件工具构建 3D 模型,然后使用 .glTF.glb (binary .glTF)导入。 glTF(GL 传输格式)是 Khronos 的一个开源项目,为 3D 素材提供了一种通用、可扩展的格式,它既高效又与现代网络技术具有高度的可互操作性。

将外部模型添加到场景中,可以使用 GLTFShape 组件,将其 src 设置为包含模型的 glTF 文件的路径。

myEntity.addComponent(new GLTFShape("models/House.gltf"))

由于 src 字段是必需的,因此在构造组件时必须赋值。

在上面的示例中,模型位于场景项目根目录下的 models 文件夹中。

提示:我们建议您将模型与其它文件分开,放在场景中的 /models 文件夹中。

在 glTF 模型可以嵌入纹理、材质、碰撞器和动画。有关详细信息,请参阅3D 模型

请记住,所有模型、着色器和纹理都必须在场景限制的参数范围内。

注意:还支持 .obj 格式的 3D 模型,但不鼓励使用。.obj 格式模型可使用 OBJShape 组件导入。请注意 .obj 模型不支持动画和其他功能。

免费的 3D 模型库

除了自己构建 3D 模型,您也可以从多个免费或付费库下载。

以下是免费或相对便宜的 3D 内容库:

注意:请注意您下载的内容许可。

请注意,在其中一些站点中,您可以选择下载模型的格式。如果有的话,请选择 .glTF 格式。如果没有,则必须先将它们转换为 glTF,然后才能在场景中使用它们。因此,我们建议将它们先导入 Blender ,然后用 glTF 导出插件导出到 .glTF 格式。

Collisions 碰撞

启用 Collisions 的实体会占用空间且阻挡用户前进,如果实体没有启用碰撞,那么用户可以从实体上直接穿越过去。

当前碰撞的设置并不会影响其他实体彼此之间的交互,实体可以重叠。碰撞设置仅影响实体与用户的交互方式。

Decentraland 目前没有物理引擎,因此如果实体需要掉落、碰撞或反弹功能,则必须在场景代码中编写相应代码。

提示:要查看场景中所有碰撞网格的限制,请使用 dcl start 启动场景预览,然后单击 c。预览会用蓝线绘制出相应的碰撞网格。

默认情况下,实体不启用碰撞。根据形状组件的类型,可以按如下方式启用碰撞:

  • 对于_基本_形状(如长方体,球体,平面等),可以将形状组件的 withCollisions 字段设置为 true 来启用碰撞。

此示例定义了一个无法通过的长方体实体。

  let box = new BoxShape()
  box.withCollisions = true
  myEntity.addComponent(box)

注意:Planes 仅阻止一个方向的移动。

  • 要在 glTF 形状中启用碰撞,您可以:

    • 外面套一个基本形状的不可见实体,并将其 withCollisions 字段设置为 true
    • 使用 Blender 等外部工具编辑模型,加一个 collider 对象。collider 必须命名为 x_collider,其中_x_是模型的名称。因此,对于名为 house 的模型,collider 必须命名为 house_collider

collider 可以是一组几何形状或平面,用来定义模型的哪些部分是碰撞的。这样可以有更多的控制并且对系统的要求也低得多,因为碰撞对象通常比原始模型更简单(具有更少的顶点)。

有关如何将 colliders 添加到 3D 模型的更多详细信息,请参阅3D模型

不可见实体

可以在其形状组件中设置 visible 字段来使实体不可见。在将形状作为碰撞使用时,这个操作尤其有用。

默认情况下,基本形状和 3D 模型的所有组件都是可见的。

const myEntity = new Entity()
myEntity.addComponent(new BoxShape())
myEntity.getComponent(BoxShape).visible = false

优化 3D 模型

要确保场景中的 3D 模型加载速度更快,占用的内存更少,请遵循以下最佳实践:

  • .glb 格式保存模型,这是 .gltf 格式的轻量版本。
  • 如果您有多个共享相同纹理的模型,请将纹理导出到一个单独的文件中。这样多个模型可以使用仅需要加载一次的单个纹理文件。
  • 如果有多个实体使用相同 3D 模型,可以仅实例化一个 GLTFShape 组件,然后将相同的组件分配给需要使用它的实体。
  • 如果您的场景中有实体经常显示和消失,最好将这些实体集中在一起,保持已定义,然后在需要时从引擎中删除。这有助于更快显示,缺点是在不使用时它们也会占用内存。请参阅实体和组件

复用形状

如果场景中的多个实体使用相同的基本形状或 3D 模型,则无需为每个实体分别创建形状组件的实例。所有实体可以共享一个相同的实例。

这样做可以让场景显得更轻量,并且可以防止您超出每个场景最多 bodies 物体限制

注意:复用的形状将添加到场景的 triangle 三角形 计数中。因此可以通过复用形状来避免最多三角形数的限制。

// Create shape component
const house = new GLTFShape("models/House.gltf")

// Create entities
const myEntity = new Entity()
const mySecondEntity = new Entity()
const myThirdEntity = new Entity()

// Assign shape component to entities
myEntity.addComponent(house)
mySecondEntity.addComponent(house)
myThirdEntity.addComponent(house)

共享形状的每个实体可以应用不同的比例、旋转或甚至材质(在基本形状的情况下),而不影响其他实体的呈现方式。

共享使用同一个 3D 模型实例的实体也可以有独立运行的动画。每个组件必须有一个单独的 Animator 组件,以及单独的 AnimationState 对象,以跟踪当前正在播放的动画的哪个部分。参见3D 模型动画