文章目录
-
-
- 实例1:委托(Delegate)的基本用法
- 实例2:事件(Event)的声明与订阅
- [实例3:Unity引擎中的委托实例 - UI Button.onClick](#实例3:Unity引擎中的委托实例 - UI Button.onClick)
- 实例4:事件(Event)的安全性
- [实例5:事件处理器链(Multicast Delegate)](#实例5:事件处理器链(Multicast Delegate))
-
在Unity中,C#的事件处理与委托密切相关。下面通过5个实例来详细阐述它们的区别和使用场景:
实例1:委托(Delegate)的基本用法
csharp
public delegate void MyAction(string message);
public class MyClass
{
private MyAction _myAction;
public MyClass(MyAction action)
{
_myAction = action;
}
public void TriggerAction()
{
if (_myAction != null)
_myAction("触发了一个动作!");
}
}
public class MainScript : MonoBehaviour
{
void Start()
{
MyClass myClass = new MyClass(OnActionTriggered);
}
void OnActionTriggered(string message)
{
Debug.Log(message);
}
}
在这个例子中,MyAction
是一个自定义的委托类型,它引用了一个无返回值并接受字符串参数的方法。当 MyClass
中的 TriggerAction
方法被调用时,会执行传递给构造函数的委托方法 OnActionTriggered
。
实例2:事件(Event)的声明与订阅
csharp
public class EventExample : MonoBehaviour
{
// 声明一个基于委托类型的事件
public event Action<string> OnMessageReceived;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
// 触发事件
OnMessageReceived?.Invoke("接收到一个消息!");
}
}
void OnEnable()
{
// 订阅事件
OnMessageReceived += HandleMessage;
}
void OnDisable()
{
// 取消订阅事件
OnMessageReceived -= HandleMessage;
}
void HandleMessage(string message)
{
Debug.Log(message);
}
}
在此例中,我们定义了一个名为 OnMessageReceived
的事件,它是基于 Action<string>
委托的。通过 +=
和 -=
运算符可以添加或移除事件的监听器(即响应事件的方法)。当按下空格键时,事件会被触发,并通知所有已订阅的监听器。
实例3:Unity引擎中的委托实例 - UI Button.onClick
csharp
public class UIExample : MonoBehaviour
{
public Button myButton;
void Start()
{
// 将方法赋值给按钮点击事件的委托
myButton.onClick.AddListener(ButtonClicked);
}
void ButtonClicked()
{
Debug.Log("按钮被点击了!");
}
void OnDestroy()
{
// 清理事件监听器以防止内存泄漏
myButton.onClick.RemoveAllListeners();
}
}
这个实例展示了Unity引擎内置的UI组件Button中对委托的实际应用。onClick
是一个预定义的 UnityEvent,它背后也是基于委托机制实现的。这里我们为按钮点击事件添加了一个监听器方法 ButtonClicked
。
实例4:事件(Event)的安全性
csharp
public class SafeEventExample
{
// 私有存储事件的委托实例
private event EventHandler<MyEventArgs> SafeEvent;
public void RaiseSafeEvent(string data)
{
SafeEvent?.Invoke(this, new MyEventArgs(data));
}
public void Subscribe(EventHandler<MyEventArgs> handler)
{
SafeEvent += handler;
}
public void Unsubscribe(EventHandler<MyEventArgs> handler)
{
SafeEvent -= handler;
}
public class MyEventArgs : EventArgs
{
public readonly string Data;
public MyEventArgs(string data)
{
Data = data;
}
}
}
此例强调了事件相对于直接操作委托的安全性。事件通常在类内部作为一个私有字段进行封装,并提供公共的 +=
和 -=
方法来管理订阅者。这样可以防止外部代码随意修改或触发事件。
实例5:事件处理器链(Multicast Delegate)
csharp
public class MulticastDelegateExample
{
public delegate void MessageHandler(string message);
public event MessageHandler OnMessage;
void Awake()
{
OnMessage += PrintToConsole;
OnMessage += SendEmail;
// 触发事件,多个监听器将依次执行
OnMessage("多重委托示例");
}
void PrintToConsole(string message)
{
Debug.Log("打印到控制台:" + message);
}
void SendEmail(string message)
{
Debug.Log("模拟发送邮件:" + message);
}
}
在这个实例中,单个事件可以关联多个不同的方法,这就是多播委托的概念。当事件触发时,所有的注册方法(如 PrintToConsole
和 SendEmail
)都会按顺序执行。这是事件功能的一个重要特性,允许单一事件触发多个相关的行为。
总结:
- 委托是类型安全的函数指针,用于表示可重用的方法签名。
- 事件是一种设计模式,它基于委托机制,提供了发布/订阅模型,确保了安全性(不可直接调用或修改),且支持多播(多个方法可以同时响应同一个事件)。
- 在Unity中,事件通常用于游戏对象间的通信,例如用户输入、状态变化或其他特定游戏逻辑的通知。
python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)
最后我们放松一下眼睛