Skip to content

附.5 事件/触发器速查表及事件时机对照表

本附录集中整理 Mindustry 的事件系统:一部分是 EventType 里的事件类(带数据),另一部分是 EventType.Trigger 的触发器(无数据、频率高)。你可以把它当成“事件总线的完整导航”,在写 Java 模组或调试逻辑时快速定位“该用哪个事件、在什么时候触发、是否能安全修改世界”。

事件系统速览

Mindustry 的事件系统基于 arc.Events事件类是“带参数的通知”,需要事件对象;触发器是“无参数的信号”,只是一个枚举值。两者都通过 Events.on(...) 注册监听,通过 Events.fire(...) 触发。

常用写法如下:

java
import arc.Events;
import mindustry.game.EventType;

// 监听有数据的事件
Events.on(EventType.BlockBuildEndEvent.class, e -> {
    if(!e.breaking){
        // 这里可以安全读取 e.tile / e.team / e.unit / e.config
    }
});

// 监听无数据的触发器
Events.on(EventType.Trigger.update, () -> {
    // 每帧都会执行,慎用重逻辑
});

触发器也可以用 Events.run(Trigger.xxx, runnable) 来注册,这种写法在原版里非常常见,本质仍是监听回调。需要强调的是:事件回调几乎都在主线程里执行,不要在事件中做阻塞操作;若确实需要,应该把耗时工作放入后台线程,或使用 Core.app.post(...) 回到主线程更新 UI / 游戏状态。

事件对象复用与安全边界

以下事件对象会被复用:BuildDamageEventTilePreChangeEventTileChangeEventTileFloorChangeEventTileOverlayChangeEventBuildTeamChangeEventUnitDamageEvent。它们的共同特点是事件实例被反复塞入新数据,因此不要缓存事件对象,也不要延迟使用。此外,TilePreChangeEvent / TileChangeEvent 这类事件明确写了警告:不要在监听里修改格子或触发新的改格操作,否则容易造成递归或异常。

触发器 Trigger 速查表

触发器无参数,适合做统计、成就、提示或轻量逻辑。下表按照原版触发位置与功能归类,尽可能给出“具体发生点”。如果你是做大体量逻辑,应优先用“事件类”,触发器更适合做轻量监听。

Trigger触发时机与来源典型用途/备注
shock“潮湿”与“电击”状态产生联动时触发常用于成就统计;只在敌方波次单位触发
blastFreeze“爆裂”与“冻结”状态产生联动时触发成就统计;只在敌方波次单位触发
cannotUpgrade重构器尝试升级但失败时触发提示或统计“升级失败”
openConsole打开控制台(Console)时触发统计或埋点
impactPower“冲击反应堆”进入满输出阶段时触发用于高功率开始的提示或成就
blastGenerator使用 ConsumeItemExplode 的方块发生爆炸时触发与“反应堆爆炸”规则相关
shockwaveTowerUse“震爆塔”使用时触发与波次统计或提示相关
forceProjectorBreak“力墙投影”因过热而破裂时触发统计防御失效
thoriumReactorOverheat“钍反应堆”过热时触发反应堆安全提示
neoplasmReact“瘤液”与其它液体发生扩散反应时触发瘤液生态相关逻辑
fireExtinguish火焰被扑灭时触发统计灭火或触发提示
acceleratorUse“行星际加速器”启动时触发战役进度或提示
newGame新局或新战役开始时触发(原版多个入口都会发)初始化阶段逻辑
tutorialComplete教程完成时触发教程统计;原版暂未广泛使用
flameAmmo炮塔收到“硫化物”弹药时触发提示“火焰弹药”被使用
resupplyTurret炮塔从“无弹药”到“有弹药”的首次补给时触发用于提示“已补给”
turretCool炮塔首次接受冷却液时触发用于教程或统计冷却
enablePixelation开启像素化渲染时触发UI / 视觉设置
exclusionDeath玩家单位被超高伤害瞬杀时触发多用于成就或统计
suicideBomb单位自爆时触发成就或提示
openWiki点击“Wiki”链接时触发埋点或引导
teamCoreDamage核心受到伤害时触发核心警报提示
socketConfigChanged服务器 socket 配置变更时触发仅服务器环境
unitCommandChange玩家单位指令发生变化时触发RTS 指令 UI
unitCommandPositionRTS 位置指令发出时触发RTS 指令 UI
unitCommandAttackRTS 攻击指令发出时触发RTS 指令 UI
importMod导入模组完成时触发模组管理相关
update每帧更新开始时触发频率极高,慎用
beforeGameUpdate游戏进行中且未暂停时,逻辑更新开始前触发频率极高,适合轻逻辑
afterGameUpdate游戏进行中且未暂停时,逻辑更新结束后触发常用于“更新后再做一次”的逻辑
preDraw渲染流程开始前触发仅客户端,渲染前准备
draw渲染流程中段触发(大部分世界绘制前)常用于插入绘制
drawOver世界与 UI 部分绘制后触发适合做覆盖层绘制
postDraw渲染流程末尾触发渲染收尾处理
uiDrawBeginUI 绘制开始时触发UI 注入绘制
uiDrawEndUI 绘制结束时触发UI 收尾
universeDrawBegin星图背景绘制开始前触发仅在行星渲染时触发
universeDraw星图行星绘制阶段触发可用于改写星图特效
universeDrawEnd星图绘制结束后触发星图后处理

事件 EventType 速查表

事件类是“带数据的通知”。你在回调中可以读取事件字段,常用于触发逻辑、统计数据、重建缓存或做调试记录。下面按功能分组给出完整事件列表。

1. 启动、加载与生命周期事件

事件字段触发时机与说明
ClientCreateEvent客户端启动早期,客户端实例创建后触发
ClientLoadEvent客户端资源加载完成后触发,常用于注册 UI / 纹理
ServerLoadEvent独立服务器加载完成后触发
PlayEvent游戏开始(进入一局)时触发
ResetEvent游戏状态被重置时触发(返回菜单、重新载入等)
HostEvent创建房间/主机时触发
DisposeEvent渲染器销毁时触发,适合释放资源
ResizeEvent客户端窗口尺寸改变后触发
StateChangeEventState from, State to游戏状态切换(菜单、进行中、编辑器等)
ContentInitEvent所有内容初始化完成后触发
ModContentLoadEvent模组内容加载完成但尚未初始化时触发
AtlasPackEvent贴图打包完成后触发,像素仍未释放
FileTreeInitEvent所有模组文件加入 Vars.tree 后触发
MusicRegisterEventSoundControl 注册音乐后触发

2. 世界加载与存档相关

事件字段触发时机与说明
WorldLoadBeginEvent世界开始加载时触发,generating = true
WorldLoadEndEvent格子初始化完成、即将更新邻接与物理时触发
WorldLoadEvent世界加载完成时触发;实体尚未完全加载
SaveWriteEvent保存写入时触发
SaveLoadEventboolean isMap保存读取完成时触发,isMap 表示是否为地图保存
ContentPatchLoadEventSeq<String> patches读取存档补丁时触发,可修改 patches 列表

3. 战役、区块与波次

事件字段触发时机与说明
WaveEvent波次开始时触发,服务器与客户端均可能收到
TurnEvent战役回合推进时触发(Universe 逻辑)
SectorCaptureEventSector sector, boolean initialCapture区块被占领时触发,initialCapture 为首次占领
SectorLoseEventSector sector离线状态下区块被波次摧毁时触发
SectorInvasionEventSector sector区块发生入侵事件时触发
SectorLaunchEventSector sector发射到新区块时触发
SectorLaunchLoadoutEventSector sector, Sector from, Schematic loadout发射载荷生成时触发
LaunchItemEventItemStack stack“发射台(旧版)”发射物品时触发

4. 地图与蓝图

事件字段触发时机与说明
MapMakeEvent创建地图时触发(编辑器)
MapPublishEvent发布地图时触发
SchematicCreateEventSchematic schematic生成新蓝图时触发

5. 输入与界面

事件字段触发时机与说明
TapEventPlayer player, Tile tile玩家点击/触碰格子时触发
LineConfirmEvent玩家确认一条铺设线时触发(桌面/移动)
BlockInfoEvent打开某个方块信息面板时触发
MenuOptionChooseEventPlayer player, int menuId, int option菜单选项被选择时触发(已不推荐直接使用)
TextInputEventPlayer player, int textInputId, String text文本输入结束时触发,text 可能为 null
ClientChatEventString message客户端发送聊天消息时触发,仅客户端
PlayerChatEventPlayer player, String message玩家聊天消息到达服务器时触发

6. 建造与方块相关

事件字段触发时机与说明
BuildSelectEventTile tile, Team team, Unit builder, boolean breaking开始建造或拆除时触发(选择阶段)
BlockBuildBeginEventTile tile, Team team, Unit unit, boolean breaking构建开始时触发,unit 可能为 null
BlockBuildEndEventTile tile, Team team, Unit unit, boolean breaking, Object config构建结束时触发,config 可能为 null
BuildRotateEventBuilding build, Unit unit, int previous建筑旋转后触发,unit 可能为 null
ConfigEventBuilding tile, Player player, Object value配置发生变化时触发,player 可能为 null
BlockDestroyEventTile tile方块即将被摧毁时触发
BuildDamageEventBuilding build, Bullet source子弹对建筑造成伤害时触发(对象复用,不保证覆盖全部伤害场景)
BuildingBulletDestroyEventBuilding build, Bullet bullet建筑被子弹直接击毁时触发(不保证全部场景)
GeneratorPressureExplodeEventBuilding build压力型反应堆爆炸时触发
BuildTeamChangeEventTeam previous, Building build建筑队伍变更后触发(对象复用)
CoreChangeEventCoreBuild core核心放置/移除/换队伍时触发
WithdrawEventBuilding tile, Player player, Item item, int amount玩家从建筑中取出物品
DepositEventBuilding tile, Player player, Item item, int amount玩家向建筑存入物品
TilePreChangeEventTile tile格子即将发生变化(对象复用,禁止改格)
TileChangeEventTile tile格子已发生变化(对象复用,禁止改格)
TileFloorChangeEventTile tile, Floor previous, Floor floor地板变化事件(对象复用)
TileOverlayChangeEventTile tile, Floor previous, Floor overlay覆盖层变化事件(对象复用)

7. 单位、载荷与战斗

事件字段触发时机与说明
UnitControlEventPlayer player, Unit unit玩家开始/结束控制某单位时触发,unit 可能为 null
UnitChangeEventPlayer player, Unit unit玩家切换单位时触发
UnitCreateEventUnit unit, Building spawner, Unit spawnerUnit单位由工厂/重构器/单位生成时触发,后两者可为 null
UnitSpawnEventUnit unit波次刷出单位时触发
UnitUnloadEventUnit unit单位被载荷建筑弹出时触发
PickupEventUnit carrier, Unit unit, Building build载荷拾取,unit/build 二选一
PayloadDropEventUnit carrier, Unit unit, Building build载荷投放,unit/build 二选一
UnitDamageEventUnit unit, Bullet bullet子弹命中单位(对象复用)
UnitDestroyEventUnit unit单位被摧毁时触发
UnitBulletDestroyEventUnit unit, Bullet bullet单位被子弹直接击毁时触发(不保证覆盖全部死亡场景)
UnitDrownEventUnit unit单位溺水或被液体摧毁时触发
GameOverEventTeam winner游戏结束时触发(逻辑层)
WinEvent玩家胜利时触发(UI 层)
LoseEvent玩家失败时触发(UI 层)

8. 玩家、网络与管理

事件字段触发时机与说明
ConnectionEventNetConnection connection客户端建立连接时触发
ConnectPacketEventNetConnection connection, ConnectPacket packet收到连接包时触发
PlayerConnectPlayer player玩家连接但尚未加入游戏
PlayerConnectionConfirmedPlayer player玩家确认已接收世界数据
PlayerJoinPlayer player玩家正式进入游戏,仅首次触发
PlayerLeavePlayer player玩家离开游戏
PlayerBanEventPlayer player, String uuid玩家被封禁时触发,player 可为空
PlayerUnbanEventPlayer player, String uuid玩家解禁时触发,player 可为空
PlayerIpBanEventString ipIP 被封禁时触发
PlayerIpUnbanEventString ipIP 解禁时触发
AdminRequestEventPlayer player, Player other, AdminAction action管理员指令请求

9. 解锁与研究

事件字段触发时机与说明
UnlockEventUnlockableContent content内容解锁时触发(远程同步也会触发)
ResearchEventUnlockableContent content研究完成时触发(研究面板)

事件时机对照表

这一部分给出“宏观时序”,用来帮助你把事件放在正确的时间点使用。

启动与加载阶段(典型顺序)

大致顺序如下(不同平台和模式略有差异,但核心流程一致):

  1. ClientCreateEvent / ServerLoadEvent:客户端或服务器启动完成。
  2. FileTreeInitEvent:模组文件树完成注册。
  3. ModContentLoadEvent:模组内容加载完成,但尚未初始化。
  4. ContentInitEvent:内容初始化完成。
  5. AtlasPackEvent:贴图打包完成,像素仍在内存里。
  6. MusicRegisterEvent:音乐注册完成。
  7. ClientLoadEvent:客户端资源完全就绪。

如果你要“改内容、改贴图、加成就”,通常应分别选择 ModContentLoadEventContentInitEventAtlasPackEventClientLoadEvent

世界加载阶段(地图/存档)

  • WorldLoadBeginEvent:开始加载地图,generating = true
  • WorldLoadEndEvent:格子初始化完毕,准备更新邻接和物理。
  • WorldLoadEvent:世界加载完成,generating = false

特别提醒:有时 WorldLoadEvent 可能会出现重复触发(原版代码中对此有注释),如果你在这里做缓存初始化,需要注意去重。

主循环更新阶段(逻辑)

Logic.update() 中,每帧会触发:

  • Trigger.update:无论是否在游戏内都会触发。
  • Trigger.beforeGameUpdate:游戏进行中且未暂停时触发。
  • 逻辑更新(单位、天气、波次、任务等)。
  • Trigger.afterGameUpdate:逻辑更新结束后触发。

所以如果你要“每帧做轻量处理”,用 Trigger.update;如果你要“只在对局中生效”,用 beforeGameUpdate / afterGameUpdate

渲染阶段(客户端)

Renderer.draw() 中顺序为:

  • Trigger.preDraw:渲染开始前。
  • Trigger.draw:世界绘制前后交界处。
  • 主要世界与特效绘制。
  • Trigger.drawOver:世界绘制结束后。
  • Trigger.postDraw:渲染末尾。

如果需要对 UI 做插入,使用 Trigger.uiDrawBeginTrigger.uiDrawEnd。如果你要修改星图渲染,使用 Trigger.universeDrawBegin / Trigger.universeDraw / Trigger.universeDrawEnd

建造与战斗阶段(高频但可控)

  • 建造:BuildSelectEventBlockBuildBeginEventBlockBuildEndEvent,拆除时 breaking = true
  • 伤害:BuildDamageEvent / UnitDamageEvent 高频触发,注意对象复用。
  • 击毁:BuildingBulletDestroyEvent / UnitBulletDestroyEvent 只在“被子弹直接击毁”时触发,不保证覆盖所有死亡场景

如果你需要稳定地统计死亡或销毁,请同时监听 UnitDestroyEventBlockDestroyEvent

实战建议与常见误区

  • 高频触发器不要做重逻辑Trigger.updateTrigger.draw 每帧都会触发,建议只做轻量处理或计时器逻辑。
  • 不要在 Tile 变更类事件里改 TileTilePreChangeEvent / TileChangeEvent / TileFloorChangeEvent / TileOverlayChangeEvent 都明确禁止在回调里再次修改格子。
  • 复用事件不要缓存。遇到“事件被复用”的类型,只能在当前回调内使用。
  • 客户端与服务器事件不同步。如 ClientChatEvent 只在客户端触发,ServerLoadEvent 只在服务器触发,写逻辑时要注意环境判断。
  • 以事件为准而不是 UIWinEvent / LoseEvent 更贴近 UI,逻辑判定请用 GameOverEvent 或规则检查。

这一份附录覆盖了 EventType 中现有的全部事件与触发器。随着版本更新,事件集合可能变化;当你发现某个事件不存在或行为变化时,最稳妥的方式仍是直接查看 core/src/mindustry/game/EventType.java 与事件触发处的代码。