Unity学了有大半年了,懵懵懂懂,不断试错。自学的难点就是会碰到很多弯路,不知道下一步该怎么学。最近买了一本Unity实战技术的书,书中的知识我感觉都是挺实用,相对于大多数只是教教基础的教程来说。
当Unity工程中模块越多,为了解耦,模块之间的消息传递肯定少不了,下面是一个简单的消息事件的封装。上代码!
事件的基类:
using UnityEngine;
using System.Collections;
public enum CEventType
{
GAME_OVER,
GAME_WIN,
PAUSE,
ENERGY_EMEPTY,
GAME_DATA,
}
public class CBaseEvent
{
protected Hashtable arguments;
protected CEventType type;
protected object sender;
/// <summary>
/// Type属性
/// </summary>
public CEventType Type
{
get { return this.type; }
set { this.type = value; }
}
public IDictionary Params//属性
{
get { return this.arguments; }
set { this.arguments = (value as Hashtable); }
}
public object Sender//属性
{
get { return this.sender; }
set { this.sender = value; }
}
public override string ToString()//重写ToString
{
return this.type + "[" + ((this.sender == null) ? "null" : this.sender.ToString()) + "]";
}
/// <summary>
/// 克隆基类的方法
/// </summary>
/// <returns></returns>
public CBaseEvent Clone()
{
return new CBaseEvent(this.type, this.arguments, Sender);
}
/// <summary>
/// 三个参数的构造函数
/// </summary>
/// <param name="type">类型</param>
/// <param name="args"></param>
/// <param name="sender"></param>
public CBaseEvent(CEventType type, Hashtable args, object sender)
{
this.Type = type;
this.arguments = args;
this.Sender = sender;
if (this.arguments==null)
{
this.arguments = new Hashtable();
}
}
/// <summary>
/// 两个参数的构造函数
/// </summary>
/// <param name="type"></param>
/// <param name="sender"></param>
public CBaseEvent(CEventType type, object sender)
{
this.Type = type;
Sender = sender;
if (this.arguments==null)
{
this.arguments = new Hashtable();
}
}
}
这个是事件派发类,包含消息注册、消息移除和消息派发的方法
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public delegate void CEventListenerDelegate(CBaseEvent evt);
public class CEventDispatcher {
//做成单例模式
static CEventDispatcher instance;
public static CEventDispatcher GetInstance()
{
if (instance==null)
{
instance = new CEventDispatcher();
}
return instance;
}
//创建一个哈希表用于存放添加的监听
private Hashtable listeners = new Hashtable();
/// <summary>
/// 添加监听
/// </summary>
/// <param name="eventType">事件类型</param>
/// <param name="listener">监听(委托类型)</param>
public void AddEventListener(CEventType eventType, CEventListenerDelegate listener)
{
//添加监听
listeners.Add(eventType, listener);
/*
//直接将事件类型赋值给表,然后得到他的值
CEventListenerDelegate ceventListenerDelegate = this.listeners[eventType] as CEventListenerDelegate;
//把监听添加到委托当中
ceventListenerDelegate = (CEventListenerDelegate)Delegate.Combine(ceventListenerDelegate, listener);
//事件(委托)重新赋值给键为eventType的监听
this.listeners[eventType] = ceventListenerDelegate;
*/
}
/// <summary>
/// 移除监听
/// </summary>
/// <param name="eventType"></param>
/// <param name="listener"></param>
public void RemoveEventListener(CEventType eventType, CEventListenerDelegate listener)
{
/*
CEventListenerDelegate ceventListenerDelegate = this.listeners[eventType] as CEventListenerDelegate;
if (ceventListenerDelegate!=null)
{
//如果事件(委托存在),则将里面的监听移除
ceventListenerDelegate = (CEventListenerDelegate)Delegate.Remove(ceventListenerDelegate, listener);
}
this.listeners[eventType] = ceventListenerDelegate;
*/
//移除监听
listeners.Remove(eventType);
}
/// <summary>
/// 分发事件消息
/// </summary>
/// <param name="evt">事件类型</param>
public void DispatchEvent(CBaseEvent evt)
{
//从哈希表里得到事件监听
CEventListenerDelegate ceventListenerDelegate = this.listeners[evt.Type] as CEventListenerDelegate;
if (ceventListenerDelegate!=null)
{
try
{
//如果事件监听不为null,则将参数:事件类型 赋值给委托,由此触发事件函数
ceventListenerDelegate(evt);
}
catch
{
}
}
}
public void RemoveAll()
{
this.listeners.Clear();
}
}
在AddEventListener方法和RemoveEventListener方法中,注释的那一段是书本中原文的写法,个人不太理解是什么意思(如果有知道的大神恳请给予指点)。而且用原文写法后,测试不成功。于是乎用添加列表的方法代替了原来一大串代码,结果测试成功。
这个是我自己写的测试类
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Sender : MonoBehaviour {
// Use this for initialization
void Start()
{
//注册消息
CEventDispatcher.GetInstance().AddEventListener(CEventType.GAME_WIN, GameWin);
//传入事件类型和object类型的Sender,如果事件类型匹配消息列表里的值,则触发事件函数
CEventDispatcher.GetInstance().DispatchEvent(new CBaseEvent(CEventType.GAME_WIN, "sender"));
}
/// <summary>
/// 用于测试的事件函数
/// </summary>
/// <param name="evt"></param>
private void GameWin(CBaseEvent evt)
{
Debug.Log("Game Win!");
}
}
初步理解了消息事件的封装,若想灵活运用,还是要在项目中多写多试。