实体命令
事件响应
运行实体命令更简单的方法是使用 queue_command 实体事件响应。
动画控制器
要触发斜杠命令,我们将使用行为包中的动画控制器。动画控制器应放置在类似路径下:animation_controllers/some_controller.json。你可以在bedrock.dev的实体事件章节了解更多关于动画控制器的内容。
简而言之,动画控制器允许我们从行为包中触发事件:
- 斜杠命令(如
/say) - Molang表达式(如
v.foo += 1;) - 实体事件(如
@s wiki:my_event)
以下是一个动画控制器的示例:
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.sirlich_entity_commands": {
"states": {
"default": {
"transitions": [
{
"on_summon": "1" //1会被判定为true
}
]
},
"on_summon": {
"on_entry": ["/say 我被召唤出来了"]
}
}
}
}
}这个动画控制器会在实体被召唤到世界时立即执行命令/say 我被召唤出来了。如果对这个机制感到困惑,请复习Molang、动画和实体事件相关内容。
简单来说,动画控制器包含多个状态,可以在on_entry子句中触发事件。我们通过查询条件在不同状态间切换。默认情况下,实体会处于default状态,除非定义了initial_state值。
WARNING
当世界/区块重新加载时,查询会重新执行。这意味着"/say 我被召唤出来了"实际上会在每次实体"加载"时运行——而不仅是在被召唤时。
如果需要避免这种情况,你需要添加额外的查询条件,比如skin_id查询。首次生成实体时检查skin_id = 0,然后设置更高的skin_id值(如skin_id = 1)。这样当实体重新加载时,就不会再次执行那些命令。文档后续会展示具体实现。
使用动画控制器
要将这个动画控制器添加到我们的实体中,可以在实体定义的description部分使用以下代码:
"description": {
"identifier": "wiki:entity_commands",
"scripts": {
"animate": [
"wiki:entity_commands"
]
},
"animations": {
"wiki:entity_commands": "controller.animation.wiki_entity_commands"
}
}再次提醒,如果对任何步骤感到困惑,请查阅实体事件文档。
通过事件触发命令
动画状态转换是通过查询条件创建的。你可以在这里阅读关于查询的内容。在我们的第一个例子中,查询条件只是简单的true,这意味着命令会自动执行。我们可以使用更复杂的查询条件来创建更有趣的效果。一个非常方便的方法是使用组件作为Molang过滤器来触发命令。
我个人喜欢使用skin_id。
我们可以更新动画控制器,使其基于skin_id触发:
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.sirlich_entity_commands": {
"states": {
"default": {
"transitions": [
{
"command_example": "q.skin_id == 1"
},
{
"zombies": "q.skin_id == 2"
}
]
},
"command_example": {
"transitions": [
{
"default": "q.skin_id != 1"
}
],
"on_entry": ["/say 执行命令一!", "@s execute_no_commands"]
},
"zombies": {
"transitions": [
{
"default": "q.skin_id != 2"
}
],
"on_entry": [
"/say 啊!到处都是僵尸!",
"/summon minecraft:zombie",
"/summon minecraft:zombie",
"/summon minecraft:zombie",
"/summon minecraft:zombie",
"@s execute_no_commands"
]
}
}
}
}
}现在这个动画控制器有两个命令状态:第一个由skin_id = 1触发,第二个由skin_id = 2触发。注意这里使用了==和!=运算符。==用于相等性测试,不要使用单个=。!表示逻辑非,因此!=用于测试不等于特定值的情况。另外请注意我在每个命令列表末尾都添加了@s execute_no_commands语法。稍后我们会创建execute_no_commands事件,它将允许我们把skin_id重置为0,从而可以重复使用这些命令。
语法是@s后跟一个实体事件名称。这允许我们从动画控制器中添加/移除组件。
设置组件组
回到实体文件中,我们可以使用skin_id组件来设置skin_id值。
skin_id组件如下所示:
"minecraft:skin_id": {
"value": 1
}我们可以添加包含skin_id的组件组:
"component_groups": {
"execute_no_commands": {
"minecraft:skin_id": {
"value": 0
}
},
"command_example": {
"minecraft:skin_id": {
"value": 1
}
},
"command_zombies": {
"minecraft:skin_id": {
"value": 2
}
}
}添加事件
现在让我们创建事件,以便轻松添加这些组件组:
"events": {
"minecraft:entity_spawned": {
"add": {
"component_groups": [
"execute_no_commands"
]
}
},
"execute_no_commands": {
"add": {
"component_groups": [
"execute_no_commands"
]
}
},
"command_example": {
"add": {
"component_groups": [
"command_example"
]
}
},
"command_zombies": {
"add": {
"component_groups": [
"command_zombies"
]
}
}
}触发事件
在Minecraft中有多种方式可以触发事件。如前所述,你可以使用动画控制器来触发事件。此外,我们来看两个具体示例:
交互组件
这个组件会在你点击实体时生成僵尸:
"minecraft:interact": {
"interactions": [{
"on_interact": {
"filters": {
"all_of": [{
"test": "is_family",
"subject": "other",
"value": "player"
}
]
},
"event": "command_zombies"
}
}]
}计时器
这个组件会每10秒触发一次示例命令:
"minecraft:timer": {
"looping": true,
"time": 10,
"time_down_event": {
"event": "example_command"
}
}通过将这些(以及类似的!)组件添加到我们的实体中,我们可以控制何时改变skin_id,从而控制哪些事件会被执行。
流程回顾
以下是整个工作流程:
- 使用交互或计时器等组件触发
example_command事件 - 这会添加
example_command组件组 - 进而添加
skin_id组件 - 设置实体的
skin_id值,该值可在动画控制器中被查询 - 动画控制器检测到这个
skin_id,并切换到example_command状态 - 动画控制器执行
/say命令 - 动画控制器执行实体事件
@s execute_no_command execute_no_command事件将skin_id重置为0- 动画控制器检测到这一变化,转回default状态
- 现在动画控制器等待新的
skin_id值









