Unity 消息队列

参考链接

http://www.voidcn.com/article/p-wgsrxllo-btn.html

https://www.cnblogs.com/cyjb/archive/2013/03/21/DelegateBuilder.html

 

这个队列做了什么

队列初始化时会把非继承自MonoBehaviour的自动注册到消息事件

自动把类的所有不同参数的OnHandle注册到事件字典

对模块间的消息进行解耦,和消息中心是一样的

继承自MonoBehaviour的怎么办

继承自MonoBehaviour的函数,自己在Awake注册消息事件

测试实例

using UnityEngine;

public class Test : MonoBehaviour
{
    private void Awake()
    {
        MsgEventManager.AddEvent(this);
    }
    private void Start()
    {
        Msg.Send();//发送消息
        Msg.Send(6);
    }
    public void OnHandle(int x)
	{
		Debug.Log(x);
	}
    void OnHandle()
    {
        Debug.Log("Test");
    }
}

public class Test2
{
	 void OnHandle()
	 {
		 Debug.Log("miao");
	 }
}

效果

Unity 消息队列_第1张图片

 

具体实现

using System.Collections.Generic;
using System.Text;

public class Msg : MonoSingle {

	bool isSendComplete= true;
	static StringBuilder stringBuilder = new StringBuilder();
	Queue queue = new Queue();

    public static void Send()
    {
        Inst.queue.Enqueue(new Data { key = string.Empty, parameter = null });
    }

    public static void Send(T arg)
    {
		Inst.queue.Enqueue(new Data{key= arg.GetType().Name, parameter= new object[1] { arg } });
    }
    public static void Send(T arg, T1 arg1)
    {   
        object[] parameter = new object[2];
        parameter[0] = arg;
        parameter[1] = arg1;

        stringBuilder.Append(arg.GetType().Name);
        stringBuilder.Append(arg1.GetType().Name);

		Inst.queue.Enqueue(new Data{key=stringBuilder.ToString(),parameter=parameter});
        stringBuilder.Length=0;
    }
    public static void Send(T arg,T1 arg1,T2 arg2)
    {
        object[] parameter = new object[3];
        parameter[0] = arg;
        parameter[1] = arg1;
        parameter[2] = arg2;

        stringBuilder.Append(arg.GetType().Name);
        stringBuilder.Append(arg1.GetType().Name);
        stringBuilder.Append(arg2.GetType().Name);
        
		Inst.queue.Enqueue(new Data{key=stringBuilder.ToString(),parameter=parameter});
        stringBuilder.Length=0;
    }
    public static void Send(T arg,T1 arg1,T2 arg2,T3 arg3)
    {
        object[] parameter = new object[4];
        parameter[0] = arg;
        parameter[1] = arg1;
        parameter[2] = arg2;
        parameter[3] = arg3;

        stringBuilder.Append(arg.GetType().Name);
        stringBuilder.Append(arg1.GetType().Name);
        stringBuilder.Append(arg2.GetType().Name);
        stringBuilder.Append(arg3.GetType().Name);
        
		Inst.queue.Enqueue(new Data{key=stringBuilder.ToString(),parameter=parameter});
        stringBuilder.Length=0;
    }
    public static void Send(T arg,T1 arg1,T2 arg2,T3 arg3,T4 arg4)
    {
        object[] parameter = new object[5];
        parameter[0] = arg;
        parameter[1] = arg1;
        parameter[2] = arg2;
        parameter[3] = arg3;
        parameter[4] = arg4;

        stringBuilder.Append(arg.GetType().Name);
        stringBuilder.Append(arg1.GetType().Name);
        stringBuilder.Append(arg2.GetType().Name);
        stringBuilder.Append(arg3.GetType().Name);
        stringBuilder.Append(arg4.GetType().Name);
        
		Inst.queue.Enqueue(new Data{key=stringBuilder.ToString(),parameter=parameter});
        stringBuilder.Length=0;
    }

    void Update () 
	{
		if(queue.Count>0 && isSendComplete)
		{
			isSendComplete = false;
			var data = queue.Dequeue();
			MsgEventManager.Inst.Invoke(data.key,data.parameter);
			isSendComplete = true;
		}
	}

	struct Data
	{
		public string key;
		public object [] parameter;
	}
}
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using UnityEngine;

public class MsgEventManager:Single
{
	static readonly string handleStr="OnHandle";
    static Type monoBehaviour = typeof(MonoBehaviour);
	Dictionary dic = new Dictionary();
    StringBuilder stringBuilder = new StringBuilder();

    public MsgEventManager()
    {
        var assembly = Assembly.GetAssembly(typeof(MsgEventManager));
        foreach(var type in assembly.GetTypes())
        {
            if (IsSubclassOfMonoBehaviour(type) || type.IsInterface)
                continue;
            var  methods = type.GetMethods(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
            foreach (var method in methods)
            {
                if (method.Name == handleStr)
                {
                    var key = GetKey(method);
                    var instance = Activator.CreateInstance(type);
                    AddMethod(key, instance, method);
                }
            }
        }
    }

    public static void AddEvent(object obj)
    {
        var type = obj.GetType();
        var  methods = type.GetMethods(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
        foreach(var method in  methods)
        {
            if(method.Name == handleStr)
            {
                var key = Inst.GetKey(method);
                Inst.AddMethod(key, obj, method);
            }
        }
	}

    public void Invoke(string key, object[]parameter)
    {
        if (!dic.ContainsKey(key))
            return;

        dic[key].DynamicInvoke(parameter);
    }
    
    void AddMethod(string key, object obj, MethodInfo method)
    {
        var tmp = CreateDelegate(obj, method);
        if (!dic.ContainsKey(key))
        {
            dic.Add(key, tmp);
        }
        else
        {
            dic[key] = Delegate.Combine(dic[key], tmp);
        }
    }

    bool IsSubclassOfMonoBehaviour(Type type)
    {
        while (type != null)
        {
            if (type == monoBehaviour)
            {
                return true;
            }
            type = type.BaseType;
        }
        return false;
    }

    string GetKey(MethodInfo value)
    {
        foreach(var parameter in value.GetParameters())
        {
            stringBuilder.Append(parameter.ParameterType.Name);
        }
        string result = stringBuilder.ToString();
        stringBuilder.Length=0;
        return result;
    }

    private Delegate CreateDelegate(object instance, MethodInfo method)
    {
        var parametersInfo = method.GetParameters();
        Expression[] expArgs = new Expression[parametersInfo.Length];
        List lstParamExpressions = new List();
        for (int i = 0; i < expArgs.Length; i++)
        {
            expArgs[i] = Expression.Parameter(parametersInfo[i].ParameterType, parametersInfo[i].Name);
            lstParamExpressions.Add((ParameterExpression)expArgs[i]);
        }

        MethodCallExpression callExpression = Expression.Call(Expression.Constant(instance), method, expArgs);
        LambdaExpression lambdaExpression = Expression.Lambda(callExpression, lstParamExpressions.ToArray());

        return lambdaExpression.Compile();
    }
}

 

你可能感兴趣的:(unity3d)