# 实体基础
温馨提示:开始阅读这篇指南之前,我们希望你对《我的世界》基岩版附加包有一定了解,有能力撰写 JSON 数据格式,并能够独立阅读《我的世界》开发者官网-开发指南或其他技术引用文档。
本文将帮助你从零开始修改原版僵尸的行为,从而帮助你认识和了解生物行为的构成。
本系列不特意涉及实体资源的相关教程,如果对这一块不熟悉的同学,请自行前往前往官网查看相关教程。
在本教程中,您将学习以下内容。
- ✅如何查看原版行为文件;
- ✅认识和了解行为文件的基本构成;
- ✅尝试修改原版僵尸的行为并实现僵尸的基础行为:
- 手动还原最基础的僵尸行为;
- 出生随机大小的僵尸;
请点击这里 (opens new window)下载本章节课程的教学包
# 原版僵尸的行为
# 如何查看原版文件
在本地游戏测试客户端的目录中(MC Studio 安装目录下的 \game\MinecraftPE_Netease
可以找到),我们可以直接查看和学习生物的行为 JSON 是如何编写的:
使用打开目录之后跟我们正常编写的附加包并无差别,略微的区别就是像是 attachables
、biomes
、feature_rules
、features
这样的定义是保存在 definitions
目录下的(我们自己写是需要写在 behavior_packs
对应目录下):
如此,我们就可以在对应行为包下找到相关的原版行为 JSON 定义了。使用 vanilla
开头的包就是我们的原版资源了,后面跟随的是版本信息,通常来说,我们应该尽可能查看高版本的行为,因为更高的版本意味着一些改进和修复。
比如,我们查看 zombie
的最新 JSON 文件(在 vanilla_1.17.20\entities
目录)和第一版 JSON 文件(在 vanilla\entities
目录下)就可以发现,最新版本的 JSON 除了在行为文件使用的版本format_version
上有差异外,还多了一个 minecraft:shareables
组件 (opens new window),这个组件允许实体分享和拾取一些道具,这直接导致了僵尸能够拾取地上物品的行为 :
# 格式概述
实体行为都保存在行为包的 entities
文件夹中。行为文件扩展名都为 .json
,这跟游戏加载项中的许多文件都使用相同的扩展名,如果你想避免混淆,可以为行为文件使用再次扩展的扩展名 .behavior.json
。对于其他再次扩展的扩展名,请参阅此表 (opens new window)。
这些文件是用 JSON 编写的,基本结构如下所示:
{
"format_version": "1.17.20",
"minecraft:entity": {
"description": {
"identifier":"minecraft:zombie",
"is_spawnable":true,
"is_summonable":true,
"is_experimental": false
},
"component_groups": {},
"components": {},
"events": {}
}
}
在 description
标签中,一些基本属性定义了游戏如何注册实体:
参数名称 | 类型 | 描述 |
---|---|---|
identifier | 字符串 | 实体的标识符。 如果这是加载项中的自定义实体,则应使用示例中所示的自定义唯一命名空间。 |
runtime_identifier | 字符串 | 游戏内部使用的标识符。 这可用于从尚未作为组件提供的原版实体继承自定义机制。 每个实体只能指定一个运行时标识符。仅在确实需要时才使用。 如果一个原版实体的机制变成了组件,通过运行时标识符依赖这些机制可能会失去功能。 |
is_spawnable | 布尔值 | 如果为 true ,则该实体的刷怪蛋将添加到创意物品栏中。 |
is_summonable | 布尔值 | 如果为 true ,则可以使用 /summon 命令来召唤实体。 |
is_experimental | 布尔值 | 如果为 true ,则实体可以使用实验功能。 该实体只会在实验世界中工作。 |
animations | 对象 | 行为动画或动画控制器的列表。 这些可用于在实体上运行命令或事件。 |
scripts | 对象 | 脚本的工作方式类似于它们在客户端实体文件中的工作方式,并且可用于播放行为动画。 |
❗️注意:
行为目录下也是可以使用动画控制器的,其结构跟资源文件下的动画控制器具有相同的通用格式,不同的是,行为包属于服务端的文件,它允许您触发命令,而不是动画。我们会在后续的章节中介绍到这一部分,这有助于实现一些复杂的生物行为。
# 组件和组件组
组件是可以添加到实体的属性或机制。 添加组件有两种方式:直接添加到 component 标签或使用组件组。
- 添加到基本 component 标签的组件始终处于活动状态,除非通过事件中的组件组移除。
- 组件组包含一个或多个组件,每个组件默认情况下处于非活动状态,但可以通过事件启用或禁用。 例如,这可用于创建实体的变体,例如 baby(婴儿)。
比如我们以原版僵尸的行为 JSON 为例(精简之后):
{
"format_version": "1.17.20",
"minecraft:entity": {
"description": {
"identifier": "minecraft:zombie",
"is_spawnable": true,
"is_summonable": true,
"is_experimental": false
},
"component_groups": {
"minecraft:zombie_baby": {
"minecraft:is_baby": {},
"minecraft:scale": {
"value": 0.5
},
"minecraft:movement": {
"value": 0.35
}
},
"minecraft:zombie_adult": {
"minecraft:movement": {
"value": 0.23
}
}
},
"components": {
"minecraft:physics": {}
// Zombie Components
// Zombie Behaviors
}
}
}
在 compoents
下的组件始终处于活动状态,而 minecraft:zombie_baby
组件组中的组件只有在添加该组之后才会处于活动状态,这需要 events
来配合使用。
# 如何学习组件
完整的可用组件列表可以再此处 (opens new window)找到。官方文档不仅有详细的参数解释,还基本都配套有一些例子和原版的应用:
另一个常用的基岩版文档网站 (opens new window)也建议存储起来。这两个网站通常需要配合起来查阅。
我们也可以通过查看《我的世界》默认实体的行为文件,来了解组件以及应该在实践中如何使用(参考上方的 #如何查看原版文件)。
# 核心组件
组件名称 | 选项 | 描述 |
---|---|---|
minecraft:physics | has_collision has_gravity | 99% 的自定义实体都需要此组件。 它允许实体留在地面上并以您期望的方式对交互和冲击做出反应。 |
minecraft:scale | value | 设置实体的比例。 |
minecraft:collision_box | width height | 设置实体的碰撞盒。 只能更改 width 和 height 。 碰撞盒始终具有一个与世界轴对齐的方形基础。 |
minecraft:type_family | family | 设置实体所在的类型系列的列表。 类型系列可以由其他实体进行测试。 例如,测试他们对哪些生物怀有敌意。 |
minecraft:movement | value | 设置实体的移动速度。 《我的世界》中大多数动物的常规速度为 0.25。 |
minecraft:movement.basic | 查看文档 (opens new window) | 允许实体在地面上移动。 |
minecraft:navigation.walk | 查看文档 (opens new window) | 允许实体在世界中游走。 还有其他类型的导航,比如悬停。 |
minecraft:is_baby minecraft:is_ignited minecraft:is_saddled minecraft:is_sheared minecraft:is_tamed minecraft:is_illager_captain | :--- | 这些组件本身不做任何事情,但可以在动画、动画控制器或渲染控制器中查询它们,允许您通过实体行为控制动画和其他视觉效果。 |
minecraft:variant minecraft:mark_variant minecraft:skin_id | value | 这些组件的工作方式与上面的类似,但它们不仅可以存储开/关状态,还可以存储整数值。 |
# 优先级 - priority
选项 priority
可用于所有行为组件(AI 目标)。 0
所有行为组件的最高优先级和默认优先级为 0。 数字越大,优先级越低。 如果实体正忙于进行一个低优先级的行为,当出现了一个高优先级的行为时,该实体将立即切换到更高优先级的行为。
在以下示例中,hurt_by_target
组件具有更高的优先级。 如果实体在漫步时受到攻击,它会立即瞄准攻击者。
"minecraft:behavior.hurt_by_target": {
"priority": 1
},
"minecraft:behavior.random_stroll": {
"priority": 4
}
一种比较推荐的书写方式就是参考原版的僵尸,把组件和行为进行区分(并不特别需要 //
注释),这样可以让我们更加容易找到 AI 组件并控制他们的优先级,避免发生冲突:
"components": {
"minecraft:is_hidden_when_invisible": {},
"minecraft:nameable": {},
"minecraft:physics": {}
// Zombie Components
// Zombie Behaviors
}
# 专属组件-组件的隐性规则
有时候我们的组件无法使用,除了排查生物使用的版本信息(format_version
)、是否存在优先级冲突、是否没有添加依赖的基础组件(请参考 #如何调试生物行为 查看)之外,还应该考虑这个组件是否是为某个生物准备的专属组件。
比如原版的末影龙就会有许多硬编码的组件供他专用:
我们查看史莱姆的相关组件也可以看到类似的说明:
如果我们仍然想要使用相关组件的话,那么就需要把 runtime_identifier
改成支持对应组件的实体才可以了。
# 事件
事件用于在实体中添加和移除组件组。 在此示例中,移除了一个旧的组件组,添加了两个新的组件组:
"events": {
"compass:example_event": {
"remove": {
"component_groups": ["compass:group_a"]
},
"add": {
"component_groups": ["compass:group_b","compass:group_c"]
}
}
}
事件可以由许多组件触发,例如 minecraft:interact
或 minecraft:environment_sensor
、通过行为动画或 summon 命令。 以下命令将在运行上述事件时生成实体。
/summon compass:example_entity ~ ~ ~ compass:example_event
# 内置事件
《我的世界》中内置了一些事件,当实体在特定条件下生成时运行。
事件名称 | 描述 |
---|---|
minecraft:entity_born | 该事件在实体通过繁殖产生时运行。 |
minecraft:entity_spawned | 该事件在实体生成时运行。 请注意,它在手动执行 /summon 时不会运行。 |
minecraft:entity_transformed | 当另一个实体转换为该实体时,该事件将运行。 |
minecraft:on_prime | 该事件在实体被激活并即将爆炸时运行。 |
# 随机化器
如果要随机指定将哪个组件组添加到实体,可以使用 randomize 函数。 您指定一个对象数组,每个对象都可以添加和移除组件组。 游戏将随机选择并运行这些对象之一。
或者,您可以向选项添加权重选项以更改每个选项的概率。 所有权重加起来为 100%。 在以下示例中,实体将以 20% (1:4) 的概率生成为 baby,而在其他情况下,不会添加任何组件组:
"events": {
"minecraft:entity_spawned": {
"randomize": [
{
"weight": 40
},
{
"weight": 10,
"add": {
"component_groups": ["baby"]
}
}
]
}
}
# 序列
有时,您需要在同一事件中接连运行多个事件实例。 例如,您可能希望随机化实体的两个方面,如颜色和标记图案。 在这种情况下,您可以使用序列。 序列的结构类似于随机化器,但列表中的每个项都是按顺序执行的。 序列与过滤器结合使用也非常有用,将在下一节中解释。
序列和随机化器可以无限嵌套。
在此示例中,将在生成实体时添加组 initial
。 之后,baby 组件将像上一节一样随机化。
"events": {
"minecraft:entity_spawned":{
"sequence": [
{
"add": {
"component_groups": ["initial"]
}
},
{
"randomize": [
{
"weight": 40
},
{
"weight": 10,
"add": {
"component_groups": ["baby"]
}
}
]
}
]
}
}
# 过滤器
过滤器通过测试当前实体(交互实体或世界)的特定属性来调节事件或事件的一部分。 过滤器可以在任何事件中使用,但也可以直接在某些组件中使用。
一个事件最多包含五个参数。 参数 test
和 value
是必需的,其他是可选的:
测试类型 | 要测试的属性 |
---|---|
value | 要测试的值。 测试字符串时可以是字符串,测试数值时可以是数值,也可以是布尔值。 |
subject | 运行测试的实体。 默认情况下为 self ,但它也可以针对交互中涉及的其他实体。 |
operator | 比较值的方式。 默认为 equals ,但也可以比较大小(数值)或是否不相等。 |
domain | 仅由少数测试使用,提供额外的上下文,例如,has_equipment 测试可测试物品栏的栏位。 |
事件中过滤器的最简示例可能如下所示:只有当实体具有 event_allowed
标签时才能添加组件组。
"events": {
"compass:example_event": {
"filters": {
"test": "has_tag",
"value":"event_allowed"
},
"add": {
"component_groups": ["baby"]
}
}
}
如果您想使用多个过滤器,您可以使用列表 all_of
、any_of
或 none_of
对它们进行分组,分别对应所有过滤器、一个过滤器或无过滤器,仅在满足相应条件时成功。 这些列表可以无限嵌套。
在以下示例中,我们将向过滤器添加第二个条件。 仅当实体具有上一个示例中的标签并且距离最近的玩家少于 10 个方块时,该事件才会运行。
"events": {
"compass:example_event": {
"filters": {
"all_of":[
{"test": "has_tag", "value": "event_allowed"},
{"test": "distance_to_nearest_player", "operator": "<", "value": 10}
]
},
"add": {
"component_groups": ["baby"]
}
}
}
# 原版僵尸行为组件分析
有了以上的基本了解之后,我们阅读原版僵尸的行为就很容易一些了,大家可以自行阅读一下,会发现就只是简单的组件堆叠。
这里只提一个比较特殊一些的地方,那就是僵尸变成溺尸的组件 minecraft:transformation
使用的特殊用法:
"minecraft:transformation": {
"into": "minecraft:drowned<minecraft:as_adult>",
"transformation_sound": "convert_to_drowned",
"drop_equipment": true,
"delay": {
"value": 15
}
}
这里的 into
的参数除了带有溺尸的标识符外,还用 <>
标识了转换之后所要触发的事件。
另一个特殊的地方是僵尸转换的时候会判断自己是否是 baby
,会转换成对应的溺尸,这是通过事件的序列和过滤器实现的:
"minecraft:convert_to_drowned": {
"sequence": [
{
"filters": {
"test": "has_component",
"operator": "!=",
"value": "minecraft:is_baby"
},
"add": {"component_groups": ["minecraft:convert_to_drowned"]},
"remove": {"component_groups": ["minecraft:start_drowned_transformation"]}
},
{
"filters": {
"test": "has_component",
"value": "minecraft:is_baby"
},
"add": {"component_groups": ["minecraft:convert_to_baby_drowned"]},
"remove": {"component_groups": ["minecraft:start_drowned_transformation"]}
}
]
}
# 基础僵尸行为还原
# 僵尸行为分析
原版的僵尸有非常多的特性,行为 JSON 有多达 590 多行,我们现在来尝试,自己一步一步还原出僵尸的基础行为。
我们来分析一下僵尸有哪些状态,分别有什么样的行为:
- 小僵尸:体型小,跑得快。
- 成年僵尸:正常体型,跑得不快。
- 通用行为:移动、攻击玩家、在白天燃烧。
在不考虑转换成溺尸的情况下,这就是僵尸的基础行为了。根据我们的分析,就可以搭建出基础的行为 JSON 框架:
{
"format_version": "1.17.20",
"minecraft:entity": {
"description": {
"identifier": "minecraft:zombie",
"is_spawnable": true,
"is_summonable": true,
"is_experimental": false
},
"component_groups": {
"minecraft:zombie_baby": {
// baby 僵尸的组件
},
"minecraft:zombie_adult": {
// 成年僵尸的组件
}
},
"components": {
// 僵尸的通用组件:行为、在白天燃烧
// 僵尸的通用行为:攻击玩家
},
"events": {
}
}
}
首先,根据上面所学的知识,我们让我们修改过的僵尸,能够按相同的概率来加载 minecraft:zombie_baby
组和 minecraft:zombie_adult
组,这有助于之后的开发和测试:
{
"format_version": "1.17.20",
"minecraft:entity": {
"description": {
"identifier": "minecraft:zombie",
"is_spawnable": true,
"is_summonable": true,
"is_experimental": false
},
"component_groups": {
"minecraft:zombie_baby": {
"minecraft:scale": {
"value": 0.5
}
},
"minecraft:zombie_adult": {
}
},
"components": {
// 僵尸的通用组件:行为、在白天燃烧
// 僵尸的通用行为:攻击玩家
},
"events": {
"minecraft:entity_spawned": {
"randomize": [
{
"weight": 1,
"add": {
"component_groups": [
"minecraft:zombie_adult"
]
}
},
{
"weight": 1,
"add": {
"component_groups": [
"minecraft:zombie_baby"
]
}
}
]
}
}
}
}
minecrat:scale
组件是用来控制实体模型大小的组件,处于 baby
组的僵尸只有成年僵尸一半的体型。
这样,我们就修改了原版的僵尸行为,实现了按 1:1 比例生成成年僵尸和幼年僵尸的行为:
有了这个基础,我们再来一步一步还原僵尸的基础行为。
# 实体移动
在我的世界中,实体有能力通过行走、游泳或者飞行在世界中移动。想要自定义的实体获得这些能力,请记住按照以下步骤添加相关的组件:
- 设置实体移动速度的组件;
- 用于设置实体移动方式(行走、飞行等)的组件;
- 用于设置实体导航功能的组件, 以便让他们可以生成路径;
- 设置实体移动的位置/时间(AI 目标)的组件;
# 移动速度
实体首先需要的是速度组件,这设置了实体在世界中的移动速度。
组件 | 说明 |
---|---|
minecraft:movement (opens new window) | 设置移动速度(必填) |
minecraft:underwater_movement (opens new window) | 设置水中的移动速度。 |
minecraft:flying_speed (opens new window) | 设置空中的飞行速度。 |
我们需要始终添加上 minecraft:movement
组件,其他两个按需加入。
所有像是海豚一类的能够游泳的实体,都包括了 minecraft:underwater_movement
,而只有少部分飞行实体(蜜蜂、末影龙)包括了 minecraft:flying_speed
,不清楚原因。
# 移动类型
移动类型是实体在世界中移动方式的硬编码行为。
您的实体只能包含一种移动类型。根据您的实体选择一种最符合要求的组件就可以。一般来说,basic
、amphibious
、fly
都是非常好用且常用的组件。
组件 | 说明 |
---|---|
minecraft:movement.amphibious (opens new window) | 这种移动控制允许生物在水中游泳并在陆地上行走。 |
minecraft:movement.basic (opens new window) | 此组件是实体的移动基础组件。 |
minecraft:movement.fly (opens new window) | 这种移动控制会导致生物飞行。 |
minecraft:movement.generic (opens new window) | 这种移动控制允许生物飞行、游泳、攀爬等。 |
minecraft:movement.hover (opens new window) | 此移动控制会导致生物悬停。 |
minecraft:movement.jump (opens new window) | 移动控制使生物在移动时跳跃,跳跃之间有指定的延迟。 |
minecraft:movement.skip (opens new window) | 此移动控制会导致生物在移动时跳跃。 |
minecraft:movement.sway (opens new window) | 这种移动控制使生物左右摇摆,给人的感觉就是它在游泳。 |
# 运动修改器
这是有关实体如何在世界中移动的附加信息。这些组件对于普通实体来说基本是不需要的,但您应该了解它们。
组件 | 说明 |
---|---|
minecraft:water_movement (opens new window) | 设置实体在水中所经历的摩擦 |
minecraft:rail_movement (opens new window) | 设置实体(仅)可以在轨道上移动 |
minecraft:friction_modifier (opens new window) | 设置实体在陆地上所经历的摩擦 |
# 导航
导航组件有非常多的参数,比如可以设置实体是否可以打开门或避免阳光照射。如何设置这些字段通常比您选择的导航组件更重要!
之所以有这么多导航组件,是因为每个组件都给出了略有不同的硬编码行为。选择其名称/描述与实体将要执行的导航类型最匹配的导航组件。
在任何情况下,您只能有一个导航组件。
组件 | 说明 |
---|---|
minecraft:navigation.climb (opens new window) | 允许此实体生成包含垂直墙的路径,就像原版蜘蛛一样。 |
minecraft:navigation.float (opens new window) | 允许该实体像普通的 Ghast 一样通过在空中飞行来生成路径。 |
minecraft:navigation.generic (opens new window) | 允许此实体通过行走、游泳、飞行和攀爬以及上下跳跃来生成路径。 |
minecraft:navigation.fly (opens new window) | 允许该实体像鹦鹉一样在空中生成路径。 |
minecraft:navigation.swim (opens new window) | 允许此实体生成包含水的路径。 |
minecraft:navigation.walk (opens new window) | 允许该实体像普通生物一样通过四处走动和上下跳跃来生成路径。 |
# 导航能力
导航组件只能告诉实体如何生成路径,但不会说明在何时何地生成路径。这就是 AI 组件的用途。
AI 目标以优先级为前缀,并遵循优先级来选择要运行的行为。将首先选择优先级较低的行为来执行。
生成路径的 AI 组件太多,无法在本文档中列出。我们将提供一些示例:
组件 | 说明 |
---|---|
minecraft:behavior.random_stroll (opens new window) | 随机漫步,需要同时拥有 movement 和 look_at 相关的组件。 |
minecraft:behavior.follow_owner (opens new window) | 允许该实体跟随主人。 |
minecraft:behavior.move_to_water (opens new window) | 允许实体在陆地的情况下返回水体中。 |
minecraft:behavior.stroll_towards_village (opens new window) | 允许该实体在搜索范围内移动到村庄的随机位置。 |
完整的 AI 组件可以参考这个列表 (opens new window)。
# 为僵尸添加基础的行走能力
按照我们上述提过的步骤,首先在 baby
和 adult
组件组中添加上移动速度的定义,因为僵尸始终会处于这两个组件组中的其中一个:
"component_groups": {
"minecraft:zombie_baby": {
"minecraft:scale": {
"value": 0.5
},
"minecraft:movement": {
"value": 0.35
}
},
"minecraft:zombie_adult": {
"minecraft:movement": {
"value": 0.23
}
}
}
然后移动方式我们选择最基础的 basic
,导航我们选择最基础的 navigation.walk
,我们都添加进公用的组件中去。当然别忘了最基础的 physics
组件以及设置血量的 health
组件:
"minecraft:physics": {},
"minecraft:health": {
"value": 20,
"max": 20
}, // 设置血量
"minecraft:jump.static":{}, // 让僵尸拥有跳跃的能力,也就是能够上高一格方块的能力
"minecraft:movement.basic": {},
"minecraft:navigation.walk": {
"is_amphibious": true,
"can_pass_doors": true,
"can_walk": true,
"can_break_doors": true
}
然后再加入一个随机漫步的 AI 组件:
"minecraft:behavior.random_stroll": {
"priority": 7,
"interval": 20,
"speed_multiplier": 1
}
进入游戏测试,就可以看见我们的僵尸行走了起来:
# 实体攻击
要让实体具备攻击能力,需要许多不同的组件才能正常工作:
- 向目标移动的移动和导航能力;
- 自主选择攻击哪个实体的目标选择能力;
- 攻击能力,如近战或远程;
- 攻击伤害和效果的设置;
# 选择目标
❗️注意
即时你正在制作一个不具备移动能力的实体(如炮塔),仍然需要添加导航组件,以便让你的实体能够找到要射击的实体。
有许多方法能够让实体产生敌意。最常见的类型,就是如下所示的 nearest_attackable_target
组件,它通常允许您定义的实体有兴趣攻击哪些实体:
"minecraft:behavior.nearest_attackable_target": {
"must_see": true, // 如果 Ture,那么目标实体必须在视线范围内
"reselect_targets": true, // 如果一个目标比当前的目标更近,那么允许实体选择更近的这一个目标
"within_radius": 25.0, // 检测范围
"must_see_forget_duration": 17.0, // 如果 "must_see" = true, 这个时间就定义了忘记目标前的时间
"entity_types": [
{
"filters": {
// 要攻击的实体类型,这里是选择的玩家
"test": "is_family",
"subject": "other",
"value": "player"
},
"max_dist": 48.0
}
]
}
为了实现更精细的控制,您还可以考虑下列组件:
组件 | 说明 |
---|---|
minecraft:behavior.nearest_attackable_target | 目标实体满足给定要求 |
minecraft:behavior.nearest_prioritized_attackable_target | 允许在每个过滤器后设置优先级 “priority”: [integer] |
minecraft:behavior.defend_trusted_target | 目标实体会损害筛选器中指定的任何实体 |
但其实还有一个——minecraft:lookat
。这个组件跟上面三个略微不同,因为它是用于检测和瞄准尝试眼神接触的实体。这个有所了解就好,用得不多。它的结构是这样的:
"minecraft:lookat": {
"search_radius": 64.0,
"set_target": true, // 如果为真,则成为有效目标
"look_cooldown": 5.0,
"filters": {
"all_of": [
{
"subject": "other",
"test": "is_family",
"value": "player"
},
{
"test": "has_equipment",
"domain": "head",
"subject": "other",
"operator": "not",
"value": "carved_pumpkin" // 所有没有带雕刻南瓜头的玩家都会成为有效目标
}
]
}
}
# 攻击能力类型
以下是能够使用的攻击类型,我们只介绍其中最常用的两种:
组件 | 说明 |
---|---|
minecraft:behavior.melee_attack (opens new window) | 对单个目标造成伤害 |
minecraft:behavior.ranged_attack (opens new window) | 向目标发射弹射物 |
minecraft:area_attack (opens new window) | 对射程内的任何物体进行有效的近战攻击 |
minecraft:behavior.knockback_roar (opens new window) | 与 minecraftarea_attack 类似,但更灵活 |
# 近战攻击
近战攻击是最常见的类型,它们会造成击退:
"minecraft:attack": {
"damage": 3, // 伤害值,可以设置为负数(此时为治疗效果)
"effect_name": "slowness", // 非必须参数,原版的效果都可以
"effect_duration": 20 // 非必须参数,攻击效果持续的时间
},
"minecraft:behavior.melee_attack": {
"priority": 3,
"melee_fov": 90.0, // 可以理解为攻击角度
"speed_multiplier": 1, // 有目标时移动速度的乘积
"track_target": false,
"require_complete_path": true
}
# 远程攻击
以指定的时间间隔向目标发射指定的抛射物,这里造成的伤害就取决于抛射物:
"minecraft:behavior.ranged_attack": {
"priority": 2,
"ranged_fov": 90.0, // 能够进行有效攻击的角度
"attack_interval_min": 1.0,
"attack_interval_max": 3.0,
"attack_radius": 15.0
},
"minecraft:shooter": {
"def": "minecraft:arrow"
}
# 为僵尸添加添加基础的攻击能力
我们让成年僵尸拥有更高的攻击力(2点),然后省略掉其余的部分,精简之后的 JSON 如下:
{
"format_version": "1.17.20",
"minecraft:entity": {
"description": {
// ...省略...
},
"component_groups": {
"minecraft:zombie_baby": {
// ...省略...
"minecraft:attack": {
"damage": 1
}
},
"minecraft:zombie_adult": {
// ...省略...
"minecraft:attack": {
"damage": 2
}
}
},
"components": {
// ...省略...
"minecraft:behavior.nearest_attackable_target": {
"priority": 2,
"must_see": true, // 如果 Ture,那么目标实体必须在视线范围内
"reselect_targets": true, // 如果一个目标比当前的目标更近,那么允许实体选择更近的这一个目标
"within_radius": 25.0, // 检测范围
"must_see_forget_duration": 17.0, // 如果 "must_see" = true, 这个时间就定义了忘记目标前的时间
"entity_types": [
{
"filters": {
// 要攻击的实体类型,这里是选择的玩家
"test": "is_family",
"subject": "other",
"value": "player"
},
"max_dist": 48.0
}
]
},
"minecraft:behavior.melee_attack": {
"priority": 3,
"melee_fov": 90.0,
"speed_multiplier": 1,
"track_target": false,
"require_complete_path": true
}
// ...省略...
},
"events": {
// ...省略...
}
}
}
至此,我们就可以开始享受“跑路”了:
# 如何调试生物行为
在我们的测试客户端中,可以点击「设置」找到「调试」选项卡,下图中圈起来的就是跟生物行为相关的一些选项的(默认都是关闭的):
能见度边框:是否显示实体的碰撞箱;
能见度路径:查看实体生成的路径,如果玩家有导航的能力,那么就会按照路径进行移动;
能见度目标状态:能够查看实体的 AI 组件列表,包含优先级、正在执行的、以及 AI 组件依赖的基础组件(括号里面就是依赖的组件);
渲染生物信息状态:能够查看实体的属性列表、当前处于的组件组和正在执行的 AI 组件信息;
# 课后作业
本次课后作业,内容如下:
- 尝试在
_b/entities
新增一个zombie.json
文件,修改原版僵尸的行为,使其具有基础的攻击和移动能力; - 打开游戏客户端的调试功能,观察实体的行为;