unity 事件(委托)

头段时间做NGUI的时候,老大给我优化了很多,用到了C#的事件。由于我之前不是学C#的,下来花了点时间看了一下事件。我老大主要把事件用于对UI界面的切换。下面我们来看看代码吧。我的例子很简单的。

 

EventManager.cs  

using System;
using System.Collections.Generic;
 
public class EventArgs
{
 
}
 
public class EventManager
{
    static EventManager _instance;
    public static EventManager Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new EventManager();
            }
 
            return _instance;
        }
    }
 
    public delegate void EventDelegate<T>(T e) where T : EventArgs;
 
    readonly Dictionary<Type, Delegate> _delegates = new Dictionary<Type, Delegate>();
 
    public void AddListener<T>(EventDelegate<T> listener) where T : EventArgs
    {
        Delegate d;
        if (_delegates.TryGetValue(typeof(T), out d))
        {
            _delegates[typeof(T)] = Delegate.Combine(d, listener);
        }
        else
        {
            _delegates[typeof(T)] = listener;
        }
    }
 
    public void RemoveListener<T>(EventDelegate<T> listener) where T : EventArgs
    {
        Delegate d;
        if (_delegates.TryGetValue(typeof(T), out d))
        {
            Delegate currentDel = Delegate.Remove(d, listener);
 
            if (currentDel == null)
            {
                _delegates.Remove(typeof(T));
            }
            else
            {
                _delegates[typeof(T)] = currentDel;
            }
        }
    }
 
    public void Raise<T>(T e) where T : EventArgs
    {
        if (e == null)
        {
            throw new ArgumentNullException("e");
        }
 
        Delegate d;
        if (_delegates.TryGetValue(typeof(T), out d))
        {
            EventDelegate<T> callback = d as EventDelegate<T>;
            if (callback != null)
            {
                callback(e);
            }
        }
    }
}


 

 

EventArgs.cs

 

using UnityEngine;
using System.Collections;

public class UIEventArgs : EventArgs {
	
	private bool _isOpen;
	public bool IsOpen
	{
		get
		{
			return _isOpen;
		}
		set
		{
			_isOpen = value;
		}
	}
}


 

 

EventListener.cs(绑定在一个物体上)

 

using UnityEngine;
using System.Collections;

public class EventListener : MonoBehaviour {

	// Use this for initialization
	void Start () {
	   EventManager.Instance.AddListener<UIEventArgs>(OnReceive);
	}
	void OnReceive(UIEventArgs e)
	{
		if(e.IsOpen)
		{
			print ("Name:"+gameObject.name);
		}
	}
	
}


 

 

SendEventMeg.cs  (绑定在一个物体上)

using UnityEngine;
using System.Collections;

public class SendEventMeg : MonoBehaviour {

	// Use this for initialization
	void Start () {
	   
	}
	
	void Send ()
	{
		var arg = new UIEventArgs()
		{
	        IsOpen = true,
		};
		EventManager.Instance.Raise(arg);
	}
	void OnGUI()
	{
		if(GUILayout.Button("Send"))
		{
			Send();
		}
	}
}


 

 

结果:打印出“Name:xxxxx”.

 

 

 

 

 

 

 

Unity 中,委托Delegate)和事件(Event)是实现对象间通信的重要机制,尤其适用于模块化设计、解耦逻辑以及提升代码的可维护性和可扩展性。通过委托事件,可以实现多个对象对某一行为的订阅和响应,而无需直接耦合彼此的逻辑。 ### 委托的基本定义与使用 在 C# 中,委托是一种类型安全的函数指针,可以用来封装方法的引用。定义一个委托使用 `delegate` 关键字,例如: ```csharp public delegate void MyDelegate(); ``` 该委托可以指向任何没有参数且返回值为 `void` 的方法。使用委托时,可以通过 `+=` 和 `-=` 操作符来添加或移除方法。 ### 事件的声明与触发 事件基于委托,通常用于实现观察者模式。在 Unity 中,事件通常被声明为静态事件,以便于在不同对象之间共享[^2]。例如: ```csharp public static event MyDelegate OnMyEvent; ``` 在某个特定条件下,比如按键触发时,调用事件: ```csharp private void Update() { if (Input.GetButtonDown("Defend")) { OnMyEvent?.Invoke(); } } ``` ### 订阅与取消订阅事件 订阅事件通常在 `Start` 或 `Awake` 方法中进行,而取消订阅则在 `OnDisable` 或 ` OnDestroy` 中完成,以避免内存泄漏或空引用异常[^2]。 ```csharp private void Start() { MyEventPublisher.OnMyEvent += MyEventHandler; } private void OnDisable() { MyEventPublisher.OnMyEvent -= MyEventHandler; } void MyEventHandler() { Debug.Log("触发委托事件"); } ``` ### 自定义事件参数 在某些情况下,事件需要传递额外的信息。可以通过自定义事件参数类来实现。例如,定义一个事件参数类: ```csharp public class PlayerAniEventArgs : EventArgs { public string AnimationName { get; set; } } ``` 然后定义一个带有自定义参数的委托事件: ```csharp public delegate void AniChangeHandle(object sender, PlayerAniEventArgs e); public event AniChangeHandle CustomMoveComplete; ``` 在触发事件时传递参数: ```csharp PlayerAniEventArgs args = new PlayerAniEventArgs { AnimationName = "Run" }; CustomMoveComplete?.Invoke(this, args); ``` ### 示例:完整委托事件实现 以下是一个完整的 Unity 委托事件实现示例: ```csharp using UnityEngine; // 定义一个委托 public delegate void MyDelegate(); public class MyEventPublisher : MonoBehaviour { // 定义一个静态事件 public static event MyDelegate OnMyEvent; private void Update() { // 检测是否按下防御键——C if (Input.GetKeyDown(KeyCode.C)) { // 如果事件不为空(有订阅者),调用所有订阅此事件的方法。 OnMyEvent?.Invoke(); } } } public class MyEventSubscriber : MonoBehaviour { private void Start() { // 订阅事件 MyEventPublisher.OnMyEvent += HandleMyEvent; } private void OnDisable() { // 取消订阅事件 MyEventPublisher.OnMyEvent -= HandleMyEvent; } private void HandleMyEvent() { Debug.Log("事件被触发"); } } ``` ### 委托事件的优势 使用委托事件可以有效降低模块之间的耦合度,使得代码更易于维护和扩展。例如,在 UI 按钮点击事件中,使用事件机制可以让多个对象响应同一事件,而不必修改按钮本身的逻辑[^3]。此外,事件机制还能够避免因直接调用方法而可能导致的死循环和逻辑混乱问题[^5]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值