实体建模和动画

在本指南中,我们将介绍为《我的世界》基岩版创建模型和创建动画的基础知识。 例如,我们将对一个小型机器人进行建模和动画制作,该机器人在添加实体简介一文中创建。

在本教程中,您将学习以下内容:

  • 如何使用 Blockbench 为实体创建模型。
  • 如何将材质和动画应用于模型。

要求

在开始本教程之前,建议完成以下内容。

模型

《我的世界》中的模型使用特定格式,该格式使用 JSON 来定义形状。 每个模型使用的材质都可通过渲染控制器分配。

为了创建模型和材质,我们将使用 Blockbench,这是一个 3D 建模程序,可以为《我的世界》的基岩版创建模型。

设置模型

首次打开 Blockbench 时,您会看到可用模型格式的列表。 选择 Bedrock Model。 您将看到一个关于项目基本设置的对话框。

Blockbench 中基岩版模型的项目设置

重要的部分是 Mob Geometry Name。 在这里,我们将为模型输入一个唯一的名称。 最佳实践是使用蛇形命名 — 所以只能使用小写字母、数字和下划线以及点。 不支持空格和其他特殊字符。 对于我们的模型,只需输入 robot

我们现在可以将文件名字段留空,稍后将在导出模型时定义它。 Box UV 设置和材质大小也可以保留为默认值,稍后会更改它们。 点击“Confirm”按钮将保存这些设置。

骨骼结构

制作模型时首先要考虑的是骨骼结构。 骨骼是模型中可以设置动画的部分,它们按任意深度的层级结构排列。 每个骨骼本身是不可见的,但可以包含将塑造模型的立方体。

Blockbench 中的骨骼列表

一个好的做法是为每个模型使用一个根骨骼,并将其他所有内容放入其中。 这意味着您以后可以同时为整个模型及其特定部分设置动画。 在 Blockbench 中创建一个新组。 在这种情况下,“组”和“骨骼”在本质上是相同的。

您可以右键单击该组或按 F2 对其进行重命名。 骨骼的名称应采用 `snake_case``(所以只包括小写字母、数字和下划线)。 每个骨骼名称都必须是唯一的,以供将来通过动画参考。

在我们按照以下步骤构建模型时,请确保正确设置结构。 您可以在组周围拖动以更改顺序或将它们放到其他组中。 此屏幕截图显示了成品模型的正确骨骼结构。

形状

您现在可以开始创建模型的形状。 创建新的立方体并使用移动、调整大小和旋转工具对其进行调整。 快速添加立方体的一个技巧是选择一个已经定位的立方体,然后按 Ctrl + D(复制)以获取副本。

Blockbench 中机器人的无材质形状

您可以通过同时按住 Shift、Control 或两者来更精确地移动立方体。 根据建模风格,可以完全沿着网格或仅以一半或四分之一的增量移动立方体。

基岩版模型默认使用 Box UV 映射。 这意味着材质映射将仅使用,并在必要时向下舍入为较小的数字。 为避免拉伸或看不见的面,请确保立方体的大小始终使用。

对于四肢等对称部分,请先在右侧创建它们,然后再将它们镜像到左侧。 您可以在创建材质之前或之后进行镜像,具体取决于您是否希望在两侧使用相同的材质。

当您为模型的移动部分创建骨骼时,始终要考虑该部分应围绕哪个点旋转。 选择一个骨骼并按 P 以获取 Pivot 工具。 此工具用于移动骨骼的枢轴点。 如果要围绕特定点旋转立方体,也可以在立方体上使用此工具。

材质

模板

模型的形状完成后,您可以创建材质模板。 模板是一种材质,对于模型的每个立方体和每个面都有一个独特的空间。 您也可以对立方体手动 UV 贴图,但通过创建模板可自动完成这一操作并找到最节省空间的布局。 请记住,《我的世界》不喜欢高分辨率图像。

创建材质时,输入robot 作为材质名称并选中模板选项。 在模板对话框中,选择您的分辨率。 《我的世界》的默认分辨率是 16x,根据需要可以提高。

底色

创建模板后,您可以移动到 Blockbench 中的“Paint”选项卡。 这将显示修改材质所需的所有工具。 选择油漆桶工具并将工具旁边的填充模式设置为立方体。 在右侧的颜色面板中选择一种颜色。 现在,您可以检查您的立方体并采用单独的基色为它们着色。

细节

您现在可以开始处理材质。 如果您更喜欢在图像编辑程序中使用材质,现在可以通过单击材质旁边的保存图标来保存材质。 然后,您可以在图像编辑器中打开它。 保存材质后,任何更改都会显示在 Blockbench 中。 但是,如果您更喜欢直接在模型上工作,可以使用 Blockbench 中的内置绘制工具。

我们可以采用一些技巧更有效地使用 Blockbench 中的画笔:

  • 要绘制更大的区域,您可以增大画笔大小。
  • 您可以直接在 3D 预览中进行绘制,也可以在左侧的 UV 编辑器中进行绘制。
  • 如果要创建一条直线,点击直线的起始位置,然后在直线的结束位置按住 Shift。
  • 为确保不会错过可能通过动画显示的覆盖点,您可以隐藏立方体。 只需点击大纲中的眼睛图标。

动画

动画可以使模型形状动起来,也可以播放声音和粒子效果。 在下一节中,我们将了解如何向实体添加动画,如何在 Blockbench 中创建自己的动画,以及如何使用动画控制器。

使用默认动画

原版资源包中包含通用动画,您可以在自己的包中引用这些动画,无需实际复制文件。 这些动画对于类似原版实体来说是一个很好的起点,但是自定义动画显然要强大得多。 您可以在此处的原版资源包中找到所有原版动画。

在此例中,我们将使用 look at 动画。 此动画将旋转“head”骨骼。 这就是为什么模型的头部使用完全相同的名称很重要。

此外,实体在其行为文件中需要一个 look at 组件。 这些是母牛的外观组件。 如果愿意,您可以尝试调整这些数字。

            "minecraft:behavior.look_at_player": {
                "priority": 7,
                "look_distance": 6,
                "probability": 0.02
            },
            "minecraft:behavior.random_look_around": {
                "priority": 9
            }

现在行为已设置,我们将转到客户端实体文件。 确保将此文件的格式版本设置为 1.10.0 或更高版本以使其正常工作。

首先来链接动画。 这是在实体 description 标签的 animations 部分完成的。 这里的第二部分 (animation.common.look_at_target) 是动画的全局标识符。 此名称在动画文件中定义,并且在此包或任何其他包中的任何位置都有效。 第一部分 (look_at_target) 是短名称。 这就是我们在实体文件中引用动画的方式,它仅在该实体的范围内有效。

            "animations": {
                "look_at_target": "animation.common.look_at_target"
            }

现在,我们需要播放动画。 对于在实体存在时始终处于活动状态的简单动画,这和在客户端实体文件的 scripts/animate 数组中列出短名称一样简单。

            "scripts": {
                "animate": ["look_at_target"]
            }

现在,如果您在游戏中测试机器人,会看到它会转过头环顾四周。

创建动画

添加实体指南中,我们为机器人制作了一个小型的驾驶动画。 现在我们创建一个动画,当机器人失去脚下的地面(轮子)时播放。 在创建动画之前,请始终检查是否有触发它的方法。 我们可以很容易地为此触发一个失去平衡的动画,因为我们可以使用 Molang 查询 query.is_on_ground 来测试机器人何时不再接触地面。

Blockbench 中的动画控制

可以在文本编辑器中创建简单的动画,但对于更复杂的、基于关键帧的动画,使用 Blockbench 更为简便。 打开模型并切换到右上角的 Animate 选项卡。 在左侧的 Animations 面板中创建一个新动画,并将其命名为 animation.robot.sway。 您还可以选择更长的名称或包含命名空间以确保与其他加载项兼容。 但请记住,动画标识符仅支持使用蛇形命名、字符串和点,但不支持冒号或破折号。

设置好动画后,就可以开始制作动画了。 选择实体的根骨骼。 将时间线中的时间光标移动到 0 秒,然后点击“Rotation”旁边的加号图标。 这将在新位置创建一个新的关键帧。 现在将光标移动到大约 0.2 秒。 选择旋转工具,将整个机器人稍微向左旋转。 这将自动生成一个新的关键帧。 在屏幕的左侧,您可以看到这些值。 将其旋转约 10 度。

现在将时间向前移动大约半秒并将根骨骼旋转到另一侧。 最后,移动到 1 秒并将其旋转回 0。

现在,如果将光标移动到开头并按下播放键,您将看到一个短暂的摇摆动画。 您已经知道如何制作动画,您可以进一步优化动画,例如,让天线稍微摆动一下。

最后,按 Ctrl + S 保存模型和动画。 将动画保存在资源包的 animations 文件夹中,名为 robot.animation.json

现在在客户端实体文件中引用和播放动画,如我们在 look at 动画中所做的操作。 但是现在只会在机器人不在地面的情况下播放摇摆动画。 这看起来像这样:

            "animations": {
                "look_at_target": "animation.common.look_at_target",
                "sway": "animation.robot.sway"
            },
            "scripts": {
                "animate": [
                    "look_at_target",
                    {"sway":"!query.is_on_ground"}
                ]
            }

如果现在生成一个机器人并将其推下边缘,则会播放动画。 但它只会播放一次。

原因是脚本部分中的查询只是动画的混合值。 它定义了播放“多少”动画,而不是何时播放和不播放。 这就是为什么动画会在 !query.is_on_groundtrue/1 时开始播放,但它永远不会停止播放。 一旦该值再次为 false/0,它就会淡出,下次它会再次淡入动画。 它不会从头重新开始播放。

这种行为很适合用于没有开始也没有结束的静态或循环动画。 但是如果我们想在每次查询更改时启动动画,需要另一种方法。 这就是动画控制器的用武之地。

动画控制器

动画控制器与状态一起工作。 动画控制器可以有无限数量的状态。 每次只有其中一种状态处于活动状态。 控制器可以通过 Molang 表达式过渡到其他状态。 每个状态都可以播放一组不同的动画、声音和粒子效果。

每次客户端加载实体时,例如,当加入一个世界时,动画控制器都会以初始状态启动。 默认情况下,此状态名为 default

要设置动画控制器,请在资源包中创建一个名为 animation_controllers 的新文件夹。 在文件夹内,创建一个名为 robot.animation_controllers.json 的新文件。 创建一个如下的动画控制器:

{
    "format_version": "1.10.0",
    "animation_controllers": {
        "controller.animation.robot.ground": {}
    }
}

现在,我们需要创建一个初始状态。 默认情况下,此状态名为 default。 加载实体时,动画控制器将始终以这种状态启动。 例如,在重新加入世界之后。

这种状态的唯一作用是一旦实体不再在地面上就过渡到摇摆状态。 我们将为此使用 transition。 一旦 query.is_on_ground 查询不再为真,控制器就会切换到该状态。

{
    "format_version": "1.10.0",
    "animation_controllers": {
        "controller.animation.robot.ground": {
            "states": {
                "default": {
                    "transitions":[
                        {"swaying": "!query.is_on_ground"}
                    ]
                }
            }
        }
    }
}

现在,我们将添加 swaying(摇摆)状态。 此状态将播放摇摆动画,然后通过返回默认状态重置控制器。 我们可以使用查询 query.all_animations_finished 仅在动画播放后进行过渡。 此查询只会在当前状态的所有动画播放完毕后才返回 true。 此外,我们将再次测试该实体是否在地面上。

{
    "format_version": "1.10.0",
    "animation_controllers": {
        "controller.animation.robot.ground": {
            "states": {
                "default": {
                    "transitions":[
                        {"swaying": "!query.is_on_ground"}
                    ]
                },
                "swaying": {
                    "animations":[
                        "sway"
                    ],
                    "transitions":[
                        {"default": "query.all_animations_finished && query.is_on_ground"}
                    ]
                }
            }
        }
    }
}

现在,我们需要将动画控制器链接到我们的实体。 动画控制器的链接方式可以与客户端实体文件中的动画相同。 控制器在 animations 部分链接并在脚本中播放。

            "animations": {
                "look_at_target": "animation.common.look_at_target",
                "sway": "animation.robot.sway",
                "ground": "controller.animation.robot.ground"
            },
            "scripts": {
                "animate": [
                    "look_at_target",
                    "ground"
                ]
            }

如果您在游戏中对此进行测试,动画现在可以多次运行。 但是,您可能会注意到,根据动画的长度,如果机器人在很短的间隔内两次失去地面,第二次将不会播放动画。 这是因为第一个动画还没有完成,所以控制器还没有被重置为默认状态。

我们尝试另一种可以解决此问题的解决方案。 通过删除 all_animations_finished 查询,我们将在实体再次着陆时退出摇摆状态。 如果我们再次测试,动画将非常突然地停止。

为了防止这种情况,我们可以使用选项 blend_transition,它允许我们在设定的时间内平滑地过渡出动画。 这是动画控制器最重要的属性之一,甚至允许我们在实体的两个固定姿势之间创建简单的过渡。

最终,哪种解决方案最适用取决于用例。 在此例中,一旦机器人再次降落在地面上,动画就会平滑地淡出。

                "swaying": {
                    "animations":[
                        "sway"
                    ],
                    "transitions":[
                        {"default": "query.is_on_ground"}
                    ],
                    "blend_transition":0.5
                }

下一步内容?

我们现在已经学习了如何创建可用于动画的模型以及如何设置其材质。 我们还将现有动画链接到模型,并在 Blockbench 中创建了我们自己的动画。

如果您想在实体外观之外添加更多功能,请查看实体行为教程。