理由:前往英文页面获取最新版本的文档
Template:Bedrock Edition Developer Documentation
这是基岩版1.12.0的动画文档。
版本:1.12.0.28
概述
当前Minecraft的JSON规范如下:
- 字段应用小写和下划线来表示(无空格)。
- 在定义的目录和子路径下所有的json文件都将会被动画系统所读取使用。
开始
v1.7Beta升级至v1.8
我们根据反馈以及沿着路线来推进技术对代码进行了很小的修改和整理。如果需要升级以前的脚本,您需要对你的所有molang脚本执行以下步骤:
- entity.flags.foo --> query.foo
- entity.member.foo --> query.foo
- entity.foo --> variable.foo
- params.foo --> global.foo
- 一般的规则是
query
表示脚本所运行实体的只读值而variable
表示用户创建的读写值。 - 我们为所有名称采用了蛇形命名法[1]。如果你愿意的话也可以使用大写字母,因为我们不区分大小写,虽然我们一般建议使用蛇形命名法。
- 之前在生物上设置的一些变量被更改为使用
query.foo
的格式。浏览下方的更新列表来查看新内容和更改。
v1.8Beta升级至v1.10
1.10主要的三大改动如下:
- 动画具有在任意深层次结构中可以引用别的动画的能力。
- 动画控制器的参数部分替换成了
variables
部分。 - 在实体定义文件中,动画控制器现在列在
animation
部分中,并且添加了scripts animate
部分以定义要播放的根动画。
v1.8文件格式向后兼容v1.10,因此你不需要_need_
来改变任何东西(尽管我们建议按照v1.10的指导重构你的文件,因为新格式会有轻微的性能提升,并使它更容易理解。
添加动画
实体定义
为了让实体具有动画, 你必须将animations
和scripts/animate
部分添加到实体的实体定义文件中。
你能在这里看见pig.json
的的实体定义:
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
"identifier": "minecraft:pig",
"min_engine_version": "1.8.0",
"materials": { "default": "pig" },
"textures": {
"default": "textures/entity/pig/pig",
"saddled": "textures/entity/pig/pig_saddle"
},
"geometry": {
"default": "geometry.pig.v1.8"
},
"animations": {
"setup": "animation.pig.setup",
"walk": "animation.quadruped.walk",
"look_at_target": "animation.common.look_at_target",
"baby_transform": "animation.pig.baby_transform"
},
"scripts": {
"animate": [
"setup",
{ "walk": "query.modified_move_speed" },
"look_at_target",
{ "baby_transform": "query.is_baby" }
]
},
"render_controllers": [ "controller.render.pig" ],
"spawn_egg": {
"texture": "spawn_egg",
"texture_index": 2
}
}
}
}
注: 因为猪的行走动画与牛、羊的行走动画相同,所以应使用animation.quadruped.walk
而不是定义自己的。如果你想自定义一个新的行走动画,你可以修改这一行以指向你自定义的行走动画。
动画被规定为短名称,后可跟其完整的资源名称。该短名称能用于动画控制器和scripts/animate
列表,其后的完整名称用于动画文件。
在scripts/animate
部分,你需要列出播放的动画以及播放顺序。你能直接指定动画,也能指定混合表达式(blend expression)。
动画控制器
我们需要能够控制动画的播放方式、播放时间以及与其他动画的交互方式。 在实体定义“scripts”中管理大量动画的同时,对动画进行分组动画。控制器示例:
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.my_mob.move": {
"initial_state": "moving",
"states": {
"moving": {
"animations": [
"wag_tail",
"wiggle_ears",
{ "walk": "query.modified_move_speed" }
],
"transitions": [
{ "grazing": "query.is_grazing" }
]
},
"grazing": {
"animations": [ "grazing" ],
"transitions": [
{ "moving": "query.all_animations_finished" }
]
}
}
}
}
}
动画
在每帧开始时,骨骼将从其几何定义重置为其默认姿势,然后按顺序为每个通道添加动画。注意通道(x,y,z),动画数据可以是原始数据。
默认情况下,旋转以度为单位,采用先x后y最后z的格式。
"rotation": [90.0, 0.0, 0.0]
也可以是运行时才计算的脚本:
"rotation": ["cos(query.anim_pos * 38.17) * 80.0 * query.anim_speed", 0.0, 0.0]
下面是原版资源包中的animation文件夹中的quadruped.animation.json
示例:
{
"format_version": "1.8.0",
"animations": {
"animation.quadruped.walk": {
"anim_time_update": "query.modified_distance_moved",
"loop": true,
"bones": {
"leg0": { "rotation": [ "Math.cos(query.anim_time * 38.17) * 80.0", 0.0, 0.0 ] },
"leg1": { "rotation": [ "Math.cos(query.anim_time * 38.17) * -80.0", 0.0, 0.0 ] },
"leg2": { "rotation": [ "Math.cos(query.anim_time * 38.17) * -80.0", 0.0, 0.0 ] },
"leg3": { "rotation": [ "Math.cos(query.anim_time * 38.17) * 80.0", 0.0, 0.0 ] }
}
}
}
}
动画层次
动画是基于通道的(旋转、缩放或平移),在此范围内,它们是关键帧:
EntityAnimation: (动画实体)动画的名称 __BoneAnimation[]: (动画骨骼)进行此动画的骨骼名称 ____AnimationChannel[]: (动画通道)动画的实现方式。旋转、缩放或平移 ______KeyFrame[]: (关键帧)指定这个通道在一个特定时间的值
以上所有概念都在下面详细的自下而上的方法中描述。
名称
所有名称(动画、骨骼、状态),都必须以字母开头,并且只包含字母数字、下划线或句点。建议使用全部小写的名称
变换
- 操作顺序:对顶点进行缩放、旋转和平移.
- 假设动画数据是分层的,并按名称应用于骨骼,将动画数据中的骨骼名称与目标几何体的骨架匹配。.
- 不是所有的骨头都需要动画.
- 可以设置目标几何体中不存在的骨骼的动画(忽略丢失的骨骼).
- 对于每个比例、旋转、位置,都可以使用单个值单独或均匀地设置字段。例如,它们是等效的:
"scale": [2.0, 2.0, 2.0] "scale": 2.0 "scale": [2.0]
通道(旋转、位移、缩放)方法
引擎分别跟踪旋转、位置和缩放的动画。在一个通道中,一个或多个关键帧是从动画开始的任意时间(以秒为单位)指定的。
实体动画格式示例
动画的JSON格式如下:
注:与几何格式匹配,单位为1/16米。
"<animation_name>": {
// (动画名称<字符串>)
// ↓可选参数↓
"loop": <bool> //(循环<布尔值>)默认为false。设置动画是否循环,也就是在执行完毕后不退出,而是重新从t=0.0的状态开始
"blend_weight": <expression> //(混合权重<表达式>)默认为字符串"1.0"。设置这个动画与其他动画的混合程度。设置为0.0为关闭、1.0则为使用所有的变换。也可以填入表达式(见下方的动画控制器章节)
"animation_length": <float> //(动画长度<浮点数>)默认为上一次关键帧的时间。系统将会在这个时间结束动画(或者开始新的循环)。
"override_previous_animation": <bool> //(覆盖之前的动画<布尔值>)默认为false。决定是否在此动画展示前将动画姿态设为绑定的姿态,从而覆盖之前动画的操作。
// ↓必需参数↓
"bones": [
//(骨头)
{
"<bone_name>": { // (骨骼名称)必须与几何骨骼(Geometry Skeleton)中指定的骨骼名称匹配。
// 下面是一些设定数据
// 省略通道会导致该通道在此动画展示时在动画的相应骨头上被跳过。
// 任何下面参数的浮点数都可以用字符串表达式替代。当然,你也不必把所有参数都换成基于表达式的。
//↓位置更改↓
"position": 1.0, // 这意味着将x,y,z的坐标设为1
"position": [1.0], // 这也意味着将x,y,z的坐标设为1
"position": [1.0, 2.0, 3.0], // 这意味着将x、y、z的坐标分别设为1、2、3
//↓旋转↓
"rotation": 45.0, // 将x、y、z的旋转角度均设为45度
"rotation": [45.0], // 仍然是将x、y、z的旋转角度设为45度
"rotation": [30.0, 0.0, 45.0], // 将x、y、z的旋转角度设为对应的度值(30、0、45)
//↓缩放↓
// 注:当前只支持非拉伸缩放
"scale": 2.0, // 缩放骨骼到原来的2.0倍
"scale": [2.0], // 也是缩放骨骼到原来的2.0倍
// ↓关键帧数据在下面定义↓
// 注:上面提到的所有格式(表达式等)都可以用于"pre"和"post"的值,并且他们的值可以使用不同的格式(就如例子里做的)
// ↓旋转↓
"rotation": {
"0.0": [80.0, 0.0, 0.0],
"0.1667": [-80.0, 0.0, 0.0],
"0.333": [80.0, 0.0, 0.0]
}
// 对于非连续曲线的通道变化,可以为前后插值指定不同的值(类似于左极限/右极限)
"rotation": {
"0.3": { // 这里的键("0.3")表示该关键帧的时间戳,其值可以使用上面提到的任何形式表示
"pre": [30.0, 0.0, 45.0], //(前)当动画插值到该帧时,使用这个值when interpolating towards this key frame from the previous, use this value
"post": "180.0 * Math.Sin(global.key_frame_lerp_time)" //(后)当动画从该帧开始插值时,使用这个值
}
}
// ↓另一个例子↓
"rotation": {
"0.0": [80.0, 0.0, 0.0], // 以x旋转80度的状态开始
"0.4": {
"pre": [80.0, 0.0, 0.0], // 在0.4秒之前,一直保持80度的状态
"post": [0.0, 0.0, 0.0], // 瞬间跳到x旋转0度的状态
},
"0.8": [-80.0, 0.0, 0.0] // 用上一帧来线性插值,用0.8秒过渡到x旋转-80度的状态
}
}
]
}
关键帧
关键帧为特定通道在指定时间转换为特定骨骼定义两个值,一个值是随着时间接近关键帧时间,另一个值是从该关键帧时间开始的。
插值
目前只支持线性插值。关键帧“pre”和“post”设置允许控制任何关键帧的插值曲线。
- 连续示例:
此示例在1秒内围绕Y轴1旋转骨骼“头部”。
"head": {
"rotation": {
"0.0":[0, 0, 0],
"0.5": [ 0, 180, 0],
"1.0": [0, 360, 0]
}
}
- 单个示例:
不连续仅仅意味着关键帧之间不会有平滑的过渡。如果你想马上发生什么事,这很有用。
此示例缩放骨骼“头”:
1.从0到0.5秒(在“pre”标签中),头部骨骼在所有尺寸上都设置为1的正常比例[x,y,z]
2.在0.5秒时,骨骼将立即扩大到正常大小的2倍,然后
3.从0.5秒到1秒(“post”),骨骼将重新缩放到其所有尺寸的正常比例1。
请注意,在上述文件格式的较大示例中,“pre”和“post”也可以由运行时计算该值的molang表达式定义。允许您有一个数学定义的曲线,而不是纯线性的。
"head": {
"scale": {
"0.5": {
"pre": [1, 1, 1],
"post": 2.0
}
"1.0": [ 1.0 ]
}
}
动画控制器
动画控制器决定播放哪些动画。每个控制器包含播放一个或多个动画的状态列表,每个动画可以在一个或多个参数上混合/控制。
动画控制器格式:
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.sheep.move": {
"states": {
"default": {
"animations": [
{ "walk": "query.modified_move_speed" }
],
"transitions": [
{ "grazing": "query.is_grazing" }
]
},
"grazing": {
"animations": [ "grazing" ],
"transitions": [
{ "default": "query.all_animations_finished" }
]
}
}
}
}
}
状态
状态定义了一组要处理的动画(每个动画都可以有自己的混合值)。每个状态都有一个可选的变量部分,列出引用动画可以使用的任何数量的变量。每个状态也有一个或多个动画,使用实体定义中给定的名称。
- 状态变量
变量可以由游戏设置,也可以由用户定义的脚本设置,该脚本可以在definitions/entity/<entity_name>.json中的实体定义JSON中找到. 变量的值由molang表达式设置。它们还可以通过线性插值曲线重新映射其值。
示例:
这定义了具有单一状态的控制器。
它将创建一个变量variable.ground_speed_curve
它仅在处理该帧的动画控制器时才存在于实体上。
它的价值在于query.ground_speed
, 然后在0.2及0.7之间重新映射基于query.ground_speed
从0.0到1.0.它将播放一个动画漫游,当地面速度从停止增加到2.3 m/s时,它将从0.0混合到1.0。
重映射曲线可以有任意数量的条目。
然后动画控制器将播放引用的实体 wiggle_nose
动画,然后是walk
动画, 按以下值缩放后者variable.ground_speed_curve
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.sheep.move": {
"states": {
"default": {
"variables": {
"ground_speed_curve": {
"input": "query.ground_speed",
"remap_curve": {
"0.0": 0.2,
"1.0": 0.7
}
}
},
"animations": [
"wiggle_nose",
{ "walk": "variable.ground_speed_curve" }
]
}
}
}
}
}
- 用户定义的脚本示例
此脚本将把foo设置为query.life的sine-of-query.life的结果,以便稍后在动画或动画控制器中使用。
注意:“pre-animation”告诉脚本在动画发生之前,在一帧中计算出这些变量的值,以便动画可以在自己的公式中使用这些值。如果变量不存在,它将创建一个新变量,其默认值将为0.0。
在definitions\entity\tiger.json中:
{
"custom:tiger":{
"scripts":{
"pre_animation": {
"variable.foo = math.sin(query.life_time)"
}
}
}
}
注意在这个例子中,由于foo等于sin波,所以它的值将在-1到1之间。这意味着您将有一个从0到-1到0的时间段,其中只播放“基础动作”,然后在相同的时间段内,当foo从0到1回到0时,walk将在基础姿势的顶部播放。基础姿势的混合值为1.0。
"controller.animation.tiger.move": {
"states": {
"default": {
"animations": [
//animations are ADDITIVE unless otherwise specified
//in this case, base_pose will always be playing in the default state
//walk will play as well if Entity.foo is greater than 0.0
"base_pose",
{ "walk": "variable.foo > 0.0" }
]
}
}
}
状态过渡
状态可以指定按顺序列出的任意数量的转换脚本。每个转换都有一个要切换到的目标状态,以及一个脚本来决定是否应该切换。 对于每个顺序的转换,计算脚本,如果它返回非零,则立即切换到指定的状态。
注意:每帧只处理一个转换。
"<controller_name>": {
"states": {
"<state_name>": {
...
"transitions": [
// 按顺序计算以下表达式。
// 第一个返回非零的是要转换到的状态。
//如果都是零,那么不要过渡
{ "<target_state_name_A>", "<expression>" },
{ "<target_state_name_B>", "<expression>" },
...
]
}
},
...
}
示例:
"controller.animation.tiger.move": {
"states": {
"default": {
"animations": [ "base_pose", "walk" ],
"transitions": [
{ "angry": "query.is_angry" }, // 如果query.is_angry返回true,则转换为愤怒状态
{ "tired": "variable.is_tired" } // 如果variable.is_tired返回true,则转换为累态。
]
},
"angry": {
"animations": [ "roar", "extend_claws" ],
"transitions": [
{ "default": "query.any_animation_finished" } // 当咆哮动画或伸爪动画结束时,切换回默认状态
]
},
"tired": {
"animations": [ "yawn", "stretch" ],
"transitions": [
{ "default": "query.all_animation_finished" }
//当哈欠与拉伸动画都完成时,转换回默认状态
]
}
}
}
状态混合
如果您希望在转换时在状态之间有交叉淡入淡出,只需将“混合切换”设置为您希望系统在两个状态之间进行混合的时间。那将会通过在指定时间内对两个状态使用线性插值来过渡。
示例:
"controller.animation.tiger.move": {
"states": {
"default": {
"animations": [ "base_pose", "walk" ],
"transitions": [
{ "angry": "query.is_angry" } //如果query.is_angry返回true,则转换为愤怒状态
],
"blend_transition": 0.2 // 从该状态转换时,交叉淡入的时间将会超过0.2秒
},
"angry": {
"animations": [ "roar", "extend_claws" ],
"transitions": [
{ "default": "query.any_animation_finished" } // 当咆哮动画或伸爪动画完成时切换回默认状态
]
}
}
}
渲染控制器
渲染控制器需要一个标识符,并且需要遵循“controller.render.<name>”的格式。此名称需要与客户机实体定义JSON中设置的名称匹配。
渲染控制器是播放机确定实体上渲染内容的一种方法。玩家可以设置实体的几何体、材质、纹理和零件可见性。除了直接设置键,玩家还可以使用数组让实体在不同选项之间进行选择。
开始
要开始在资源包的根目录中创建一个名为“render_controllers”的新文件夹,您需要在其中添加新的render controller json。
豹猫的渲染控制器JSON示例:
"format_version": "1.8.0",
"render_controllers": {
"controller.render.ocelot": {
"arrays": {
"textures": {
"Array.skins": ["Texture.wild", "Texture.black", "Texture.red", "Texture.siamese"]
}
},
"geometry": "Geometry.default",
"materials": [{ "*": "Material.default" }],
"textures": ["Array.skins[query.variant]"]
}
}
示例
羊JSON的几何数组示例
"arrays": {
"geometries": {
"Array.geos": ["Geometry.default", "Geometry.sheared"]
}
},
"geometry": "Array.geos[query.is_sheared]",
蜘蛛JSON的材质示例数组
"arrays": {
"materials": {
"Array.materials": ["Material.default", "Material.invisible"]
}
},
"materials": [{ "*": "Array.materials[query.is_invisible]" }],
村民JSON的纹理示例数组
"arrays": {
"textures": {
"Array.skins": ["Texture.farmer", "Texture.librarian", "Texture.priest", "Texture.smith", "Texture.butcher"]
}
},
"textures": ["Array.skins[query.variant]"]
盔甲渲染控制器JSON中骨骼着色器的颜色示例:
"format_version": "1.8.0",
"render_controllers": {
"controller.render.armor.chest.v1.0": {
"arrays": {
"materials": {
"array.armor_material": [
"material.armor",
"material.armor_enchanted",
"material.armor_leather",
"material.armor_leather_enchanted"
]
},
"textures": {
"array.armor_texture": [
"texture.leather",
"texture.chain",
"texture.iron",
"texture.diamond",
"texture.gold"
]
}
},
//对于在同一生物上进行多贴图的调用渲染方式
"geometry": "geometry.armor",
"materials" : [
{ "body": "array.armor_material[query.armor_material_slot(1)]" },
{ "leftarm": "array.armor_material[query.armor_material_slot(1)]" },
{ "rightarm": "array.armor_material[query.armor_material_slot(1)]" }
],
//对于单个骨骼的调用渲染方式
"part_visibility" : [
{ "*": 0 },
{ "body": "query.has_armor_slot(1)" },
{ "leftarm": "query.has_armor_slot(1)" },
{ "rightarm": "query.has_armor_slot(1)" }
],
"color": {
"r": "query.armor_color_slot(1, 0)",
"g": "query.armor_color_slot(1, 1)",
"b": "query.armor_color_slot(1, 2)",
"a": "query.armor_color_slot(1, 3)"
},
"textures": ["array.armor_texture[query.armor_texture_slot(1)]", "texture.enchanted"]
}
}
凋灵渲染控制器JSON的overlay_color示例:
"format_version": "1.8.0",
"render_controllers": {
"controller.render.wither_boss": {
"arrays": {
"textures": {
"Array.wither_state": ["Texture.invulnerable", "Texture.default"]
}
},
"geometry" : "Geometry.default",
"materials" : [{ "*": "Material.default" }],
"textures" : ["Array.wither_state[variable.display_normal_skin]"],
"overlay_color" : {
"r": "variable.is_invulnerable ? 1.0 : this",
"g": "variable.is_invulnerable ? 1.0 : this",
"b": "variable.is_invulnerable ? 1.0 : this",
"a": "variable.is_invulnerable ? query.overlay_alpha : this"
}
}
}
part_visibility示例,用于从羊驼json打开和关闭部分骨骼的可见性:
"format_version": "1.8.0",
"render_controllers": {
"controller.render.llama": {
"arrays": {
"textures": {
"Array.base": ["Texture.creamy", "Texture.white", "Texture.brown", "Texture.gray"],
"Array.decor": ["Texture.decor_none", "Texture.decor_white", "Texture.decor_orange", "Texture.decor_magenta", "Texture.decor_light_blue", "Texture.decor_yellow", "Texture.decor_lime", "Texture.decor_pink", "Texture.decor_gray", "Texture.decor_silver", "Texture.decor_cyan", "Texture.decor_purple", "Texture.decor_blue", "Texture.decor_brown", "Texture.decor_green", "Texture.decor_red", "Texture.decor_black"]
}
},
"geometry": "Geometry.default",
"part_visibility": [{ "chest*": "query.is_chested" }],
"materials": [{ "*": "Material.default" }],
"textures": [
"Array.base[query.variant]",
"Array.decor[variable.decor_texture_index]",
"Texture.decor_none"
]
}
}
注意:材质和骨骼可见性的数组按指定的顺序应用。文件后面指定的材质和骨骼可见性将覆盖以前的材质或骨骼。
来自Horse渲染控制器的材质数组示例。马鞍将超越鬃毛,这将超越尾毛等:
"materials": [
{ "*": "Material.default" },
{ "TailA": "Material.horse_hair" },
{ "Mane": "Material.horse_hair" },
{ "*Saddle*": "Material.horse_saddle" }
],
参见
- ↑ 指所有字母小写,用下划线分词的一种英文变量命名法。