Unity C# 游戏开发 事件 消息派发器 (图文详细,带源码)
事情是这样的
可可爱爱的程序媛小姐姐又来找我玩啦,本来是开心的聊天却变成了技术研讨会,小姐姐说最近敲代码,各种事件委托,各种观察者模式,手都敲麻了,问我有好办法没有
 
 那我可以帮你揉一下?(显然不符合我钢铁直男的人设),那就写个消息派发器来帮助小姐姐吧!
 
🔥总目录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 (Exception e)
        {
            UnityEngine.Debug.LogError(e.Message);
            UnityEngine.Debug.LogError(e.StackTrace);
        }
        return default(T);
    }
    public void RegistFn<T, T1>(int evt, Fn<T, T1> listener)
    {
        if (listener == null)
        {
            return;
        }
        AddDelegate(evt, listener);
    }
    public void UnRegistFn<T, T1>(int evt, Fn<T, T1> listener)
    {
        if (listener == null)
        {
            return;
        }
        RemoveDelegate(evt, listener);
    }
    public T DispatchEventFn<T, T1>(int evt, T1 args)
    {
        Delegate func;
        try
        {
            if (listeners.TryGetValue(evt, out func) && func != null)
            {
                var tmp = (Fn<T, T1>)func;
                return tmp(args);
            }
        }
        catch (Exception e)
        {
            UnityEngine.Debug.LogError(e.Message);
            UnityEngine.Debug.LogError(e.StackTrace);
        }
        return default(T);
    }
    public void RegistFn<T, T1, T2>(int evt, Fn<T, T1, T2> listener)
    {
        if (listener == null)
        {
            return;
        }
        AddDelegate(evt, listener);
    }
    public void UnRegistFn<T, T1, T2>(int evt, Fn<T, T1, T2> listener)
    {
        if (listener == null)
        {
            return;
        }
        RemoveDelegate(evt, listener);
    }
    public T DispatchEventFn<T, T1, T2>(int evt, T1 arg1, T2 arg2)
    {
        Delegate func;
        try
        {
            if (listeners.TryGetValue(evt, out func) && func != null)
            {
                var fn = (Fn<T, T1, T2>)func;
                return fn(arg1, arg2);
            }
        }
        catch (Exception e)
        {
            UnityEngine.Debug.LogError(e.Message);
            UnityEngine.Debug.LogError(e.StackTrace);
        }
        return default(T);
    }
    public void RegistFn<T, T1, T2, T3>(int evt, Fn<T, T1, T2, T3> listener)
    {
        if (listener == null)
        {
            return;
        }
        AddDelegate(evt, listener);
    }
    public void UnRegistFn<T, T1, T2, T3>(int evt, Fn<T, T1, T2, T3> listener)
    {
        if (listener == null)
        {
            return;
        }
        RemoveDelegate(evt, listener);
    }
    public T DispatchEventFn<T, T1, T2, T3>(int evt, T1 arg1, T2 arg2, T3 arg3)
    {
        Delegate func;
        try
        {
            if (listeners.TryGetValue(evt, out func) && func != null)
            {
                var fn = (Fn<T, T1, T2, T3>)func;
                return fn(arg1, arg2, arg3);
            }
        }
        catch (Exception e)
        {
            UnityEngine.Debug.LogError(e.Message);
            UnityEngine.Debug.LogError(e.StackTrace);
        }
        return default(T);
    }
    public void RegistFn<T, T1, T2, T3, T4>(int evt, Fn<T, T1, T2, T3, T4> listener)
    {
        if (listener == null)
        {
            return;
        }
        AddDelegate(evt, listener);
    }
    public void UnRegistFn<T, T1, T2, T3, T4>(int evt, Fn<T, T1, T2, T3, T4> listener)
    {
        if (listener == null)
        {
            return;
        }
        RemoveDelegate(evt, listener);
    }
    public T DispatchEventFn<T, 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 fn = (Fn<T, T1, T2, T3, T4>)func;
                return fn(arg1, arg2, arg3, arg4);
            }
        }
        catch (Exception e)
        {
            UnityEngine.Debug.LogError(e.Message);
            UnityEngine.Debug.LogError(e.StackTrace);
        }
        return default(T);
    }
    
}
 
三、使用案例
接下来就是重点了,那我们如何使用呢?
 比如说我要做一个功能,按下Esc键,退出app
1.没有参数的调用
那首先,我们就要先注册事件
EventDispatcher.GameEvent.Regist(4500,EscBehavior);
private void EscBehavior()
    {
        Application.Quit();
    }
 
触发事件
private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            Debug.Log("发了4500");
            EventDispatcher.GameEvent.DispatchEvent(4500);
        }
    }
 
移除事件
 private void OnDestroy()
    {
        EventDispatcher.GameEvent.UnRegist(4500,EscBehavior);
    }
 
这就是一个完整的调用流程。
2.有参数的调用
又有人问了,那需要传参的怎么用啊
 需要传参的用法,那他来了
 熟悉的配方:
 
1.注册事件
EventDispatcher.GameEvent.Regist<string>(4500,EscBehavior);
private void EscBehavior(string content)
    {
        Debug.Log("要debug的内容:"+content);
        Application.Quit();
    }
 
2.触发事件
private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            Debug.Log("发了4500");
             EventDispatcher.GameEvent.DispatchEvent<string>(4500,"必须要退出app啦!!!!!");
        }
    }
 
3.移除事件
private void OnDestroy()
    {
        EventDispatcher.GameEvent.UnRegist<string>(4500,EscBehavior);
    }
 
至此就大功告成了,小姐姐的手终于不麻了。
总结
欢迎大佬多多来给萌新指正,欢迎大家来共同探讨。
 如果各位看官觉得文章有点点帮助,跪求各位给点个“一键三连”,谢啦~
声明:本博文章若非特殊注明皆为原创原文链接
 https://blog.csdn.net/Wrinkle2017/article/details/119575597
 ————————————————————————————————
版权声明
 版权声明:本博客为非营利性个人原创
 所刊登的所有作品的著作权均为本人所拥有
 本人保留所有法定权利,违者必究!
 对于需要复制、转载、链接和传播博客文章或内容的
 请及时和本博主进行联系
 对于经本博主明确授权和许可使用文章及内容的
 使用时请注明文章或内容出处并注明网址
 转载请附上原文出处链接及本声明
Unity C# 游戏开发:事件消息派发器实现与应用
        
                  
                  
                  
                  
                            
                            
                            
本文详细介绍了如何使用C#在Unity中实现一个事件消息派发器,包括添加事件注册、触发事件和移除事件的功能,并提供了完整代码。通过实例展示了无参数和有参数的事件调用,简化了游戏开发中的事件处理。此外,还给出了使用案例,如按Esc键退出游戏的事件处理。
          
                    
      
          
                
                
                
                
              
                
                
                
                
                
              
                
                
              
            
                  
					2513
					
被折叠的  条评论
		 为什么被折叠?
		 
		 
		
    
  
    
  
            


            