跳到主要内容

游戏事件行为

GES · Visual Workflow

在事件的 Behavior 窗口中配置条件门、UnityEvent 动作、延迟、重复调度与跨场景持久化

面向不写监听代码、直接在 Inspector 中连接事件反应的开发者

在 Game Event Editor 中打开一条事件的 Behavior,可查看管理器绑定的回调与事件资产上的调度设置

Game Event Behavior 中的事件信息、条件、回调和调度

上图中,Event Information 确认正在编辑的事件,Action Condition 与 Event Action 决定管理器何时执行哪些回调,Schedule Configuration 负责事件的延迟、重复和跨场景持久化


打开行为窗口​

从 游戏事件编辑器 访问:

游戏事件编辑器 → 点击任意事件行上的行为按钮(彩色药丸)

按钮颜色状态:

颜色图标含义详情
🟢 绿色✓已配置(Inspector)在Manager中有UnityEvent动作
🔵 蓝色▶运行时活动(播放模式)通过 AddListener() 有基于代码的监听器
🟡 橙色⚠未配置无动作或监听器

按钮标签:显示事件类型签名(例如,<void>、<int>、<GameObject, DamageInfo>)


窗口概览​

行为窗口有四个主要部分:

  1. 事件信息 - 身份确认(名称、类别、GUID)
  2. 动作条件 - 可视化逻辑树(执行门控)
  3. 事件动作 - UnityEvent回调(要执行什么)
  4. 调度配置 - 时间控制(延迟、循环、持久化)

1. 事件信息​

只读摘要,确认您正在编辑正确的事件

Event Information

显示的数据:

  • 事件名称:资产名称
  • 类别:组织分组
  • GUID:唯一的内部标识符(在重命名后保留)

在数据库中重命名事件时,事件的内部 GUID 保持不变,UnityEvent 回调方法和 Unity 资产引用由各自的序列化信息保存


2. 动作条件(执行门控)​

逻辑引擎:仅当这些条件评估为 TRUE 时,动作才会执行

Action Condition Section

它的作用​

Behavior 条件作用于 Game Event Manager 绑定的回调,单个组件的条件在对应 Receiver 的 Inspector 中配置,见 Receiver 动作条件

根据运行时值控制是否执行动作:

可视化逻辑树​

无需代码即可构建复杂的布尔逻辑,使用:

  • 组:使用AND/OR逻辑组合条件
  • 比较:单个检查(例如,Health < 20)
  • 嵌套:组内嵌套组(无限深度)

性能​

AOT 安全条件

IL2CPP 构建前运行 Bake AOT Conditions,GES 会生成运行时使用的求值器注册表,序列化条件缺失或过期时会阻止构建

了解更多​

在条件树中用数据源和比较运算配置判断,用 AND 或 OR 组合多个条件

  • 4种源类型:事件参数、场景类型、随机、常量
  • 10种比较运算符:数值、字符串、集合检查
  • Bool方法支持:使用自定义 bool 方法作为条件
  • 拖放重新排序:可视化组织逻辑
  • 类型验证:自动检测不兼容的比较

📖 完整指南:可视化条件树


3. 事件动作(回调层)​

动作定义了在事件被触发且满足所有条件后执行的Unity回调

Event Action 中 Unity 原生的 UnityEvent 列表

在 Event Action 中,使用原生 UnityEvent 列表的 + 添加回调,拖入目标对象后选择要调用的方法

理解UnityEvent字段​

系统基于Unity原生的 UnityEvent 架构,因此可以直接接入你现有的MonoBehaviour和UI组件


对于无参数事件(GameEvent)​

仅标准触发逻辑

类型后端字段兼容性
逻辑UnityEvent (void)🟢 接受任何 零参数 方法

示例: OnGameStart ➔ AudioManager.PlayBGM()、UI.FadeIn()


对于单参数事件(GameEvent<T>)​

监听器方法直接接收事件传入的参数

类型后端字段兼容性
逻辑UnityEvent<T>🟡 接受具有 一个类型T参数 的方法

示例: OnHealthChanged(float) ➔ HealthBar.UpdateFill(float)


对于Sender事件(GameEvent<TSender, TArgs>)​

监听器方法同时接收事件的发送者和参数

类型后端字段兼容性
逻辑UnityEvent<TSender, TArgs>🔵 接受具有 两个参数 的方法

示例: OnDamage(GameObject, int) ➔ VFXManager.SpawnAt(GameObject.pos)、Popup.Show(int)

原生集成

因为我们使用 原生UnityEvent,您可以直接在Inspector中或通过代码使用AddListener()分配监听器

它支持 静态 和 动态 调用

签名匹配

Inspector UI将自动过滤方法列表,仅显示与事件签名匹配的函数,防止运行时错误


添加动作(工作流)​

添加动作:目标对象、函数下拉菜单与参数

按照这三个简单步骤通过Unity Inspector连接您的逻辑

1. 分配目标对象​

将包含您逻辑的GameObject或Component 拖放 到 Object 插槽中

  • 🖱️ 操作: 从层级视图拖动 ➔ 放入空插槽
  • 📦 结果: 该字段现在引用您脚本的特定实例

2. 选择回调方法​

点击 Function Dropdown 浏览分配对象上所有可用的公共方法

  • 🔍 操作: 点击No Function ➔ 导航到您的脚本/组件
  • ⚡ 提示: 只有与 事件签名 匹配的方法(例如,void、int)才会出现在顶部以便于选择

3. 定义参数映射​

决定是使用事件的实时数据还是固定值

  • ⚖️ 动态调用: 使用事件发送的 运行时值(例如,实际造成的伤害)
  • ⚙️ 静态参数: 使用您在Inspector中手动定义的 固定值

动态与静态:选择哪一个?​

模式视觉图标最适合...
动态🚀实时数据(例如,使用当前HP更新生命条)
静态📌固定触发(例如,记录"按钮已点击"到控制台)
专业提示

在下拉菜单中,动态 方法始终列在菜单的 顶部

如果您没有看到您的方法,请检查参数类型是否完全匹配!


动态与静态函数​

动态(带事件数据):

// 接收事件参数
public void TakeDamage(float amount) {
health -= amount;
}

// 对于Sender事件
public void OnDamageReceived(GameObject attacker, DamageInfo info) {
// 同时使用sender和args
}

静态(忽略事件数据):

// 不需要参数
public void PlaySound() {
audioSource.Play();
}

何时使用每种:

使用动态当使用静态当
您需要事件的数据只需要通知
处理float/int值播放声音/效果
检查sender引用触发动画
数据驱动的反应状态变化

多个动作与优先级​

添加多个:重复点击+以添加更多动作

执行顺序:从上到下

重新排序:拖动每个动作左侧的☰把手

示例:

📜 LogDamageEvent() ➔
🥇 第一(元数据/日志记录)
🎵 PlayHitSound() ➔
🥈 第二(音频/VFX反馈)
📊 UpdateHealthBar(float) ➔
🥉 第三(UI/视觉表示)
🏁 CheckDeathCondition() ➔
🏆 最终(游戏状态逻辑)

清除所有动作​

点击 "Clear All" 按钮(右上角)一次性删除所有动作

⚠️ 显示确认:"您确定吗?"


4. 调度配置​

调度层决定在事件触发后何时以及多久执行一次您的动作

调度配置部分:延迟、间隔、次数与持久化

动作延迟​

**时间偏移

** 在事件触发和实际执行之间引入间隙

  • 🕒 值: float(秒)
  • 🎯 目的: 与动画、VFX或延迟游戏逻辑同步

工作原理:

  1. 🔔 事件触发 ➔ 接收到信号
  2. ⏳ 延迟中 ➔ 系统等待指定的X秒
  3. 🔍 条件检查 ➔ 在等待之后重新验证条件
  4. 🚀 执行 ➔ 仅当条件仍然通过时才触发动作

故障排除​

动作未执行​

问题:事件触发但什么都没发生

检查清单:

✅ 检查条件:

1. 条件是否启用?(在条件部分切换)
2. 条件是否评估为TRUE?
3. 测试条件逻辑 - 参见可视化条件树指南
4. 添加Debug.Log()以验证值

✅ 检查动作:

1. UnityEvent字段是否为空?添加动作!
2. 目标GameObject是否被销毁?
3. 目标Component是否被禁用?
4. 检查控制台是否有错误

✅ 检查调度:

1. 动作延迟是否太长?
2. 重复间隔是否造成混淆?
3. 事件是否在不应该时是持久化的?

"找不到字段"警告​

问题:Field 'IntGameEventAction' not found.

原因:事件类型缺少其绑定代码

解决方案:

点击 "Force Rebuild All (Fix Missing Bindings)" 按钮

这会重新生成所有绑定字段:

Assets/TinyGiants/GameEventSystem/Data/CodeGen/Events/Basic/
└─ IntGameEvent.cs(使用绑定字段重新生成)

编译后:重新打开行为窗口


动作触发多次​

问题:动作执行次数超过预期

常见原因:

原因1:重复设置

检查:
- 重复间隔 > 0?
- 重复计数 > 0?

如果是,事件正在循环(有意或无意)

原因2:多次事件触发

代码中多次触发事件:
OnHealthChanged.Raise(newHealth); ← 重复调用

解决方案:确保事件仅在需要时触发

原因3:多个监听器

在UnityEvent中多次添加相同动作

解决方案:检查动作列表,删除重复项

下一步

现在您已经了解了事件行为,探索 可视化条件树 以掌握高级条件逻辑

或跳转到 流程编辑器 构建事件编排!