Unity C# 游戏开发 事件 消息派发器(图文详细,带源码)

Posted 水光涵月

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity C# 游戏开发 事件 消息派发器(图文详细,带源码)相关的知识,希望对你有一定的参考价值。


事情是这样的

可可爱爱的程序媛小姐姐又来找我玩啦,本来是开心的聊天却变成了技术研讨会,小姐姐说最近敲代码,各种事件委托,各种观察者模式,手都敲麻了,问我有好办法没有

那我可以帮你揉一下?(显然不符合我钢铁直男的人设),那就写个消息派发器来帮助小姐姐吧!


一、消息派发器的几个功能

既然是要来简化观察者模式,那功能肯定一个都不能少

1.添加事件注册

需要2个参数,第一个是索引,第二个是事件

/// <summary>
    /// 添加事件注册
    /// </summary>
    /// <param name="evt">索引</param>
    /// <param name="listener"></param>
    private void AddDelegate(int evt, Delegate listener)
    {
        Delegate value;
        if (!listeners.TryGetValue(evt, out value))
        {
            //key不存在就添加
            listeners.Add(evt, listener);
        }
        else
        {
            //key存在判断value是否为空,为空就替换,不为空就多播
            value = (value != null) ? Delegate.Combine(value, listener) : listener;
            listeners[evt] = value;
        }
    }

2.事件的触发

事件的触发需要传入一个 索引

/// <summary>
    /// 事件触发
    /// </summary>
    /// <param name="evt"></param>
    public void DispatchEvent(int evt)
    {
        Delegate func;

        try
        {
            if (listeners.TryGetValue(evt, out func) && func != null)
            {
                var act = (Act)func;
                act();
            }
        }
        catch (Exception e)
        {
            UnityEngine.Debug.LogError(e.Message);
            UnityEngine.Debug.LogError(e.StackTrace);
        }
    }

3.移除事件

事件移除和注册需要的参数是一样的

/// <summary>
    /// 移除事件
    /// </summary>
    /// <param name="evt"></param>
    /// <param name="listener"></param>
    private void RemoveDelegate(int evt, Delegate listener)
    {
        Delegate func;
        if (listeners.TryGetValue(evt, out func))
        {
            if (func != null)
            {
                func = Delegate.Remove(func, listener);
                listeners[evt] = func;
            }
            else
            {
                Debug.LogError("Key" + evt + "不存在!");
            }
        }
    }

二、完整代码

using System;
using System.Collections.Generic;
using UnityEngine;

public delegate void Act();
public delegate void Act<in T>(T t1);
public delegate void Act<in T1, in T2>(T1 t1, T2 t2);
public delegate void Act<in T1, in T2, in T3>(T1 t1, T2 t2, T3 t3);
public delegate void Act<in T1, in T2, in T3, in T4>(T1 t1, T2 t2, T3 t3, T4 t4);

public delegate T Fn<out T>();
public delegate T Fn<out T, in T1>(T1 t1);
public delegate T Fn<out T, in T1, in T2>(T1 t1, T2 t2);
public delegate T Fn<out T, in T1, in T2, in T3>(T1 t1, T2 t2, T3 t3);
public delegate T Fn<out T, in T1, in T2, in T3, in T4>(T1 t1, T2 t2, T3 t3, T4 t4);

public class EventDispatcher
{
    /// <summary>
    /// 字典存放
    /// </summary>
    private Dictionary<int, Delegate> listeners = new Dictionary<int, Delegate>();
    public static EventDispatcher GameWorldEventDispatcher = new EventDispatcher();
    /// <summary>
    /// 单例模式
    /// </summary>
    public static EventDispatcher GameEvent
    {
        get
        {
            return GameWorldEventDispatcher;
        }
    }
    /// <summary>
    /// 构造函数
    /// </summary>
    public EventDispatcher()
    {
    }
    /// <summary>
    /// 移除字典中所有的键值(解绑所有事件)
    /// </summary>
    public void ClearEventListener()
    {
        listeners.Clear();
    }
    /// <summary>
    /// 添加事件注册
    /// </summary>
    /// <param name="evt">索引</param>
    /// <param name="listener"></param>
    private void AddDelegate(int evt, Delegate listener)
    {
        Delegate value;
        if (!listeners.TryGetValue(evt, out value))
        {
            //key不存在就添加
            listeners.Add(evt, listener);
        }
        else
        {
            //key存在判断value是否为空,为空就替换,不为空就多播
            value = (value != null) ? Delegate.Combine(value, listener) : listener;
            listeners[evt] = value;
        }
    }
    /// <summary>
    /// 移除事件
    /// </summary>
    /// <param name="evt"></param>
    /// <param name="listener"></param>
    private void RemoveDelegate(int evt, Delegate listener)
    {
        Delegate func;
        if (listeners.TryGetValue(evt, out func))
        {
            if (func != null)
            {
                func = Delegate.Remove(func, listener);
                listeners[evt] = func;
            }
            else
            {
                Debug.LogError("Key" + evt + "不存在!");
            }
        }
    }
    /// <summary>
    /// 注册
    /// </summary>
    /// <param name="evt"></param>
    /// <param name="listener"></param>
    public void Regist(int evt, Act listener)
    {
        if (listener == null)
        {
            return;
        }

        AddDelegate(evt, listener);
    }
    /// <summary>
    /// 移除
    /// </summary>
    /// <param name="evt"></param>
    /// <param name="listener"></param>
    public void UnRegist(int evt, Act listener)
    {
        if (listener == null)
        {
            return;
        }

        RemoveDelegate(evt, listener);
    }
    /// <summary>
    /// 事件触发
    /// </summary>
    /// <param name="evt"></param>
    public void DispatchEvent(int evt)
    {
        Delegate func;

        try
        {
            if (listeners.TryGetValue(evt, out func) && func != null)
            {
                var act = (Act)func;
                act();
            }
        }
        catch (Exception e)
        {
            UnityEngine.Debug.LogError(e.Message);
            UnityEngine.Debug.LogError(e.StackTrace);
        }
    }

    public void Regist<T>(int evt, Act<T> listener)
    {
        if (listener == null)
        {
            return;
        }

        AddDelegate(evt, listener);
    }

    public void UnRegist<T>(int evt, Act<T> listener)
    {
        if (listener == null)
        {
            return;
        }

        RemoveDelegate(evt, listener);
    }

    public void DispatchEvent<T1>(int evt, T1 args)
    {
        Delegate func;

        if (listeners.TryGetValue(evt, out func) && func != null)
        {
            var act = (Act<T1>)func;
            act(args);
        }
    }

    public void Regist<T1, T2>(int evt, Act<T1, T2> listener)
    {
        if (listener == null)
        {
            return;
        }

        AddDelegate(evt, listener);
    }

    public void UnRegist<T1, T2>(int evt, Act<T1, T2> listener)
    {
        if (listener == null)
        {
            return;
        }

        RemoveDelegate(evt, listener);
    }

    public void DispatchEvent<T1, T2>(int evt, T1 arg1, T2 arg2)
    {
        Delegate func;
        try
        {
            if (listeners.TryGetValue(evt, out func) && func != null)
            {
                var tmp = (Act<T1, T2>)func;
                tmp(arg1, arg2);
            }
        }
        catch (Exception e)
        {
            UnityEngine.Debug.LogError(e.Message);
            UnityEngine.Debug.LogError(e.StackTrace);
        }
    }

    public void Regist<T1, T2, T3>(int evt, Act<T1, T2, T3> listener)
    {
        if (listener == null)
        {
            return;
        }

        AddDelegate(evt, listener);
    }

    public void UnRegist<T1, T2, T3>(int evt, Act<T1, T2, T3> listener)
    {
        if (listener == null)
        {
            return;
        }

        RemoveDelegate(evt, listener);
    }

    public void DispatchEvent<T1, T2, T3>(int evt, T1 arg1, T2 arg2, T3 arg3)
    {
        Delegate func;

        try
        {
            if (listeners.TryGetValue(evt, out func) && func != null)
            {
                var tmp = (Act<T1, T2, T3>)func;
                tmp(arg1, arg2, arg3);
            }
        }
        catch (Exception e)
        {
            UnityEngine.Debug.LogError(e.Message);
            UnityEngine.Debug.LogError(e.StackTrace);
        }
    }

    public void Regist<T1, T2, T3, T4>(int evt, Act<T1, T2, T3, T4> listener)
    {
        if (listener == null)
        {
            return;
        }

        AddDelegate(evt, listener);
    }

    public void UnRegist<T1, T2, T3, T4>(int evt, Act<T1, T2, T3, T4> listener)
    {
        if (listener == null)
        {
            return;
        }

        RemoveDelegate(evt, listener);
    }

    public void DispatchEvent<T1, T2, T3, T4>(int evt, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
    {
        Delegate func;

        try
        {
            if (listeners.TryGetValue(evt, out func) && func != null)
            {
                var tmp = (Act<T1, T2, T3, T4>)func;
                tmp(arg1, arg2, arg3, arg4);
            }
        }
        catch (Exception e)
        {
            UnityEngine.Debug.LogError(e.Message);
            UnityEngine.Debug.LogError(e.StackTrace);
        }
    }

    public void RegistFn<T>(int evt, Fn<T> listener)
    {
        if (listener == null)
        {
            return;
        }

        AddDelegate(evt, listener);
    }

    public void UnRegistFn<T>(int evt, Fn<T> listener)
    {
        if (listener == null)
        {
            return;
        }

        RemoveDelegate(evt, listener);
    }

    public T DispatchEventFn<T>(int evt)
    {
        Delegate func;
        try
        {
            if (listeners.TryGetValue(evt, out func) && func != null)
            {
                var fn = (Fn<T>)func;
                return fn();
            }
        }
        catch (以上是关于Unity C# 游戏开发 事件 消息派发器(图文详细,带源码)的主要内容,如果未能解决你的问题,请参考以下文章

Unity游戏开发C#基础委托与事件

在 Unity 中使用委托和事件创建事件管理器(消息系统)

转UNITY3D 游戏开发之七C# 中的委托事件匿名函数Lambda 表达式

错误记录Visual Studio 2019 中运行 Unity C# 脚本时报错 ( 根据解决方案, 可能需要安装额外的组件才能获得 | .NET 桌面开发 | 使用 Unity 的游戏开发 )

在 Unity 中管理与游戏时间相关的事件的最佳方式是啥?

Android项目实战(三十九):Android集成Unity3D项目(图文详解)