游戏框架通用模块之一消息机制

使用方式:

注册消息: 在需要的位置注册一个带string参数的接收消息函数

CoreRoot.eventMgr.AddListener<string>("gmCommand", OnGmCommand);

发送消息:

CoreRoot.eventMgr.TriggerEvent<string>("gmCommand", inputField.text);

 

消息机制核心代码:

//支持的功能包括,事件的优先级排序,是否在切换场景时移除,每个委托可能绑定多个事件
public class EventMgr : MonoBehaviour

{

    //定义优先级

public enum EventPriority
    {
        Highest        = 10,
        High        = 100,
        AboveMedium = 150,
        Medium        = 200,            // 默认优先级
        BelowMedium = 250,
        Low            = 300,
        Lowest        = 400,
    }

//支持从0到3个参数的委托,

    public delegate void EventFunction(string ge);
    public delegate void EventFunction<U>(string ge, U arg1);
    public delegate void EventFunction<U, V>(string ge, U arg1, V arg2);
    public delegate void EventFunction<U, V, W>(string ge, U arg1, V arg2, W arg3);

    //定义事件类
    public class EventNode
	{
		public EventNode(Delegate function, bool removeOnLoadScene, EventPriority priority)
		{
			this.function = function;
			this.removeOnLoadScene = removeOnLoadScene;
			this.priority = priority;
		}
		
		public Delegate function;
		public bool removeOnLoadScene;
		public EventPriority priority;
	}

    //按优先级排序
    public class EventNodeCompare : IComparer<EventNode>
	{
		public int Compare(EventNode x, EventNode y)
		{
			if (x == null)
			{
				if (y == null)
					return 0;
				else
					return -1;
			}
			else
			{
				if (y == null)
					return 1;
				else
					return ((int)x.priority) - ((int)y.priority);
			}
		}
	}

    public class MapNode
	{
		public bool dirty = false;
		public List<EventNode> nodeList = new List<EventNode>();
	}

    void Awake ()
	{
		eventMap = new Dictionary<string, MapNode>();
	}

    // removeOnLoadScene决定此监听注册是否在加载场景时自动移除,大部分监听都应该选择自动移除,这是防止内存泄漏的保障机制
	public void AddListener(string ge, EventFunction ef, bool removeOnLoadScene = true, EventPriority priority = EventPriority.Medium)
	{
		AddListenerInternal(ge, ef, removeOnLoadScene, priority);
	}
	
	public void AddListener<U>(string gameEvent, EventFunction<U> ef, bool removeOnLoadScene = true, EventPriority priority = EventPriority.Medium)
	{
		AddListenerInternal(gameEvent, ef, removeOnLoadScene, priority);
	}
	
	public void AddListener<U, V>(string gameEvent, EventFunction<U, V> ef, bool removeOnLoadScene = true, EventPriority priority = EventPriority.Medium)
	{
		AddListenerInternal(gameEvent, ef, removeOnLoadScene, priority);
	}
	
	public void AddListener<U, V, W>(string gameEvent, EventFunction<U, V, W> ef, bool removeOnLoadScene = true, EventPriority priority = EventPriority.Medium)
	{
		AddListenerInternal(gameEvent, ef, removeOnLoadScene, priority);
	}
	
	private void AddListenerInternal(string ge, Delegate ef, bool removeOnLoadScene, EventPriority priority)
	{
		// 如果event为空,那么返回
		if (ge == null || ge.Length == 0) 
		{
			Debug.LogWarning("EventMgr" + "EventName Error");
			return;
		}
		
		// 如果第一次注册此类事件,需要创建对应链表
		MapNode mapNode;
		if( !eventMap.TryGetValue(ge, out mapNode) )
		{
			mapNode = new MapNode();
			eventMap[ge] = mapNode;
		}
		
		// 如果重复注册则返回
		//foreach( EventNode node in nodeList )
		bool shouldSort = false;
		for (int i=0; i<mapNode.nodeList.Count; ++i)
		{
			var node = mapNode.nodeList[i];
			
			if( node.priority != EventPriority.Medium )
				shouldSort = true;
			
			if( node.function.Equals(ef) )
				return;
		}
		
		if( priority != EventPriority.Medium )
			shouldSort = true;
		
		mapNode.nodeList.Add( new EventNode(ef, removeOnLoadScene, priority) );
		if( mapNode.nodeList.Count > 1 && shouldSort )
			mapNode.dirty = true;
    }
    
	
	public void RemoveListener(string ge, EventFunction ef)
	{
		RemoveListenerInternal(ge, ef);
	}
	
	public void RemoveListener<U>(string ge, EventFunction<U> ef)
	{
		RemoveListenerInternal(ge, ef);
	}
	
	public void RemoveListener<U, V>(string ge, EventFunction<U, V> ef)
	{
		RemoveListenerInternal(ge, ef);
	}
	
	public void RemoveListener<U, V, W>(string ge, EventFunction<U, V, W> ef)
	{
		RemoveListenerInternal(ge, ef);
	}
	
	public void RemoveListenerInternal(string ge, Delegate ef)
	{
		MapNode mapNode;
		if( !eventMap.TryGetValue(ge, out mapNode) )
			return;
		
		int nCount = 0;
		foreach( EventNode node in mapNode.nodeList )
		{
			if( node.function.Equals(ef) )
			{	
				mapNode.nodeList.RemoveAt(nCount);
				return;
			}
			
			nCount++;
		}
	}
	
	EventNode[] PrepareNodeList(string ge)
	{
		if (ge == null || ge.Length == 0)
		{
			//CoreEntry.logMgr.Log(LogLevel.WARNING, "EventMgr", "trigger null event");
			return null;
		}
		
		MapNode mapNode;
		if( !eventMap.TryGetValue(ge, out mapNode) )
			return null;
		
		if( mapNode.dirty )
		{
			mapNode.nodeList.Sort(eventNodeCompare);
			mapNode.dirty = false;
		}
		
		// 将事件响应队列复制一个副本
		EventNode[] tpList = new EventNode[ mapNode.nodeList.Count ];
		mapNode.nodeList.CopyTo(tpList);
		return tpList;
	}
	
	public void TriggerEvent(string ge)
	{
		EventNode[] tpList = PrepareNodeList(ge);
		if( tpList == null )
			return;
		
		foreach( EventNode node in tpList )
		{
			EventFunction ef = node.function as EventFunction;
			if( ef != null )
				ef(ge);
			else
				Debug.LogError(string.Format("处理事件 \"{0}\" 时回调函数参数不匹配", ge) );
		}
	}
	
	public void TriggerEvent<U>(string ge, U arg1)
	{
		EventNode[] tpList = PrepareNodeList(ge);
		if( tpList == null )
			return;
		
		foreach( EventNode node in tpList )
		{
			EventFunction<U> ef = node.function as EventFunction<U>;
			if( ef != null )
				ef(ge, arg1);
			else
				Debug.LogError(string.Format("处理事件 \"{0}\" 时回调函数参数不匹配", ge) );
		}
	}
	
	public void TriggerEvent<U, V>(string ge, U arg1, V arg2)
	{
		EventNode[] tpList = PrepareNodeList(ge);
		if( tpList == null )
			return;
		
		foreach( EventNode node in tpList )
		{
			EventFunction<U, V> ef = node.function as EventFunction<U, V>;
			if( ef != null )
				ef(ge, arg1, arg2);
			else
				Debug.LogError(string.Format("处理事件 \"{0}\" 时回调函数参数不匹配", ge) );
		}
	}
	
	public void TriggerEvent<U, V, W>(string ge, U arg1, V arg2, W arg3)
	{
		EventNode[] tpList = PrepareNodeList(ge);
		if( tpList == null )
			return;
		
		foreach( EventNode node in tpList )
		{
			EventFunction<U, V, W> ef = node.function as EventFunction<U, V, W>;
			if( ef != null )
				ef(ge, arg1, arg2, arg3);
			else
				Debug.LogError(string.Format("处理事件 \"{0}\" 时回调函数参数不匹配", ge) );
		}
	}
	
	// 切换场景时移除removeOnLoadScene标志为true的监听对象
	public void OnLoadSceneRecycle()
	{
		foreach( MapNode mapNode in eventMap.Values )
		{
			for( int i=0; i<mapNode.nodeList.Count; )
			{
				if( mapNode.nodeList[i].removeOnLoadScene )
					mapNode.nodeList.RemoveAt(i);
				else
					++i;
			}
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张乂卓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值