附加包中的每个生物都有一个行为文件。它决定生物有多少生命值、如何移动、攻击什么,以及如何随时间变化。本页以红宝石傀儡为例,把这个文件一块一块地拆开讲解。
如果你从没做过生物,请先从你的第一个自定义生物开始。本页会更深入地讲解这个文件是如何组织的。
文件
行为文件放在行为包的 entities 文件夹中。文件名由你决定,不过以生物的名字命名会更整洁。
BP/
entities/
ruby_golem.json
spawn_rules/
ruby_golem.json生物的外观是在资源包中的另一个文件里设置的。参见客户端实体文件。
四个部分
minecraft:entity 内部最多有四个块。只有 description 是必需的,但几乎每个生物四个都会用到。
| 部分 | 包含的内容 |
|---|---|
description | 生物的 ID 和几个开关:能否有刷怪蛋、能否用 /summon 召唤、存储哪些属性 |
components | 生物始终拥有的东西:生命值、移动、碰撞箱、基础行为 |
component_groups | 具名的组件集合,之后可以开启和关闭,比如“幼年”或“愤怒” |
events | 具名的动作,用来开启和关闭这些组件集合 |
这是一个空的骨架:
{
"format_version": "1.26.50",
"minecraft:entity": {
"description": {},
"components": {},
"component_groups": {},
"events": {}
}
}format_version 告诉游戏你的文件遵循哪个版本的规则。请使用较新的版本,比如原版实体所使用的版本。
第 1 部分:description
"description": {
"identifier": "wiki:ruby_golem",
"is_spawnable": true,
"is_summonable": true
}| 字段 | 作用 |
|---|---|
identifier | 生物的 ID,格式为 命名空间:名称。它必须与资源包文件完全一致。自己的生物千万不要使用 minecraft 命名空间。 |
is_spawnable | 设为 true 时,生物会有刷怪蛋,并且生成规则可以把它放到世界中。 |
is_summonable | 设为 true 时,可以用 /summon 命令召唤它。 |
runtime_identifier | 可选。借用某个原版生物隐藏的硬编码行为,比如 minecraft:snowball。大多数生物用不到它。 |
properties | 可选。生物会记住的数值,下面会讲解。 |
很多原版生物还有一行 spawn_category,比如 "creature" 或 "monster"。你的生物没有它也能正常工作。
属性:生物会记住的数值
属性是存储在每个生物身上的小块数据。你可以通过事件修改它们,用过滤器检测它们,还可以在 Molang 中用 q.property('wiki:mood') 读取它们。
"properties": {
"wiki:mood": {
"type": "enum",
"values": ["calm", "angry"],
"default": "calm",
"client_sync": true
},
"wiki:rubies_eaten": {
"type": "int",
"range": [0, 5],
"default": 0
}
}| 类型 | 存储 | 额外字段 |
|---|---|---|
bool | true 或 false | 无 |
int | 整数 | range:允许的最小值和最大值 |
float | 小数 | range:允许的最小值和最大值 |
enum | 列表中的一个词 | values:允许的词列表 |
default是初始值。它也可以是一个 Molang 表达式,原版的蜜蜂就是用它来计算初始状态的。client_sync会把这个值发送给资源包,这样动画和渲染控制器就能使用它。只有当外观依赖这个值时才开启它。
用属性还是组件组?
当生物需要表现出不同的行为时,使用组件组。当你只是需要记住某个东西,或者模型、纹理需要随之变化时,使用属性。
第 2 部分:components
components 从生物生成的那一刻起就始终生效。把那些永远不变的东西放在这里:它的类型族、碰撞箱、物理效果和行走方式。
"components": {
"minecraft:type_family": { "family": ["ruby_golem", "golem", "mob"] },
"minecraft:health": { "value": 40, "max": 40 },
"minecraft:collision_box": { "width": 1.2, "height": 2.4 },
"minecraft:physics": {},
"minecraft:movement": { "value": 0.25 },
"minecraft:movement.basic": {},
"minecraft:navigation.walk": { "avoid_water": true },
"minecraft:jump.static": {},
"minecraft:behavior.random_stroll": { "priority": 6, "speed_multiplier": 0.8 },
"minecraft:behavior.look_at_player": { "priority": 7, "look_distance": 8 }
}每个键是一个组件,它的对象里放的是该组件的设置。空对象 {} 表示“使用默认值”。可供选择的组件有好几百个:在实体组件中可以浏览全部。
第 3 部分:组件组
组件组是一个具名的组件集合,在被事件添加之前一直处于关闭状态。正是靠它,同一个生物才能从幼年变成成年,或者从平静变得愤怒。
"component_groups": {
"wiki:baby": {
"minecraft:is_baby": {},
"minecraft:scale": { "value": 0.5 },
"minecraft:ageable": {
"duration": 1200,
"grow_up": { "event": "wiki:grow_up", "target": "self" }
}
},
"wiki:angry": {
"minecraft:attack": { "damage": 6 },
"minecraft:behavior.melee_attack": { "priority": 3 },
"minecraft:movement": { "value": 0.32 }
}
}有几条规则值得了解:
- 组名由你决定。加上你的命名空间(
wiki:angry)可以避免冲突,也更容易辨认。 - 每个组件在一个生物身上只能有一份。当添加一个带有
minecraft:movement的组时,会使用它的速度,替换掉生物原来的速度。 - 添加一个已经生效的组时,会重新启动其中的组件。比如
minecraft:timer会重新从零开始计时。
第 4 部分:事件
事件就是开关。每个事件都有一个名称和一份要做的事情列表,最常见的是对组件组的 add 和 remove。
"events": {
"wiki:grow_up": {
"remove": { "component_groups": ["wiki:baby"] }
},
"wiki:become_angry": {
"add": { "component_groups": ["wiki:angry"] },
"set_property": { "wiki:mood": "angry" }
}
}事件必须由某个东西来触发。在上面的幼年组中,minecraft:ageable 会在时间到了时触发 wiki:grow_up。其他组件,比如 minecraft:damage_sensor、minecraft:timer 和 minecraft:environment_sensor,也能触发事件。命令同样可以:/event entity @e[type=wiki:ruby_golem] wiki:become_angry。
事件还能做更多事情:随机选择、按顺序执行步骤以及检查条件。这些都在下一页实体事件中讲解。
完整的红宝石傀儡
下面是把所有内容放在一起的样子。傀儡大多数时候以成年状态生成,有时是幼年。玩家打它时它会生气,20 秒后平静下来。
{
"format_version": "1.26.50",
"minecraft:entity": {
"description": {
"identifier": "wiki:ruby_golem",
"is_spawnable": true,
"is_summonable": true,
"properties": {
"wiki:mood": {
"type": "enum",
"values": ["calm", "angry"],
"default": "calm",
"client_sync": true
}
}
},
"components": {
"minecraft:type_family": { "family": ["ruby_golem", "golem", "mob"] },
"minecraft:health": { "value": 40, "max": 40 },
"minecraft:collision_box": { "width": 1.2, "height": 2.4 },
"minecraft:physics": {},
"minecraft:movement": { "value": 0.25 },
"minecraft:movement.basic": {},
"minecraft:navigation.walk": { "avoid_water": true },
"minecraft:jump.static": {},
"minecraft:behavior.hurt_by_target": { "priority": 2 },
"minecraft:behavior.random_stroll": { "priority": 6, "speed_multiplier": 0.8 },
"minecraft:behavior.look_at_player": { "priority": 7, "look_distance": 8 },
"minecraft:damage_sensor": {
"triggers": [
{
"on_damage": {
"filters": { "test": "is_family", "subject": "other", "value": "player" },
"event": "wiki:become_angry"
}
}
]
}
},
"component_groups": {
"wiki:baby": {
"minecraft:is_baby": {},
"minecraft:scale": { "value": 0.5 },
"minecraft:ageable": {
"duration": 1200,
"grow_up": { "event": "wiki:grow_up", "target": "self" }
}
},
"wiki:angry": {
"minecraft:attack": { "damage": 6 },
"minecraft:behavior.melee_attack": { "priority": 3 },
"minecraft:movement": { "value": 0.32 },
"minecraft:timer": {
"time": 20,
"looping": false,
"time_down_event": { "event": "wiki:calm_down" }
}
}
},
"events": {
"minecraft:entity_spawned": {
"randomize": [
{ "weight": 80 },
{ "weight": 20, "add": { "component_groups": ["wiki:baby"] } }
]
},
"wiki:grow_up": {
"remove": { "component_groups": ["wiki:baby"] }
},
"wiki:become_angry": {
"add": { "component_groups": ["wiki:angry"] },
"set_property": { "wiki:mood": "angry" }
},
"wiki:calm_down": {
"remove": { "component_groups": ["wiki:angry"] },
"set_property": { "wiki:mood": "calm" }
}
}
}
}运行流程:
- 傀儡出现。游戏自动触发
minecraft:entity_spawned,其中的randomize有五分之一的几率添加wiki:baby。 - 玩家打了它。伤害感应器检查过滤器(攻击者是玩家吗?),然后触发
wiki:become_angry。 - 这个事件添加了愤怒组:傀儡现在拥有了攻击、近战行为和更快的速度。
hurt_by_target已经把这名玩家设为了它的目标。 - 愤怒组中的计时器数满 20 秒后触发
wiki:calm_down,再把这个组移除。
小技巧
components只放永远不变的东西。 如果一个组件既在components里又在某个组里,就很难分清到底哪个在生效。会变化的东西只放在组里。- 一个组只做一件事。 像
wiki:angry和wiki:baby这样的小组,比每个状态一个大组更容易组合。 - 照着原版抄。 原版实体中的牛、狼和蜜蜂文件展示了很多实际用法。
出问题时
| 你看到的现象 | 最可能的原因 |
|---|---|
生物不存在(/summon 失败) | JSON 有错误,或者 identifier 有拼写错误。查看内容日志。 |
| 没有刷怪蛋 | is_spawnable 为 false,或者资源包中没有 spawn_egg |
| 事件没有任何效果 | add 中的组名与 component_groups 中的名称不匹配 |
| 日志中出现属性错误 | 属性没有在 description.properties 中声明,或者值超出了 range 或 values |
| 生物一直变不回来 | 没有任何东西触发移除该组的事件 |