教程:制作附加包/实体

来自Minecraft基岩版开发Wiki
实体
系列教程
所属系列
难度
中级
前置知识
适用版本
国际版
实践设备
WindowsAndroidIOSMacOS
所需软件

引言[编辑]

与物品不同,实体的自定义要由两部分完成:

  • 服务端(纹理、名称、动画、声音)
  • 客户端(行为、属性)

除此之外,我们还需要准备实体的模型及动画,关于这部分内容后面的章节将详细讲述[1]

添加实体[编辑]

服务端[编辑]

实体的服务端文件与物品非常相似,我们只需要在行为包/entities文件夹下新建一个名为custom_entity.json的文件并插入以下内容即可:

{
	"format_version": "1.16.0",
	"minecraft:entity": {
		"description": {
			"identifier": "wiki:custom_entity",
			"is_summonable": true,
			"is_spawnable": true,
			"is_experimental": false
		},
		"components": {
			"minecraft:type_family": {
				"family": ["monster"]
			},
			"minecraft:health": {
				"value": 20,
				"max": 20
			},
			"minecraft:attack": {
				"damage": 3
			},
			"minecraft:movement": {
				"value": 0.2
			},
			"minecraft:collision_box": {
				"width": 1,
				"height": 2
			},
			"minecraft:loot": {
				"table": "loot_tables/entities/custom_entity.json"
			},

			"minecraft:movement.basic": {},
			"minecraft:navigation.walk": {
				"can_walk": true,
				"avoid_sun": true,
				"can_pass_doors": true,
				"can_open_doors": true
			},

			"minecraft:behavior.random_stroll": {
				"priority": 6,
				"speed_multiplier": 1
			},
			"minecraft:behavior.random_look_around": {
				"priority": 7
			},
			"minecraft:behavior.look_at_player": {
				"priority": 7,
				"look_distance": 6,
				"probability": 0.02
			},
			"minecraft:behavior.hurt_by_target": {
				"priority": 1
			},
			"minecraft:behavior.nearest_attackable_target": {
				"priority": 2,
				"within_radius": 25,
				"reselect_targets": true,
				"entity_types": [
					{
						"filters": {
							"any_of": [
								{
									"test": "is_family",
									"subject": "other",
									"value": "player"
								}
							]
						},
						"max_dist": 35
					}
				]
			},
			"minecraft:behavior.delayed_attack": {
				"priority": 0,
				"attack_once": false,
				"track_target": true,
				"require_complete_path": false,
				"random_stop_interval": 0,
				"reach_multiplier": 1.5,
				"speed_multiplier": 1,
				"attack_duration": 0.75,
				"hit_delay_pct": 0.5
			}
		}
	}
}

实体描述[编辑]

"description": {
	"identifier": "wiki:custom_entity",
	"is_summonable": true,
	"is_spawnable": true,
	"is_experimental": false
}

描述存储了此实体的最基础的一些属性:

  • identifier:实体的赋命名空间标识符,此处不再赘述
  • is_summonable:实体是否可以使用/summon命令召唤
  • is_spawnable:实体是否可以使用刷怪蛋或生成规则在世界中生成
  • is_experimental:实体实体是否只能添加到开启了实验性玩法的世界

实体组件[编辑]

组件定义了实体更高级的属性,其包含基础组件、AI意向、触发器等多种类型,关于组件的更多信息,参见Manual:数据驱动/实体

基础组件[编辑]
"minecraft:type_family": {
	"family": ["monster"]
},
"minecraft:health": {
	"value": 20,
	"max": 20
},
"minecraft:attack": {
	"damage": 3
},
"minecraft:movement": {
	"value": 0.2
},
"minecraft:collision_box": {
	"width": 1,
	"height": 2
},
"minecraft:loot": {
	"table": "loot_tables/entities/custom_entity.json"
}

基础组件设置实体的生命值、移动速度、战利品、碰撞箱等属性,在上面的示例中:

运动机制[编辑]
"minecraft:physics": {},
"minecraft:jump.static": {},
"minecraft:movement.basic": {},
"minecraft:navigation.walk": {
	"can_walk": true,
	"avoid_sun": true,
	"can_pass_doors": true,
	"can_open_doors": true
}

运动机制由一些特殊的组件定义:

  • minecraft:physics将重力和碰撞应用于实体
  • minecraft:jump.static使实体可以跳跃
  • minecraft:movement.basic允许实体在方块行走
  • minecraft:navigation.walk定义了实体遵循的路径
AI意向[编辑]
"minecraft:behavior.random_stroll": {
	"priority": 6,
	"speed_multiplier": 1
},
"minecraft:behavior.random_look_around": {
	"priority": 7
},
"minecraft:behavior.look_at_player": {
	"priority": 7,
	"look_distance": 6,
	"probability": 0.02
},
"minecraft:behavior.hurt_by_target": {
	"priority": 1
},
"minecraft:behavior.nearest_attackable_target": {
	"priority": 2,
	"within_radius": 25,
	"reselect_targets": true,
	"entity_types": [
		{
			"filters": {
				"any_of": [
					{
						"test": "is_family",
						"subject": "other",
						"value": "player"
					}
				]
			},
			"max_dist": 35
		}
	]
},
"minecraft:behavior.delayed_attack": {
	"priority": 0,
	"attack_once": false,
	"track_target": true,
	"require_complete_path": false,
	"random_stop_interval": 0,
	"reach_multiplier": 1.5,
	"speed_multiplier": 1,
	"attack_duration": 0.75,
	"hit_delay_pct": 0.5
}

AI意向定义了实体将在何时做何事。

所有AI意向都包含一个名为priority(优先级)的字段,其将会确定在可以在何时执行意向。

当实体选择要执行的意向时,它会从最低优先级到最高优先级搜索并排列其所有行为,并执行选择选中的意向,因此,建议将一些重要的意向的优先级设置为01[1]

至此,实体的服务端文件便设置好了,接下来我们将学习实体的客户端文件。

这时如果打开世界并尝试使用命令召唤实体,它的行为应该像我们预期的那样。但地面上只会有一个影子,且实体名称是一个本地化键名,这是因为我们还没有设置客户端文件

实体的客户端文件与物品或实体服务端文件区别较大,且包含动画、动画控制器、渲染控制器等多部分,下节我们就将学习实体的客户端配置。

客户端[编辑]

模型[编辑]

{
	"format_version": "1.12.0",
	"minecraft:geometry": [
		{
			"description": {
				"identifier": "geometry.custom_entity",
				"texture_width": 16,
				"texture_height": 16,
				"visible_bounds_width": 3,
				"visible_bounds_height": 3,
				"visible_bounds_offset": [0, 0.5, 0]
			},
			"bones": [
				{
					"name": "bb_main",
					"pivot": [0, 0, 0],
					"cubes": [
						{"origin": [-8, 0, -8], "size": [16, 16, 16], "uv": [-14, -14]}
					]
				}
			]
		}
	]
}

模型,又称几何,决定了实体的形状。实体的模型按照JSON格式存储在资源包/models/entity文件夹中,得益于Blockbench等工具,我们不必详细学习其语法。

上面的代码示例就是在Blockbench内自动生成的一个类似于原版史莱姆的模型,请注意,此示例不可以直接拿来使用。

我们唯一需要注意的是字符串identifier,这是模型的赋命名空间标识符,一般格式为geometry.<模型名称>,我们后面需要利用它来调用模型。

纹理[编辑]

纹理,决定了实体的外观,实体的纹理一般是.png文件。为了保证模型与纹理完美契合,我们通常会在Blockbench中生成一个模板纹理,然后对这个模板纹理进行绘制,绘制完成后我们将其放入资源包/textures/entity中即可。

动画[编辑]

{
	"format_version": "1.8.0",
	"animations": {
		"animation.custom_entity.move": {},
		"animation.custom_entity.idle": {}
	}
}

动画让实体更加栩栩如生,我们可以根据需要为实体提供任意数量的动画。

在上面的示例中,animation.custom_entity.move是动画的标识符。除此之外,笔者省去了动画的执行过程而只保留动画的标识符,这在实际中是不允许的。

与模型类似,动画也是在Blockbench中自动生成的,因此我们不必学习其语法。

我们将动画文件放入资源包/animations文件夹中,但此时我们还不能正常触发它,因为这是是动画控制器的职责。

动画控制器[编辑]

{
    "format_version": "1.12.0",
    "animation_controllers": {
        "controller.animation.custom_entity.walk": {
            "initial_state": "standing",
            "states": {
                "standing": {
                    "blend_transition": 0.2,
                    "animations": [
                        "idle"
                    ],
                    "transitions": [
                        {
                            "moving": "q.modified_move_speed > 0.1"
                        }
                    ]
                },
                "moving": {
                    "blend_transition": 0.2,
                    "animations": [
                        "move"
                    ],
                    "transitions": [
                        {
                            "standing": "q.modified_move_speed < 0.1"
                        }
                    ]
                }
            }
        }
    }
}

动画控制器控制动画的播放方式,其由状态和状态之间的过渡组成。这使我们能够在实体处于某些状态时播放某些动画,当满足某些条件时,我们可以在它们之间转换。

"standing": {
                    "blend_transition": 0.2,
                    "animations": [
                        "idle"
                    ],
                    "transitions": [
                        {
                            "moving": "q.modified_move_speed > 0.1"
                        }
                    ]
                },
                "moving": {
                    "blend_transition": 0.2,
                    "animations": [
                        "move"
                    ],
                    "transitions": [
                        {
                            "standing": "q.modified_move_speed < 0.1"
                        }
                    ]
                }

可以看到,我们设置了两个状态:standing(站立)和moving(移动)。

     "transitions": [
                        {
                            "standing": "q.modified_move_speed < 0.1"
                        }
                    ]

通过设置transitions,我们可以让动画的状态相互转换。其中前一个值[注 1]是将要转换的状态名称,后一个值[注 2]是通过Molang设置的转换的条件。

现在动画控制器编写完成,我们将其放到资源包/animation_controllers中即可。

渲染控制器[编辑]

{
	"format_version": "1.10.0",
	"render_controllers": {
		"controller.render.custom_entity": {
			"geometry": "geometry.default",
			"materials": [
				{
					"*": "material.default"
				}
			],
			"textures": ["texture.default"]
		}
	}
}

渲染控制器帮助开发者控制生物如何渲染在游戏世界中的表现,其存储在资源包/render_controllers文件夹中,与动画控制器同为自定义实体最难的两个部分。

原版实体中,不是所有生物都只有单一表现。例如村民根据群系拥有不同皮肤,热带鱼拥有数千种组合,狼在生气时会红眼等,这些都是由渲染控制器所控制。[2]

作为初学者,我们无需制作太复杂的渲染控制器,上面的示例即可满足我们的需求,其将从实体客户端文件中获取并采用默认材质、纹理、模型。

客户端实体[编辑]

{
	"format_version": "1.10.0",
	"minecraft:client_entity": {
		"description": {
			"identifier": "wiki:custom_entity",
			"materials": {
				"default": "entity_alphatest"
			},
			"textures": {
				"default": "textures/entity/custom_entity"
			},
			"geometry": {
				"default": "geometry.custom_entity"
			},
			"scripts": {
				"animate": ["walk_controller"]
			},
			"animations": {
				"walk_controller": "controller.animation.custom_entity.walk",
				"idle": "animation.custom_entity.idle",
				"move": "animation.custom_entity.move"
			},
			"spawn_egg": {
				"overlay_color": "#114514",
				"base_color": "#9f2333"
			},
			"render_controllers": ["controller.render.custom_entity"]
		}
	}
}

客户端实体将动画、纹理、模型整合到一起,存储在资源包/entity文件夹下,其中:

  • identifier:实体的赋命名空间标识符,值应与服务端文件保持一致
  • materials:材质类型,这里选用entity_alphatest以支持透明纹理
  • geometry:实体模型,填写模型的赋命名空间标识符
  • textures:实体纹理,填写纹理路径
动画短名称[编辑]
"animations": {
	"walk_controller": "controller.animation.custom_entity.walk",,
	"idle": "animation.custom_entity.idle",
	"move": "animation.custom_entity.move"
}

动画控制器或动画想要在实体中被引用就必须在客户端文件中的animations对象定义短名称,其中前一个值[注 3]是短名称,后一个值[注 4]是动画的赋命名空间标识符。

脚本[编辑]
"scripts": {
	"animate": [
		"walk_controller"
	]
}

脚本决定实体在哪些特定时间执行哪些某些操作,其中animate数组将在每一刻执行数组内的动画或动画控制器。

现在,我们的动画应该可以正常工作了。

刷怪蛋[编辑]
"spawn_egg": {
	"overlay_color": "#114514",
	"base_color": "#9f2333"
}
"spawn_egg": {
	"texture": "<物品纹理短名称>"
}

spawn_egg对象将为实体自动生成一个刷怪蛋,其有两种写法:

  • 使用十六进制RGB代码为刷怪蛋自动着色
  • 使用物品纹理短名称自定义刷怪蛋纹理

本地化文件[编辑]

我们的实体还没有自己的名称,我们只需要进入或创建资源包/texts/zh_CN.lang文件,插入以下内容:

entity.wiki:custom_entity.name=自定义实体

item.spawn_egg.entity.wiki:custom_entity.name=自定义实体

大功告成!现在你的实体已经可以正常显示在Minecraft中了,恭喜!

注释[编辑]

  1. 这里是standing
  2. 这里是q.modified_move_speed < 0.1
  3. 在这里是move
  4. 在这里是animation.custom_entity.move

参考[编辑]

< 战利品表 | 动画与渲染 >