For the complete documentation index, see llms.txt. This page is also available as Markdown.

实体定位

如何设置场景中实体的位置、旋转和缩放

你可以设置 位置, 旋转 和 缩放 任意实体的,方法是使用 Transform 组件。它可用于 3D 空间中的任何实体,并影响实体的渲染位置。这包括基本形状(立方体、球体、平面等)、3D 文本形状、NFT 形状和 3D 模型(GltfContainer).

在 Creator Hub 中使用场景编辑器

通过场景编辑器向场景添加项目时,它会隐式包含一个 Transform 组件。随后,通过更改实体的位置、旋转或缩放,你可以隐式更改实体 Transform 组件中的值。你还可以使用场景编辑器的 UI 以数值方式提供更精确的值。

代码基础



若要在一段时间内移动、旋转或调整场景中的实体大小,请逐帧增量地更改此组件中的值。参阅 移动实体 了解更多详情和最佳实践。

位置

位置 是一个 三维向量,它设置实体中心在全部三个轴上的位置, x, y,以及 z。参阅 几何类型 了解更多详情。

设置位置时,请牢记以下注意事项:

  • 位置向量中的数值表示 米 (除非该实体是经缩放实体的子实体)。

  • 由单个地块组成的场景尺寸为 16m x 16m。场景中心(地面高度)位于 x:8, y:0, z:8。如果场景由多个地块组成,中心位置将取决于它们的排列方式。

  • x:0, y:0, z:0 指的是 西南 场景基础地块在地面高度的角落。

    提示:查看场景预览时,场景的 (0,0,0) 点会显示一个指南针,并标有各轴标签作为参考。

    注意:你可以通过编辑 base 的属性 scene.json.

  • 为了更好地确定方向,请使用你的 左 手:

    • 你的食指(指向前方)是 z 轴

    • 你的中指(指向侧方)是 x 轴

    • 你的拇指(指向上方)是 y 轴。

  • 如果一个实体是另一个实体的子实体,则 x:0, y:0, z:0 指的是其父实体的中心,无论父实体位于场景中的何处。

  • 场景中的每个实体必须始终位于其所占地块的边界内。如果实体离开这些边界,将引发错误。

    提示:在预览模式下查看场景时,超出边界的实体会以 红色.

  • 场景的高度也有限制。无论占用多少地块,每个场景的最大高度均为 330 米。放置在 200 米以上的实体可能会出现多人同步问题。参阅 场景限制 了解更多详情。

旋转

旋转 存储为一个 四元数,即由四个数字组成的系统, x, y, z 和 w。这些数字中的每一个取值范围均为 -1 到 1。参阅 几何类型 了解更多详情。

你也可以使用以下方式设置旋转字段: 欧拉 角,这是一种更常见的 x, y 和 z 表示法,使用大多数人熟悉的 0 到 360 的数字。要使用欧拉角,请采用以下表示法之一:

使用一个 三维向量 来表示欧拉角时, x, y 和 z 表示该轴上的旋转,以度为单位。完整旋转一圈需要 360 度。

获取实体的旋转时,默认返回四元数。要获得以欧拉角表示的旋转,请使用 Quaternion.toEulerAngles():

获取实体的全局位置和旋转

该 getWorldPosition 和 getWorldRotation 函数会返回实体的全局位置和旋转。这意味着它会返回玩家看到该物品时所感知的位置或旋转,忽略任何父级层级结构。

  • getWorldPosition(engine, entity: Entity): Vector3Type:此函数会返回实体的世界位置,并考虑所有父实体的位置(如果实体本身有父实体),若 {x: 0, y: 0, z: 0} 实体没有 Transform,则返回该值。

  • getWorldRotation(engine, entity: Entity): QuaternionType:此函数会返回实体的世界旋转,并考虑所有父实体的旋转(如果实体本身有父实体)。它返回一个 Quaternion 类型,并返回单位四元数 {x: 0, y: 0, z: 0, w: 1} 实体没有 Transform,则返回该值。

注意: 全局位置和全局旋转相对于场景内部坐标,而非 Genesis City。

面向玩家

添加一个 Billboard 组件到实体,使其始终旋转以面向玩家。

广告牌是 20 世纪 90 年代 3D 游戏中常用的一种技术,当时大多数实体都是始终面向玩家的 2D 平面。同样的理念也可用于旋转 3D 模型。

你可以通过以下参数配置广告牌的行为:

  • billboardMode:使用 BillboardMode 的值,以设置哪些旋转轴自动旋转来面向玩家:

    • BillboardMode.BM_ALL:实体会在所有旋转轴上旋转以面向玩家。如果玩家位于实体上方很高处,实体将朝上。

    • BillboardMode.BM_NONE:实体完全不会旋转。

    • BillboardMode.BM_X:实体仅在其 x 旋转轴上旋转。

    • BillboardMode.BM_Y:实体仅在其 y 旋转轴上旋转。它仅左右旋转,不会上下旋转。如果玩家位于实体上方或下方,它会保持垂直于地面。

    • BillboardMode.BM_Z:实体仅在其 z 旋转轴上旋转。

  • targetEntity:(可选)广告牌旋转以面向的实体,而非玩家的摄像机。如果引用的实体不存在(例如尚未创建或已被移除),广告牌将停止旋转并保持最后的朝向,直到该实体再次存在。将此项设置为 engine.CameraEntity 等同于不设置它。

💡 提示:广告牌非常适合添加到 文本 实体,因为它使它们始终清晰可读。

该 旋转 实体的 Transform 组件的值不会随着广告牌跟随玩家而改变。

如果一个实体同时拥有 Billboard 组件和 Transform 带有 旋转 值的组件,玩家将看到该实体像广告牌一样旋转。如果广告牌不影响所有轴,其余轴将根据 Transform 组件旋转。

面向一组坐标

使实体 A 面向实体 B:

缩放

缩放 也是一个 三维向量,存储为一个 Vector3 对象,包括各个 x, y 和 z 轴上的缩放因子。无论实体的形状是基本形状还是 3D 模型,都会相应地缩放。

默认缩放为 1,因此赋予大于 1 的值可拉伸实体,赋予小于 1 的值可缩小实体。

继承父级变换

当一个实体嵌套在另一个实体内时,子实体会继承父实体的组件。这意味着如果父实体被定位、缩放或旋转,其子实体也会受到影响。子实体的位置、旋转和缩放值不会覆盖父实体的值,而是会与之叠加。

通过设置子实体的 parent 字段,将一个实体指定为另一个实体的父实体 Transform 组件旋转。

如果父实体被缩放,其所有子实体的位置值也会被缩放。

在此示例中,子实体会缩小至 0.5,因为其父实体具有该缩放比例。子实体的位置也将相对于其父实体。我们必须将父实体的位置与子实体的位置相加。在本例中,由于父实体缩放为原来的一半,子实体的变换也会按比例缩小。以绝对坐标计,子实体位于 { x: 3, y: 1.5, z: 1 }。如果父实体具有 旋转,这也会影响子实体的最终位置,因为它会改变子实体偏移所依据的轴。

如果子实体的 Transform 上没有 位置 ,默认值为 0,0,0,这会使其保持在与父实体相同的位置。

你可以使用没有形状组件的不可见实体作为父实体,以包装一组其他实体。该实体不会在渲染的场景中可见,但可用于对其子实体进行分组,并对它们全部应用变换。

将实体附加到虚拟形象

有三种将实体附加到玩家的方法:

  • 将其设为以下对象的子实体: 虚拟形象实体

  • 将其设为以下对象的子实体: 摄像机实体

  • 使用 AvatarAttach 组件

将实体附加到虚拟形象的最简单方法是将父级设置为 保留实体 engine.PlayerEntity。该实体随后将随玩家的位置一起移动。

你也可以将实体设为 保留实体 engine.CameraEntity。在第一人称模式下使用摄像机实体时,附加的实体将跟随摄像机的移动。这非常适合让某些物体始终保持在视野中,例如即使摄像机朝上,也始终让枪的 3D 模型保持在视野中。

要将对象附加到虚拟形象的一块骨骼上,并使其随虚拟形象的动画一起移动,请添加一个 AvatarAttach 组件到实体。

你可以在虚拟形象上选择不同的锚点,其中大多数点都与玩家的骨架关联,并跟随玩家的动画。例如,使用右手锚点时,附加的实体会在虚拟形象挥手或跑步时摆动手臂时移动,就像玩家正用手拿着该实体一样。

创建一个 AvatarAttach 组件时,传入包含以下数据的对象:

  • avatarId: 可选 要附加到的玩家 ID。对于使用以太坊钱包连接的玩家,此 ID 与玩家的以太坊地址相同。如果未指定,则将实体附加到本地玩家的虚拟形象。

  • anchorPointId:使用枚举中的值,指定要将实体附加到虚拟形象骨架上的哪个锚点 AvatarAnchorPointType.

以下示例将一个实体附加到特定虚拟形象,以便所有其他玩家都看到它附加在该同一虚拟形象上。

以下锚点可用于 AvatarAnchorPointType 枚举:

  • AAPT_RIGHT_HAND:固定在玩家的右手上

  • AAPT_LEFT_HAND:固定在玩家的左手上

  • AAPT_HEAD:固定在玩家头部中心。

  • AAPT_NECK:固定在玩家颈部底部。

  • AAPT_SPINE:固定在脊柱上部。

  • AAPT_SPINE1:固定在脊柱中部。

  • AAPT_SPINE2:固定在脊柱下部。

  • AAPT_HIP:固定在髋骨上。

  • AAPT_LEFT_SHOULDER:固定在左肩上。

  • AAPT_LEFT_ARM:固定在左侧第一块臂骨上,位于肩部高度。

  • AAPT_LEFT_FOREARM:固定在左前臂骨上。

  • AAPT_LEFT_HAND_INDEX:固定在左手食指指尖。

  • AAPT_RIGHT_SHOULDER:固定在右肩上。

  • AAPT_RIGHT_ARM:固定在右侧第一块臂骨上,位于肩部高度。

  • AAPT_RIGHT_FOREARM:固定在右前臂骨上。

  • AAPT_RIGHT_HAND_INDEX:固定在右手食指指尖。

  • AAPT_LEFT_UP_LEG:固定在左腿上部的腿骨上。

  • AAPT_LEFT_LEG:固定在左腿下部的腿骨上。

  • AAPT_LEFT_FOOT:固定在左腿的脚踝上。

  • AAPT_LEFT_TOE_BASE:固定在左腿脚趾尖上。

  • AAPT_RIGHT_UP_LEG:固定在右腿上部的腿骨上。

  • AAPT_RIGHT_LEG:固定在右腿下部的腿骨上。

  • AAPT_RIGHT_FOOT:固定在右腿的脚踝上。

  • AAPT_RIGHT_TOE_BASE:固定在右腿脚趾尖上。

  • .AAPT_NAME_TAG:浮动在玩家姓名标签正上方,不受玩家动画影响。

    注意:姓名标签的高度会根据玩家所穿戴物品的高度动态调整。因此,戴着高帽子的玩家,其姓名标签会比其他人高一点。

  • AAPT_POSITION 已弃用:玩家的整体位置。它显示在玩家脚下方 0.8 的高度处。

💡 提示:要使用这些值,请写 AvatarAnchorPointType. ,VS Code 会在下拉菜单中显示完整的选项列表。



实体渲染由场景的每个实例本地决定。将实体附加到某个玩家身上,并不会让其他正在看到该玩家的玩家也看到它。如果实体附加到默认的本地玩家身上,每个玩家都会把该实体体验为附加在自己的头像上。

该 AvatarAttach 组件会覆盖以下 Transform 组件中的值。你放入 Transform 组件中的任何值都会被替换为该实体相对于玩家 Transform 的相对位置,这些值会随着玩家移动和动画逐帧更新。

如果你需要让实体相对于头像锚点带有偏移,或者使用不同的旋转或缩放,请通过父实体来实现。

  1. 创建一个不可见实体,只包含一个 Transform 和一个 AvatarAttach 组件。其 Transform 值会随着玩家移动而被覆盖

  2. 将你想附加的实体设为这个父实体的子实体。其 Transform 值可以描述相对于锚点的偏移。

附加到其他玩家

你可以使用 AvatarAttach 组件将实体附加到另一位玩家。为此,你必须知道该玩家的 id。

要将实体附加到另一位玩家的头像上,你必须在字段 avatarId中提供该用户的 ID。获取这些数据有 多种方式 。

获取 userId 为附近所有其他玩家的 getPlayer()

将它与 AvatarAttach一起使用时,你可以用以下代码在场景中每位其他玩家头顶添加一个悬浮立方体:

查看获取其他用户 ID 的其他方法,请参见 获取玩家数据.

场景边界

场景中的所有实体都必须位于场景边界内,因为边界外的区域是属于其他玩家的地块。

如果你的模型在预览运行时有任何部分超出这些限制,这些超出的部分将会被裁掉,并且不会被渲染,无论是在预览中还是在已发布的场景中都是如此。

场景中实体的位置在它们移动时会持续被检查,如果某个实体离开场景后又返回,它将被移除,然后再次正常渲染。

场景地面上的网格显示了场景的边界,默认情况下其范围在 x 和 z 轴上从 0 到 16,并在 y 轴上最高到 20。你可以自由地将实体放置在地下,在 y 轴。

💡 提示以下的 0 处。如果你的场景需要更多地块,你可以将它们添加到项目的 scene.json 文件中。请参见 场景元数据 中的说明。添加后,你应该会看到网格扩展以覆盖额外的地块。

最后更新于