分享一个消息发送及接收的框架,改编至一个叫EventManager的消息管理类(https://unity3d.com/cn/learn/tutorials/topics/scripting/events-creating-simple-messaging-system),之前在寻找消息管理框架的时候发现了这个类,感觉挺好用,逻辑也很清晰。但随着需求的增加,发现它也有些许的局限性,不能传参,只能触发事件,于是自己在上面做了些扩展。它的核心思想是通过字典来管理方法及方法触发的条件,
private Dictionary <string, UnityEvent> eventDictionary;
string表示存入的消息名,unityEvent存入的消息名所对应的事件,unityEvent本身是一个不带参的委托,因此导致我们调用的时候不能传参。于是我把unityEvent换成了Action,这样就可以存带参的方法了,如Action<int>,Action<string>等等。但问题又来了,一个项目肯定要传多种参数,我到底是要用Action<int>,还是要用Action<string>,还是都要呢,多种参数怎么传呢?用列表保存!于是我选用了ArrayList,没有使用List,因为List需指定泛型,这样限制了我们传参的种类。
private Dictionary <string, Action<ArrayList>> eventDictionary;
因为项目赶时间,没来得及细化,若有不足之处,欢迎指证,下面给出代码:
消息管理类(挂在场景中任意物体上)
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MSGCenter : MonoBehaviour {
private Dictionary<string, Action<ArrayList>> eventDictionary;
private static MSGCenter eventManager;
//单例
public static MSGCenter instance
{
get
{
if (!eventManager)
{
//在Unity的Hierarchy中必须有一个名为EventManager的空物体,并挂上EventManager脚本
eventManager = FindObjectOfType(typeof(MSGCenter)) as MSGCenter;
if (!eventManager)
{
Debug.LogError("There needs to be one active EventManger script on a GameObject in your scene.");
}
else
{
eventManager.Init();
}
}
return eventManager;
}
}
public void Init()
{
if (eventDictionary == null)
{
eventDictionary = new Dictionary<string, Action<ArrayList>>();
}
}
//在需要监听某个事件的脚本中,调用这个方法来监听这个事件
public static void StartListening(string eventName, Action<ArrayList> action)
{
if (instance.eventDictionary.ContainsKey(eventName))
{
instance.eventDictionary[eventName]=action;
}
else
{
instance.eventDictionary.Add(eventName, action);
}
}
//在不需要监听的时候停止监听
public static void StopListening(string eventName)
{
if (instance.eventDictionary.ContainsKey(eventName))
{
instance.eventDictionary.Remove(eventName);
}
}
//触发某个事件
public static void TriggerEvent(string eventName, ArrayList obj)
{
if (instance.eventDictionary.ContainsKey(eventName))
{
instance.eventDictionary[eventName].Invoke(obj);
}
}
}
消息接受类(需注册消息,指定消息的接受方法)
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class EventManagerTest : MonoBehaviour
{
void OnEnable()
{
Action<ArrayList> action=new Action<ArrayList>(MoveCube);
MSGCenter.StartListening ("hello", action);
}
void OnDisable()
{
MSGCenter.StopListening ("hello");
}
private void MoveCube(ArrayList obj)
{
print("触发了消息"+obj[0]+obj[1]);
}
}
消息触发类(指定触发的消息)这里传入了一个int型 一个string型
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BtnEventHandle : MonoBehaviour {
// Use this for initialization
void Start () {
}
private void Update()
{
if (Input.GetKeyUp(KeyCode.S))
{
MSGCenter.TriggerEvent("hello",new ArrayList {1,"str" });
}
}
}