实体计时器¶
在地图和附加包开发中,时间控制是极其常用的工具——延迟执行事件、周期性触发行为、随机化等待时间……实现这些的方案很多,本文整理了两大类:基于组件的计时器和基于动画的计时器。
基于组件的计时器¶
基于组件的计时器写在行为包的实体JSON文件中。优点是实体重载(卸载区块再加载)后计时仍会继续,因为组件状态会持久化。缺点是同种组件只能有一个实例,定义多个minecraft:timer时后者会覆盖前者。
minecraft:timer¶
这是最简单也最直接的计时组件,支持三种计时方式:
- 精确计时:在指定时间(秒)后触发事件
- 随机区间:在指定范围内随机选取一个时间触发
- 加权随机:从多个时间中按权重随机选取一个触发
精确计时示例(5.6秒后触发事件):
"minecraft:timer": {
"time": 5.6,
"time_down_event": {
"event": "wiki:my_event"
}
}
加权随机示例(分别有25%概率在0.5s、10s、30s、120s后触发):
"minecraft:timer": {
"looping": false,
"random_time_choices": [
{ "weight": 25, "value": 0.5 },
{ "weight": 25, "value": 10 },
{ "weight": 25, "value": 30 },
{ "weight": 25, "value": 120 }
],
"time_down_event": {
"event": "wiki:event",
"target": "self"
}
}
循环计时器结合随机事件:将looping设为true,每次到时间时触发一个使用randomize参数的事件,可以用一个计时器模拟多种概率行为:
"wiki:on_tick": {
"randomize": [
{
"weight": 1,
"add": { "component_groups": ["wiki:rare_event"] }
},
{
"weight": 5,
"add": { "component_groups": ["wiki:common_event"] }
},
{
"weight": 50
}
]
}
minecraft:environment_sensor¶
通过hourly_clock_time或clock_time过滤器,可以在特定游戏时间触发事件。以下示例在白天第800刻触发(游戏时间范围为0~24000):
"minecraft:environment_sensor": {
"triggers": [
{
"filters": {
"test": "hourly_clock_time",
"operator": "=",
"value": 800
},
"event": "wiki:my_daily_event"
}
]
}
minecraft:ageable¶
如果这个组件在实体行为中没有被用于其他用途,可以将其作为额外的计时器。它需要同时定义minecraft:is_baby组件才能正常工作。以下示例在4秒后触发事件:
"minecraft:is_baby": {},
"minecraft:ageable": {
"duration": 4,
"grow_up": {
"event": "wiki:my_event",
"target": "self"
}
}
其他可用组件¶
凡是有time_down_event或duration字段的组件,理论上都可以作为计时器使用。常见的还有:
minecraft:angry(需要目标,时间必须是整数)minecraft:behavior.hideminecraft:behavior.celebrate
基于动画的计时器¶
行为包动画是实现时间控制的另一种强大手段。优点是可以定义近乎"无限"数量的独立计时器。缺点是实体重载(区块卸载再加载)时所有动画会重置。
行为包动画的工作方式与资源包不同,如果你不熟悉,建议先阅读动画与动画控制器教程。
简单时间轴计时器¶
通过动画的timeline字段,可以在指定时间触发命令、Molang表达式或实体事件:
{
"format_version": "1.8.0",
"animations": {
"animation.wiki.example_timeline": {
"timeline": {
"0.0": "/say 这条命令立即执行",
"3.0": "/say 这条命令3秒后执行"
},
"animation_length": 3.1
},
"animation.wiki.long_timeline": {
"timeline": {
"0.0": ["/say 可以在同一时刻触发多条命令", "/say 只需用数组即可"],
"55.55": "/say 55.55秒后触发",
"100": "/say 100秒后触发"
},
"animation_length": 100.1
}
}
}
随机区间计时器¶
使用动画控制器配合math.random()可以模拟minecraft:timer的随机区间功能。以下示例在进入active状态后,随机等待2到7秒后退出:
"controller.animation.wiki.random_interval": {
"initial_state": "inactive",
"states": {
"inactive": {
"transitions": [{ "active": "q.is_sheared" }]
},
"active": {
"on_entry": [
"v.random_interval = math.random(2, 7);"
],
"animations": ["wiki:animate_interval"],
"transitions": [
{ "inactive": "q.anim_time >= v.random_interval" }
],
"on_exit": ["@s wiki:on_interval_end"]
}
}
}
说明
animation_length要大于随机区间的最大值(这里是7),100是一个通用安全值。
加权随机计时器¶
以下示例实现加权随机:在2s(权重30%)、5s(权重60%)或9s(权重10%)后触发事件。
"controller.animation.wiki.random_choices": {
"initial_state": "inactive",
"states": {
"inactive": {
"transitions": [{ "active": "q.is_powered" }]
},
"active": {
"on_entry": [
"v.choice = math.random(0, 100);"
],
"animations": ["wiki:animate_choices"],
"transitions": [
{ "inactive": "q.anim_time >= 2.0 && v.choice < 30" },
{ "inactive": "q.anim_time >= 5.0 && v.choice < 90" },
{ "inactive": "q.anim_time >= 9.0 && v.choice <= 100" }
],
"on_exit": ["@s wiki:on_choice_end"]
}
}
}
权重计算方式
各行的阈值是权重的累加:30%取030,60%取3090,10%取90~100。转移条件从时间最短到最长排列,确保短时间条件优先判断。