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

Unity C# 游戏开发:事件消息派发器实现与应用
本文详细介绍了如何使用C#在Unity中实现一个事件消息派发器,包括添加事件注册、触发事件和移除事件的功能,并提供了完整代码。通过实例展示了无参数和有参数的事件调用,简化了游戏开发中的事件处理。此外,还给出了使用案例,如按Esc键退出游戏的事件处理。


事情是这样的

可可爱爱的程序媛小姐姐又来找我玩啦,本来是开心的聊天却变成了技术研讨会,小姐姐说最近敲代码,各种事件委托,各种观察者模式,手都敲麻了,问我有好办法没有
请添加图片描述
那我可以帮你揉一下?(显然不符合我钢铁直男的人设),那就写个消息派发器来帮助小姐姐吧!


🔥总目录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
————————————————————————————————

版权声明

版权声明:本博客为非营利性个人原创
所刊登的所有作品的著作权均为本人所拥有
本人保留所有法定权利,违者必究!
对于需要复制、转载、链接和传播博客文章或内容的
请及时和本博主进行联系
对于经本博主明确授权和许可使用文章及内容的
使用时请注明文章或内容出处并注明网址
转载请附上原文出处链接及本声明

评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值