Unity中的C#委托与事件

在Unity开发中,C#的委托(Delegate)​事件(Event)​就像一对双胞胎兄弟,曾困惑于它们的本质区别。本文将通过实战案例揭开这对”孪生兄弟”的神秘面纱,了解它们的正确使用姿势。

一、委托:灵活的函数指针

1.1 委托的本质

委托本质上是一个类型安全的函数指针容器,可以存储多个方法引用。我们可以通过+=运算符实现多播委托:

public delegate void HealthHandler(float health);

public class Player {
    public HealthHandler OnHealthChanged;

    public void TakeDamage(float damage) {
        currentHealth -= damage;
        OnHealthChanged?.Invoke(currentHealth);
    }
}

1.2 委托的妙用场景

  • 实现回调系统(如成就解锁)
  • 跨脚本通信(非MonoBehaviour类间通信)
  • 异步操作处理(如资源加载完成回调)

二、事件:安全的委托封装器

2.1 事件的核心特征

事件在委托基础上添加了访问控制层,使用event关键字声明:

public class Achievements {
    public event Action OnAchievementUnlocked;

    private void Unlock(string achievementName) {
        OnAchievementUnlocked?.Invoke(achievementName);
    }
}

2.2 事件的安全机制

  • 封装性:外部类只能订阅/取消订阅(+=/-=)
  • 访问控制:仅声明类可触发事件
  • 线程安全:编译器自动生成线程同步代码

三、关键差异对比表

特性 委托 事件
访问权限 公共可调用 仅声明类可触发
赋值操作 支持=赋值 仅支持+=/-=
多播能力 原生支持 通过委托机制支持
空引用检查 需手动检查 自动生成空检查代码
设计目的 通用回调机制 观察者模式实现
典型应用场景 函数参数、回调列表 UI交互、游戏事件通知

四、Unity实战案例解析

4.1 委托实现技能冷却系统

public class SkillSystem {
    public delegate void CooldownCallback(int skillID);
    public CooldownCallback OnCooldownStart;

    public void CastSkill(int skillID) {
        // 释放技能逻辑
        OnCooldownStart?.Invoke(skillID);
    }
}

// 使用端
skillSystem.OnCooldownStart += id => Debug.Log($"技能{id}开始冷却");

4.2 事件实现成就系统

public class AchievementSystem {
    public event Action<string> OnAchievementCompleted;

    public void CompleteAchievement(string name) {
        OnAchievementCompleted?.Invoke(name);
    }
}

// 订阅端
achievementSystem.OnAchievementCompleted += name => {
    PlayEffect(name);
    UpdateUI(name);
};

五、设计选择指南

✅ ​使用委托当:​

  • 需要函数作为参数传递时
  • 实现回调函数列表时
  • 需要直接控制调用时

✅ ​使用事件当:​

  • 构建发布-订阅系统时
  • 需要保护触发权限时
  • 处理UI交互事件时
  • 实现系统解耦时

六、性能优化贴士

  1. 避免每帧触发高频事件(如Update中的物理检测)
  2. 及时取消订阅防止内存泄漏
  3. 对高频事件使用EventManager集中管理
  4. 值类型参数优先使用ref传递
  5. 使用对象池重用事件参数

结语

理解委托和事件的区别就像掌握魔法世界中的两种咒语:委托是灵活的基础咒语,而事件则是施加了保护咒的强化版本。在Unity开发中,建议80%的场景使用事件,仅在需要完全控制调用时使用原始委托。记住:​事件不是委托的替代品,而是其安全封装形态。合理运用这对黄金组合,可以让游戏代码既优雅又高效!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>