能否脱离Delegate仅使用Event?Unity场景下实现方式咨询
嘿,这个问题问得挺实在的!很多刚接触Events的朋友都会有这个疑惑——毕竟网上教程大多是Delegate和Event一起讲,容易让人觉得它们是绑定死的必选项。
先给你明确答案:严格来说,Event本身不能完全脱离Delegate存在,因为Event本质上是对Delegate实例的一种安全封装(限制外部只能订阅/取消订阅,不能直接触发)。但你说的“不需要使用Delegate”,应该是指不想自己手动定义自定义的Delegate类型吧?那完全可以做到!我们可以用.NET内置的通用Delegate类型(比如Action、Action<T>)来简化代码,不用自己写额外的Delegate声明,看起来就像是“单独用Event”一样。
1. 在Player类中声明Event(用内置Action)
如果你不需要传递任何参数,直接用无参的Action就够了;如果需要传递数据(比如子弹类型、伤害值),就用带泛型的Action<T>、Action<T1,T2>等。
示例代码(无参版):
public class Player : MonoBehaviour { // 直接基于内置Action声明Event,无需自定义Delegate public event Action Shoot; // 你手动触发Event的方法(比如玩家按发射键时调用) public void FireBullet() { // 先判断有没有订阅者,避免空引用异常 Shoot?.Invoke(); // 这里写发射子弹的核心逻辑,比如生成子弹对象等 } }
2. 监听器脚本的订阅与处理
在另一个GameObject的脚本里,订阅Player的Shoot事件,当事件触发时执行你想要的逻辑:
public class BulletEffectListener : MonoBehaviour { // 在Inspector面板中拖入你的Player对象 public Player targetPlayer; private void OnEnable() { // 订阅Shoot事件,关联到我们要执行的方法 targetPlayer.Shoot += PlayShootEffect; } private void OnDisable() { // 务必取消订阅,防止对象销毁后出现内存泄漏 targetPlayer.Shoot -= PlayShootEffect; } // 事件触发时执行的方法,签名要和Action完全匹配(无参数、无返回值) private void PlayShootEffect() { Debug.Log("玩家开枪了!播放枪口火焰特效 + 射击音效"); // 这里写你的具体业务逻辑,比如实例化特效、播放音频等 } }
进阶:带参数的Event示例
如果需要在触发Shoot事件时传递额外数据(比如子弹伤害),只需要把Action换成带泛型的版本:
// Player类中的Event声明 public event Action<int> Shoot; // 触发时传递参数 public void FireBullet(int bulletDamage) { Shoot?.Invoke(bulletDamage); } // 监听器的方法也要对应修改参数 private void PlayShootEffect(int damage) { Debug.Log($"玩家发射了子弹,伤害值:{damage}"); }
为什么说Event离不开Delegate?因为event关键字后面必须跟一个Delegate类型——不管是你自己定义的public delegate void ShootDelegate();,还是.NET内置的Action,本质都是Delegate。但用内置的通用Delegate类型,就可以省去你手动定义Delegate的步骤,完美符合你“只想单独使用Event”的需求。
内容的提问来源于stack exchange,提问作者Jacob

