Unity C# 游戲開發 事件 訊息派發器 (圖文詳細,帶原始碼)
- 事情是這樣的
- 一、訊息派發器的幾個功能
- 1.添加事件注冊
- 2.事件的觸發
- 3.移除事件
- 二、完整代碼
- 三、使用案例
- 1.沒有引數的呼叫
- 2.有引數的呼叫
- 總結
- 著作權宣告
事情是這樣的
可可愛愛的程式媛小姐姐又來找我玩啦,本來是開心的聊天卻變成了技術研討會,小姐姐說最近敲代碼,各種事件委托,各種觀察者模式,手都敲麻了,問我有好辦法沒有

那我可以幫你揉一下?(顯然不符合我鋼鐵直男的人設),那就寫個訊息派發器來幫助小姐姐吧!
一、訊息派發器的幾個功能
既然是要來簡化觀察者模式,那功能肯定一個都不能少
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
————————————————————————————————
著作權宣告
著作權宣告:本博客為非營利性個人原創
所刊登的所有作品的著作權均為本人所擁有
本人保留所有法定權利,違者必究!
對于需要復制、轉載、鏈接和傳播博客文章或內容的
請及時和本博主進行聯系
對于經本博主明確授權和許可使用文章及內容的
使用時請注明文章或內容出處并注明網址
轉載請附上原文出處鏈接及本宣告
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/293440.html
標籤:其他
上一篇:牛批了!全站首個!tkinter 網路音樂播放器,你不點贊算我輸!
下一篇:Java 基礎語法(2)邏輯控制
