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

3D 模型动画

如何为场景中的 3D 模型制作动画

3D 模型中的 .glTF 和 .glb 格式可以包含任意数量的动画。动画通过指定一系列 关键帧 ,这些关键帧按时间排列,然后网格会从一个姿势平滑过渡到另一个姿势,以模拟连续运动。

大多数 3D 模型动画都是 骨骼动画。这些动画会把模型的复杂几何结构简化为“火柴人”,将网格中的每个顶点连接到最近的 骨骼 在 骨架。建模者将骨架调整为不同姿势,网格则伸展和弯曲以跟随这些动作。

作为替代, 顶点动画 无需骨架即可为模型添加动画。这些动画直接指定模型中每个顶点的位置。Decentraland 也支持这些动画。

参见 动画 ,了解如何为 3D 模型创建动画。请阅读 Shape 组件 ,了解如何将 3D 模型导入场景的说明。

💡 提示:动画通常更适合让物体原地移动,而不是改变实体的位置。例如,你可以设置一个动画让角色的脚原地移动,但要改变实体的位置,最好使用 Transform 组件。参见 实体定位 了解更多详情。

检查 3D 模型是否包含动画

并非所有 glTF 文件都包含动画。要查看是否有可用动画,你可以执行以下操作:

  • 如果使用 VS Code(推荐),安装 GLTF Tools 扩展,并在其中查看 glTF 文件的内容。

  • 打开 Babylon Sandbox 网站,然后将 glTF 文件(以及任何 .jpg 或 .bin 依赖项)拖到浏览器中。

  • 打开 .glTF 文件,用文本编辑器打开并向下滚动直到找到 "animations":.

💡 提示:在 骨骼 动画中,动画名称通常由骨架名称、下划线和动画名称组成。例如 myArmature_animation1.

自动播放

如果 3D 模型包含任何动画,默认行为是始终循环播放其中第一个动画。

要避免这种行为,请向拥有该模型的实体添加一个 动画器 组件,然后显式处理动画播放。如果实体中存在一个 动画器 组件,则所有动画默认处于 playing: false 状态,需要手动播放。

💡 提示:在 场景编辑器,你可以添加一个 动画器 Animator 组件。参见 添加组件。你还可以通过无代码方式控制动画,借助 操作以无代码方式触发声音播放,参见 让任意项目变为智能项目.

显式处理动画

一个 动画器 组件用于访问实体的所有动画,并可用于显式指示实体播放或停止某个动画。 动画器 组件包含一个由 状态组成的数组,这个列表必须为 3D 模型可执行的每个动画都包含一个对象。单个 动画器 可以包含任意数量所需的状态。

每个 state 对象会跟踪动画当前是否正在播放。

获取动画

通过 动画器 按名称从 .Animator.getClip() 函数中获取一个片段。此函数返回动画状态对象的可变版本。

Animator.getClip 需要以下参数:

  • 实体:你要查询的实体的 动画器 组件。

  • clipName:你要获取的片段名称字符串。

Animator.getClip 获取动画状态的可变版本,因此你可以自由修改该函数返回的值。

播放动画

该 .playing 字段决定动画当前是否正在播放。请注意,单个 3D 模型中可以同时播放多个动画。

使用 Animator.playSingleAnimation() 函数作用于一个 AnimationState 对象。

如果该实体正在播放任何其他动画, Animator.playSingleAnimation 会停止它们。

Animator.playSingleAnimation 需要以下参数:

  • 实体:你要查询的实体的 动画器 组件。

  • clipName:你要播放的片段名称字符串。

  • resetCursor: (可选) 如果 true,它会从头开始播放动画,即使该动画之前已暂停。如果 false,它将从暂停的位置继续播放动画。默认值: true.

下表总结了 Animator.playSingleAnimation() 在不同的 resetCursor 属性取值下的表现:

resetCursor = false

resetCursor = true (默认)

当前正在播放

无影响。

从头播放。

已暂停

从最后播放的帧继续。

从头播放。

已结束(非循环)

从头播放。

从头播放。

循环动画

默认情况下,动画会循环播放,永远重复。

通过设置 loop 属性在 state 对象。

如果 loop 设置为 false,动画只播放一次,然后停止,并停留在最后一帧的姿势上。

停止动画

要停止实体正在播放的所有动画,请使用 Animator.stopAllAnimations().

Animator.stopAllAnimations 需要以下参数:

  • 实体:你要查询的实体的 动画器 组件。

  • resetCursor: (可选) 如果 true,它会恢复到动画第一帧的姿势。如果 false,则会停留在当前姿势并保持暂停。默认值: true.

当非循环动画播放结束后,默认情况下 3D 模型会保持在它最后的姿势。 shouldReset 属性控制当已停止的动画再次播放时会发生什么:如果 true,每当动画从停止切换为播放时,都会将其恢复到初始状态(第一帧;如果以负的 速度播放,则为最后一帧)。如果 false (默认),它将从之前停止的位置继续。

你也可以随时使用 Animator.stopAllAnimations() ,将姿势显式重置为动画的第一帧。

检测动画何时结束

当非循环动画播放结束时,运行时会将该动画状态的 playing 属性重置回 false。你的场景代码可以读取此值来判断动画何时结束,例如紧接着串联另一个动画。

处理多个动画

如果一个 3D 模型打包了多个动画,一个 动画器 组件就可以处理它们全部。

在上面的示例中,两个动画分别由不同的 state 对象处理,然后它们都被分配到同一个 动画器 组件。

动画中的每根骨骼一次只能受一个动画影响,除非这些动画有一个 权重 ,其总和为 1 或更少。

如果一个动画只影响角色的腿,而另一个只影响角色的头部,那么它们可以同时播放,没有问题。但如果它们都影响角色的腿,那么你必须要么一次只播放一个,要么以更低的 权重 值列表。

如果在上面的示例中, bite 动画只影响鲨鱼的嘴部,而 swim 动画只影响鲨鱼脊柱的骨骼,那么它们就可以同时播放。

动画速度

通过更改 速度 属性来改变动画的播放速度。速度值默认是 1。

将速度设为小于 1 可减慢播放,例如设为 0.5 表示以一半速度播放。将其设为大于 1 可加快播放,例如设为 2 表示以两倍速度播放。

动画权重

该 权重 属性允许单个模型同时执行多个动画,通过计算动画中所有运动的加权平均值。 权重 决定该动画在平均计算中占据多大比重。

默认情况下, 权重 等于 1。 权重 不能高于 1.

该 权重 实体中所有活动动画的值应始终加起来为 1。如果总和小于 1,加权平均在剩余部分的计算中将使用骨架的默认姿势。

例如,在上面的代码示例中,我们正在播放 swim 动画,它只有一个 权重 为 0.2。这种游泳动作会相当细微:只有动画定义强度的 20%。剩余 80% 的计算会取自骨架的默认姿势。

该 权重 属性可以以有趣的方式使用,例如 权重 属性 swim 可以按鲨鱼游动的速度成比例设置,这样你就不需要为快慢游动创建多个动画。

你也可以在开始和停止动画时逐渐改变 权重 值,让过渡更自然,并避免从默认姿势跳到动画的第一个姿势。

最后更新于