Appearance
委托、事件、Action
核心理解
委托就是“能存方法的变量”。
c
public delegate void DamageHandler(int damage);
void PlayHitSound(int damage)
{
Debug.Log("播放受击音效");
}
DamageHandler handler = PlayHitSound;
handler(10);DamageHandler 规定:能放进来的方法必须是 void 返回值,并且有一个 int 参数。
Action 是什么
Action 是 C# 已经帮你定义好的常用委托,表示“没有返回值的方法”。
c
Action onDied;
Action<int> onHpChanged;
Action<int, int> onHpChangedWithOldNew;所以很多时候你不用自己写:
c
public delegate void DieHandler();直接写:
c
public Action OnDied;event 是什么
event 是给委托加一层安全限制。
c
public event Action OnDied;外部脚本只能:
c
health.OnDied += ShowGameOver;
health.OnDied -= ShowGameOver;外部不能随便 Invoke,也不能直接 = null 清空。 也就是说:发布者自己触发事件,订阅者只能订阅或取消订阅。
Unity 常见写法
c
public class Health : MonoBehaviour
{
public event Action<int, int> OnHpChanged;
public event Action OnDied;
private int hp = 100;
public void TakeDamage(int damage)
{
int oldHp = hp;
hp -= damage;
OnHpChanged?.Invoke(oldHp, hp);
if (hp <= 0)
{
OnDied?.Invoke();
}
}
}订阅者:
c
void OnEnable()
{
health.OnHpChanged += RefreshHpBar;
health.OnDied += ShowGameOver;
}
void OnDisable()
{
health.OnHpChanged -= RefreshHpBar;
health.OnDied -= ShowGameOver;
}记住这套关系
delegate:定义一种“方法形状”。 Action:C# 内置的无返回值委托。 Func:C# 内置的有返回值委托。 event:受保护的委托,只允许外部订阅和取消订阅。 UnityEvent:Unity 的可序列化事件,可以在 Inspector 里拖对象配置回调。
选择口诀
代码内部模块通信:优先 event Action。 需要在 Inspector 里配置:用 UnityEvent。 事件订阅了:记得在 OnDisable 里取消订阅。
参考链接