总结
- Action = C# 无返回值委托 ,Unity 中用来做事件 / 回调
- 声明:
Action、Action<T>、Action<T1,T2> - 调用:
action?.Invoke(); - 注册:
action += 方法; - 作用:解耦代码、跨脚本通信
一、Action 到底是什么?
- 本质 :
System.Action是 C# 官方封装好的 无返回值委托(delegate) - 作用:存储 ** 没有返回值(void)** 的方法,可以像变量一样传递、调用
- 分类 :
Action:无参数、无返回值Action<T>:1 个参数、无返回值Action<T1,T2>:2 个参数、无返回值- 最多支持 16 个参数
简单记:Action = 可以存方法的变量,只能存 void 方法
二、 Action 在 Unity 中的声明方式
1. 最基础:无参数 Action
cs
// 声明一个 Action 变量
public Action OnPlay;
// 声明私有 Action
private Action OnGameOver;
2. 带参数 Action(最常用)
cs
// 1个参数:int 类型
public Action<int> OnScoreChange;
// 2个参数:string + bool
public Action<string, bool> OnUIMessage;
// 3个参数(以此类推)
public Action<int, float, string> OnSkillCast;
3. 静态 Action(全局事件,跨脚本调用)
cs
// 全局广播:玩家受伤
public static Action<float> OnPlayerHurt;
4.只读 / 只能外部订阅、内部调用
cs
// 外部只能 += 注册,不能直接 = 赋值,更安全
public Action OnDie { get; private set; }
三、Action 完整使用示例(Unity 可直接运行)
示例 1:无参数 Action(按钮点击 / 技能释放)
cs
using UnityEngine;
using System;
public class Player : MonoBehaviour
{
// 1. 声明 Action
public Action OnJump;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
// 2. 调用 Action(触发所有注册的方法)
OnJump?.Invoke();
}
}
}
另一个脚本订阅:
cs
public class UIManager : MonoBehaviour
{
void Start()
{
// 注册方法到 Action
FindObjectOfType<Player>().OnJump += ShowJumpEffect;
}
void ShowJumpEffect()
{
Debug.Log("播放跳跃特效!");
}
}
示例 2:带参数 Action(扣血、得分)
cs
public class Enemy : MonoBehaviour
{
// 声明带 int 参数的 Action
public Action<int> OnTakeDamage;
void Hit()
{
// 调用并传参
OnTakeDamage?.Invoke(50);
}
}
订阅:
cs
// 接收参数
enemy.OnTakeDamage += (damage) =>
{
Debug.Log("受到伤害:" + damage);
};
四、关键语法说明
1. ?.Invoke() 必须加!
cs
// 安全调用:如果 Action 为空(没注册方法),不会报错
OnJump?.Invoke();
不加 ?. 会报 空引用异常 ,Unity 中必须写。
2. 注册与注销
cs
// 注册
OnJump += MyMethod;
// 注销(重要!避免内存泄漏)
OnJump -= MyMethod;
五、Action 与 普通委托 的区别
你也可以自己声明委托,效果一样:
cs
// 自定义委托(等价于 Action)
public delegate void MyDelegate();
public MyDelegate OnEvent;
六、Action 适用场景(Unity 高频使用)
- UI 按钮点击回调
- 玩家受伤、死亡、升级事件
- 任务完成、道具拾取通知
- 技能释放、冷却完成
- 全局消息广播(跨脚本通信)
- 异步加载完成回调