Unity C# game development event message dispatcher details

Posted by wannalearnit on Fri, 24 Dec 2021 22:14:11 +0100

it happened like this

But the lovely and loving program, little sister yuan, came to play with me again. Originally a happy chat, it turned into a technical seminar. She said that recently, she knocked the code, entrusted various events, various observer modes, and her hands were numb. She asked me if I had a good way

Can I rub it for you? (obviously not in line with my iron straight man's design), then write a message dispatcher to help my little sister!

1, Several functions of message dispatcher

Since it is to simplify the observer mode, there must be no less functions

1. Add event registration

Two parameters are required, the first is the index and the second is the event

/// <summary>
    ///Add event registration
    /// </summary>
    ///< param name = "EVT" > index < / param >
    /// <param name="listener"></param>
    private void AddDelegate(int evt, Delegate listener)
    {
        Delegate value;
        if (!listeners.TryGetValue(evt, out value))
        {
            //Add if key does not exist
            listeners.Add(evt, listener);
        }
        else
        {
            //If the key exists, judge whether the value is empty, replace it if it is empty, and multicast if it is not empty
            value = (value != null) ? Delegate.Combine(value, listener) : listener;
            listeners[evt] = value;
        }
    }

2. Event triggering

An index needs to be passed in to trigger the event

/// <summary>
    ///Event trigger
    /// </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. Remove event

The parameters required for event removal and registration are the same

/// <summary>
    ///Remove event
    /// </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 + "non-existent!");
            }
        }
    }

2, Complete code

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>
    ///Dictionary storage
    /// </summary>
    private Dictionary<int, Delegate> listeners = new Dictionary<int, Delegate>();
    public static EventDispatcher GameWorldEventDispatcher = new EventDispatcher();
    /// <summary>
    ///Singleton mode
    /// </summary>
    public static EventDispatcher GameEvent
    {
        get
        {
            return GameWorldEventDispatcher;
        }
    }
    /// <summary>
    ///Constructor
    /// </summary>
    public EventDispatcher()
    {
    }
    /// <summary>
    ///Remove all key values from the dictionary (unbind all events)
    /// </summary>
    public void ClearEventListener()
    {
        listeners.Clear();
    }
    /// <summary>
    ///Add event registration
    /// </summary>
    ///< param name = "EVT" > index < / param >
    /// <param name="listener"></param>
    private void AddDelegate(int evt, Delegate listener)
    {
        Delegate value;
        if (!listeners.TryGetValue(evt, out value))
        {
            //Add if key does not exist
            listeners.Add(evt, listener);
        }
        else
        {
            //If the key exists, judge whether the value is empty, replace it if it is empty, and multicast if it is not empty
            value = (value != null) ? Delegate.Combine(value, listener) : listener;
            listeners[evt] = value;
        }
    }
    /// <summary>
    ///Remove event
    /// </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 + "non-existent!");
            }
        }
    }
    /// <summary>
    ///Register
    /// </summary>
    /// <param name="evt"></param>
    /// <param name="listener"></param>
    public void Regist(int evt, Act listener)
    {
        if (listener == null)
        {
            return;
        }

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

        RemoveDelegate(evt, listener);
    }
    /// <summary>
    ///Event trigger
    /// </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);
    }

    
}


3, Use case

Now that's the point, how do we use it?
For example, I want to do a function, press Esc to exit the app

1. Call without parameters

First, we need to register events

EventDispatcher.GameEvent.Regist(4500,EscBehavior);
private void EscBehavior()
    {
        Application.Quit();
    }

Trigger event

private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            Debug.Log("4500");
            EventDispatcher.GameEvent.DispatchEvent(4500);
        }
    }

Remove event

 private void OnDestroy()
    {
        EventDispatcher.GameEvent.UnRegist(4500,EscBehavior);
    }

This is a complete call process.

2. Call with parameters

Someone asked again, how to use those that need to pass parameters
Need to pass the use of parameters, then he's here
Familiar formula:

1. Registration event

EventDispatcher.GameEvent.Regist<string>(4500,EscBehavior);
private void EscBehavior(string content)
    {
        Debug.Log("want debug Content of:"+content);
        Application.Quit();
    }

2. Trigger event

private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            Debug.Log("4500");
             EventDispatcher.GameEvent.DispatchEvent<string>(4500,"You must exit app la");
        }
    }

3. Remove event

private void OnDestroy()
    {
        EventDispatcher.GameEvent.UnRegist<string>(4500,EscBehavior);
    }

So far, it's done. My little sister's hands are finally numb.

summary

Welcome big guys to give more comments to Mengxin, and welcome everyone to discuss it together.
If you feel that the article is a little helpful, please kneel down and beg you to point out "one key three links". Thank you~

Statement: this blog article is original unless otherwise noted Original link
https://blog.csdn.net/Wrinkle2017/article/details/119533902
----------------

Copyright notice

Copyright notice: this blog is created by non-profit individuals
I own the copyright of all published works
I reserve all legal rights. Violators will be prosecuted!
For those who need to copy, reprint, link and disseminate blog posts or content
Please contact the blogger in time
For the use of articles and contents expressly authorized and licensed by the blogger
When using, please indicate the source of the article or content and indicate the website
Please attach the original source link and this statement

Topics: C# Unity Game Development Unity3d