Files
netease-bedrock-wiki/mconline/60-我的世界创造营教程/SDK大师教程/0-怪物AI制作/0-实体基础.md
2025-08-25 18:36:29 +08:00

822 lines
39 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 实体基础
> 温馨提示:开始阅读这篇指南之前,我们希望你对《我的世界》基岩版附加包有一定了解,有能力撰写 JSON 数据格式,并能够独立阅读《我的世界》开发者官网-开发指南或其他技术引用文档。
本文将帮助你从零开始修改原版僵尸的行为,从而帮助你认识和了解生物行为的构成。
本系列不特意涉及实体资源的相关教程,如果对这一块不熟悉的同学,请自行前往前往官网查看相关教程。
在本教程中,您将学习以下内容。
- ✅如何查看原版行为文件;
- ✅认识和了解行为文件的基本构成;
- ✅尝试修改原版僵尸的行为并实现僵尸的基础行为:
- 手动还原最基础的僵尸行为;
- 出生随机大小的僵尸;
请点击[这里](https://g79.gdl.netease.com/Entity.zip)下载本章节课程的教学包
## 原版僵尸的行为
### 如何查看原版文件
在本地游戏测试客户端的目录中MC Studio 安装目录下的 `\game\MinecraftPE_Netease` 可以找到),我们可以直接查看和学习生物的行为 JSON 是如何编写的:
![](./assets/image-20231031095005439.png)
使用打开目录之后跟我们正常编写的附加包并无差别,略微的区别就是像是 `attachables``biomes``feature_rules``features` 这样的定义是保存在 `definitions` 目录下的(我们自己写是需要写在 `behavior_packs` 对应目录下):
![](./assets/image-20231031095254881.png)
如此,我们就可以在对应行为包下找到相关的原版行为 JSON 定义了。使用 `vanilla` 开头的包就是我们的原版资源了,后面跟随的是版本信息,通常来说,我们应该**尽可能查看高版本的行为**,因为更高的版本意味着一些改进和修复。
比如,我们查看 `zombie` 的最新 JSON 文件(在 `vanilla_1.17.20\entities` 目录)和第一版 JSON 文件(在 `vanilla\entities` 目录下)就可以发现,最新版本的 JSON 除了在行为文件使用的版本`format_version` 上有差异外,还多了一个 `minecraft:shareables` [组件](https://learn.microsoft.com/zh-cn/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_shareables),这个组件允许实体分享和拾取一些道具,这直接导致了僵尸能够拾取地上物品的行为
![僵尸拾取物品行为演示](./assets/0_1.gif)
### 格式概述
实体行为都保存在行为包的 `entities` 文件夹中。行为文件扩展名都为 `.json`,这跟游戏加载项中的许多文件都使用相同的扩展名,如果你想避免混淆,可以为行为文件使用再次扩展的扩展名 `.behavior.json`。对于其他再次扩展的扩展名,请参阅[此表](https://learn.microsoft.com/zh-cn/minecraft/creator/documents/introductiontoaddentity)。
这些文件是用 JSON 编写的,基本结构如下所示:
```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 为例(精简之后):
```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` 来配合使用。
#### 如何学习组件
完整的可用组件列表可以再[此处](https://learn.microsoft.com/zh-cn/minecraft/creator/reference/content/entityreference/examples/componentlist)找到。官方文档不仅有详细的参数解释,还基本都配套有一些例子和原版的应用:
![官方文档示例](./assets/image-20231031151519365.png)
另一个常用的[基岩版文档网站](https://bedrock.dev/zh)也建议存储起来。这两个网站通常需要配合起来查阅。
![基岩版文档](./assets/image-20231031151749226.png)
我们也可以通过查看《我的世界》默认实体的行为文件,来了解组件以及应该在实践中如何使用(参考上方的 #如何查看原版文件)。
#### 核心组件
| 组件名称 | 选项 | 描述 |
| :----------------------------------------------------------- | :----------------------------------------------------------- | :----------------------------------------------------------- |
| `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` | [查看文档](https://learn.microsoft.com/zh-cn/creator/Reference/Content/EntityReference/Examples/EntityComponents/minecraftComponent_movement.basic.md) | 允许实体在地面上移动。 |
| `minecraft:navigation.walk` | [查看文档](https://learn.microsoft.com/zh-cn/creator/Reference/Content/EntityReference/Examples/EntityComponents/minecraftComponent_navigation.walk.md) | 允许实体在世界中游走。 还有其他类型的导航,比如悬停。 |
| `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` 组件具有更高的优先级。 如果实体在漫步时受到攻击,它会立即瞄准攻击者。
```json
"minecraft:behavior.hurt_by_target": {
"priority": 1
},
"minecraft:behavior.random_stroll": {
"priority": 4
}
```
一种比较推荐的书写方式就是参考原版的僵尸,把**组件和行为进行区分**(并不特别需要 `//` 注释),这样可以让我们更加容易找到 AI 组件并控制他们的优先级,避免发生冲突:
```json
"components": {
"minecraft:is_hidden_when_invisible": {},
"minecraft:nameable": {},
"minecraft:physics": {}
// Zombie Components
// Zombie Behaviors
}
```
#### 专属组件-组件的隐性规则
有时候我们的组件无法使用,除了排查生物使用的版本信息(`format_version`)、是否存在优先级冲突、是否没有添加依赖的基础组件(请参考 #如何调试生物行为 查看)之外,还应该考虑这个组件是否是为某个生物准备的专属组件。
比如原版的末影龙就会有许多硬编码的组件供他专用:
![末影龙的专属组件](./assets/image-20231103120559952.png)
我们查看史莱姆的相关组件也可以看到类似的说明:
![史莱姆组件说明](./assets/image-20231103121138327.png)
如果我们仍然想要使用相关组件的话,那么就需要把 `runtime_identifier` 改成支持对应组件的实体才可以了。
### 事件
事件用于在实体中添加和移除组件组。 在此示例中,移除了一个旧的组件组,添加了两个新的组件组:
```json
"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 命令。 以下命令将在运行上述事件时生成实体。
```txt
/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而在其他情况下不会添加任何组件组
```json
"events": {
"minecraft:entity_spawned": {
"randomize": [
{
"weight": 40
},
{
"weight": 10,
"add": {
"component_groups": ["baby"]
}
}
]
}
}
```
#### 序列
有时,您需要在同一事件中接连运行多个事件实例。 例如,您可能希望随机化实体的两个方面,如颜色和标记图案。 在这种情况下,您可以使用序列。 序列的结构类似于随机化器,但列表中的每个项都是按顺序执行的。 序列与过滤器结合使用也非常有用,将在下一节中解释。
序列和随机化器可以无限嵌套。
在此示例中,将在生成实体时添加组 `initial`。 之后baby 组件将像上一节一样随机化。
```json
"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` 标签时才能添加组件组。
```json
"events": {
"compass:example_event": {
"filters": {
"test": "has_tag",
"value":"event_allowed"
},
"add": {
"component_groups": ["baby"]
}
}
}
```
如果您想使用多个过滤器,您可以使用列表 `all_of``any_of``none_of` 对它们进行分组,分别对应所有过滤器、一个过滤器或无过滤器,仅在满足相应条件时成功。 这些列表可以无限嵌套。
在以下示例中,我们将向过滤器添加第二个条件。 仅当实体具有上一个示例中的标签**并且**距离最近的玩家少于 10 个方块时,该事件才会运行。
```json
"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` 使用的特殊用法:
```json
"minecraft:transformation": {
"into": "minecraft:drowned<minecraft:as_adult>",
"transformation_sound": "convert_to_drowned",
"drop_equipment": true,
"delay": {
"value": 15
}
}
```
这里的 `into` 的参数除了带有溺尸的标识符外,还用 `<>` 标识了转换之后所要触发的事件。
另一个特殊的地方是僵尸转换的时候会判断自己是否是 `baby`,会转换成对应的溺尸,这是通过事件的序列和过滤器实现的:
```json
"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 框架:
```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` 组,这有助于之后的开发和测试:
```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: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 比例生成成年僵尸和幼年僵尸的行为:
![随机大小演示](./assets/0_2.gif)
有了这个基础,我们再来一步一步还原僵尸的基础行为。
### 实体移动
在我的世界中,实体有能力通过行走、游泳或者飞行在世界中移动。想要自定义的实体获得这些能力,请记住按照以下步骤添加相关的组件:
- **设置实体移动速度**的组件;
- 用于**设置实体移动方式**(行走、飞行等)的组件;
- 用于**设置实体导航功能**的组件, 以便让他们可以生成路径;
- 设置**实体移动的位置/时间**AI 目标)的组件;
#### 移动速度
实体首先需要的是速度组件,这设置了实体在世界中的移动速度。
| 组件 | 说明 |
| ------------------------------------------------------------ | -------------------- |
| [minecraft:movement](https://wiki.bedrock.dev/entities/vanilla-usage-components.html#movement) | 设置移动速度(必填) |
| [minecraft:underwater_movement](https://wiki.bedrock.dev/entities/vanilla-usage-components.html#underwater-movement) | 设置水中的移动速度。 |
| [minecraft:flying_speed](https://wiki.bedrock.dev/entities/vanilla-usage-components.html#flying-speed) | 设置空中的飞行速度。 |
我们需要**始终添加**上 `minecraft:movement` 组件,其他两个按需加入。
所有像是海豚一类的能够游泳的实体,都包括了 `minecraft:underwater_movement`,而只有少部分飞行实体(蜜蜂、末影龙)包括了 `minecraft:flying_speed`,不清楚原因。
#### 移动类型
移动类型是实体在世界中移动方式的硬编码行为。
您的实体**只能包含一种移动类型**。根据您的实体选择一种最符合要求的组件就可以。一般来说,`basic``amphibious``fly` 都是非常好用且常用的组件。
| 组件 | 说明 |
| ------------------------------------------------------------ | ---------------------------------------------------- |
| [minecraft:movement.amphibious](https://bedrock.dev/docs/stable/Entities#minecraft%3Amovement.amphibious) | 这种移动控制允许生物在水中游泳并在陆地上行走。 |
| [minecraft:movement.basic](https://bedrock.dev/docs/stable/Entities#minecraft%3Amovement.basic) | 此组件是实体的移动基础组件。 |
| [minecraft:movement.fly](https://bedrock.dev/docs/stable/Entities#minecraft%3Amovement.fly) | 这种移动控制会导致生物飞行。 |
| [minecraft:movement.generic](https://bedrock.dev/docs/stable/Entities#minecraft%3Amovement.generic) | 这种移动控制允许生物飞行、游泳、攀爬等。 |
| [minecraft:movement.hover](https://bedrock.dev/docs/stable/Entities#minecraft%3Amovement.hover) | 此移动控制会导致生物悬停。 |
| [minecraft:movement.jump](https://bedrock.dev/docs/stable/Entities#minecraft%3Amovement.jump) | 移动控制使生物在移动时跳跃,跳跃之间有指定的延迟。 |
| [minecraft:movement.skip](https://bedrock.dev/docs/stable/Entities#minecraft%3Amovement.skip) | 此移动控制会导致生物在移动时跳跃。 |
| [minecraft:movement.sway](https://bedrock.dev/docs/stable/Entities#minecraft%3Amovement.sway) | 这种移动控制使生物左右摇摆,给人的感觉就是它在游泳。 |
#### 运动修改器
这是有关实体如何在世界中移动的附加信息。这些组件对于普通实体来说基本是不需要的,但您应该了解它们。
| 组件 | 说明 |
| ------------------------------------------------------------ | ------------------------------ |
| [minecraft:water_movement](https://bedrock.dev/docs/stable/Entities#minecraft%3Awater_movement) | 设置实体在水中所经历的摩擦 |
| [minecraft:rail_movement](https://bedrock.dev/docs/stable/Entities#minecraft%3Arail_movement) | 设置实体(仅)可以在轨道上移动 |
| [minecraft:friction_modifier](https://bedrock.dev/docs/stable/Entities#minecraft%3Afriction_modifier) | 设置实体在陆地上所经历的摩擦 |
#### 导航
导航组件有非常多的参数,比如可以设置实体是否可以打开门或避免阳光照射。如何设置这些字段通常比您选择的导航组件更重要!
之所以有这么多导航组件,是因为每个组件都给出了略有不同的硬编码行为。选择其名称/描述与实体将要执行的导航类型最匹配的导航组件。
在任何情况下,您**只能有一个**导航组件。
| 组件 | 说明 |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| [minecraft:navigation.climb](https://bedrock.dev/docs/stable/Entities#minecraft%3Anavigation.climb) | 允许此实体生成包含垂直墙的路径,就像原版蜘蛛一样。 |
| [minecraft:navigation.float](https://bedrock.dev/docs/stable/Entities#minecraft%3Anavigation.float) | 允许该实体像普通的 Ghast 一样通过在空中飞行来生成路径。 |
| [minecraft:navigation.generic](https://bedrock.dev/docs/stable/Entities#minecraft%3Anavigation.generic) | 允许此实体通过行走、游泳、飞行和攀爬以及上下跳跃来生成路径。 |
| [minecraft:navigation.fly](https://bedrock.dev/docs/stable/Entities#minecraft%3Anavigation.fly) | 允许该实体像鹦鹉一样在空中生成路径。 |
| [minecraft:navigation.swim](https://bedrock.dev/docs/stable/Entities#minecraft%3Anavigation.swim) | 允许此实体生成包含水的路径。 |
| [minecraft:navigation.walk](https://bedrock.dev/docs/stable/Entities#minecraft%3Anavigation.walk) | 允许该实体像普通生物一样通过四处走动和上下跳跃来生成路径。 |
#### 导航能力
导航组件只能告诉实体如何生成路径,但不会说明在何时何地生成路径。这就是 **AI 组件**的用途。
AI 目标以**优先级**为前缀,并遵循优先级来选择要运行的行为。将首先选择优先级较低的行为来执行。
生成路径的 AI 组件太多,无法在本文档中列出。我们将提供一些示例:
| 组件 | 说明 |
| ------------------------------------------------------------ | ----------------------------------------------------------- |
| [minecraft:behavior.random_stroll](https://bedrock.dev/docs/stable/Entities#minecraft%3Abehavior.random_stroll) | 随机漫步,需要同时拥有 `movement``look_at` 相关的组件。 |
| [minecraft:behavior.follow_owner](https://bedrock.dev/docs/stable/Entities#minecraft%3Abehavior.follow_owner) | 允许该实体跟随主人。 |
| [minecraft:behavior.move_to_water](https://bedrock.dev/docs/stable/Entities#minecraft%3Abehavior.move_to_water) | 允许实体在陆地的情况下返回水体中。 |
| [minecraft:behavior.stroll_towards_village](https://bedrock.dev/docs/stable/Entities#minecraft%3Abehavior.stroll_towards_village) | 允许该实体在搜索范围内移动到村庄的随机位置。 |
完整的 AI 组件可以参考[这个列表](https://bedrock.dev/docs/stable/Entities#AI%20Goals)。
#### 为僵尸添加基础的行走能力
按照我们上述提过的步骤,首先在 `baby``adult` 组件组中添加上**移动速度**的定义,因为僵尸始终会处于这两个组件组中的其中一个:
```json
"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` 组件:
```json
"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 组件**
```json
"minecraft:behavior.random_stroll": {
"priority": 7,
"interval": 20,
"speed_multiplier": 1
}
```
进入游戏测试,就可以看见我们的僵尸行走了起来:
![基础的行走能力](./assets/0_3.gif)
### 实体攻击
要让实体具备攻击能力,需要许多不同的组件才能正常工作:
- 向目标移动的**移动**和**导航**能力;
- 自主选择攻击哪个实体的**目标选择**能力;
- **攻击**能力,如近战或远程;
- **攻击伤害和效果**的设置;
#### 选择目标
> ❗️**注意**
>
> 即时你正在制作一个**不具备移动能力**的实体(如炮塔),**仍然需要添加导航**组件,以便让你的实体能够找到要射击的实体。
有许多方法能够让实体产生敌意。最常见的类型,就是如下所示的 `nearest_attackable_target` 组件,它通常允许您定义的实体有兴趣攻击哪些实体:
```json
"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`。这个组件跟上面三个略微不同,因为它是用于检测和瞄准尝试眼神接触的实体。这个有所了解就好,用得不多。它的结构是这样的:
```json
"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](https://wiki.bedrock.dev/entities/entity-attack.html#melee) | 对单个目标造成伤害 |
| [minecraft:behavior.ranged_attack](https://wiki.bedrock.dev/entities/entity-attack.html#ranged) | 向目标发射弹射物 |
| [minecraft:area_attack](https://wiki.bedrock.dev/entities/entity-attack.html#area) | 对射程内的任何物体进行有效的近战攻击 |
| [minecraft:behavior.knockback_roar](https://wiki.bedrock.dev/entities/entity-attack.html#knockback-roar) | 与 minecraftarea_attack 类似,但更灵活 |
##### 近战攻击
近战攻击是最常见的类型,它们会造成击退:
```json
"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
}
```
##### 远程攻击
以指定的时间间隔向目标发射指定的抛射物,这里造成的伤害就取决于抛射物:
```json
"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 如下:
```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": {
// ...省略...
}
}
}
```
至此,我们就可以开始享受“跑路”了:
![僵尸跟着追](./assets/0_4.gif)
## 如何调试生物行为
在我们的测试客户端中,可以点击「设置」找到「调试」选项卡,下图中圈起来的就是跟生物行为相关的一些选项的(默认都是关闭的):
![测试客户端的调试设置](./assets/image-20231103114038608.png)
- 能见度边框:是否显示实体的碰撞箱;
![蓝色框就是行为 JSON 里面定义的碰撞箱](./assets/image-20231103114246018.png)
- 能见度路径:查看实体生成的路径,如果玩家有导航的能力,那么就会按照路径进行移动;
- 能见度目标状态:能够查看实体的 AI 组件列表,包含优先级、正在执行的、以及 **AI 组件依赖的基础组件**(括号里面就是依赖的组件);
![能见度目标状态演示](./assets/image-20231103114447470.png)
- 渲染生物信息状态:能够查看实体的属性列表、当前处于的**组件组**和正在执行的 AI 组件信息;
![生物信息状态演示](./assets/image-20231103114549090.png)
## 课后作业
本次课后作业,内容如下:
- 尝试在 `_b/entities` 新增一个 `zombie.json` 文件,修改原版僵尸的行为,使其具有基础的攻击和移动能力;
- 打开游戏客户端的调试功能,观察实体的行为;