Unity遊戲開發 — 事件系統
記得剛剛畢業時候,上班的第一天,主程就給我講了遊戲開發中最常見的幾種設計模式,當時聽得一頭霧水。只知道事件分發,事件監聽,事件註冊。那麼到底是怎麼實現的呢?下面我們慢慢的揭開它。
-
先了解一下什麼是委託。這是C#基礎,這裏就不在陳述了。
-
瞭解什麼觀察者模式。簡單的說:就是完美的將觀察者和被觀察的對象分離開,觀察者設計模式定義了對象間的一種一對多的組合關係,以便一個對象的狀態發生變化時,所有依賴於它的對象都得到通知並自動刷新。
遊戲事件系統
unity的事件系統就是根據上面的組合現實的。
- 添加事件註冊`
private void AddDelegate(int evt, Delegate listener)
{
Delegate value;
if (!listeners.TryGetValue(evt, out value))
{
listeners.Add(evt, listener);
}
else
{
value = (value != null) ? Delegate.Combine(value, listener) : listener;
listeners[evt] = value;
}
}
- 移除事件
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;
}
}
}
- 事件觸發
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);
}
}
基本就是上面的這三個步驟;
這是源代碼
using System;
using System.Collections.Generic;
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
{
private Dictionary<int, Delegate> listeners = new Dictionary<int, Delegate>();
public EventDispatcher()
{
}
public void ClearEventListener()
{
listeners.Clear();
}
private void AddDelegate(int evt, Delegate listener)
{
Delegate value;
if (!listeners.TryGetValue(evt, out value))
{
listeners.Add(evt, listener);
}
else
{
value = (value != null) ? Delegate.Combine(value, listener) : listener;
listeners[evt] = value;
}
}
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;
}
}
}
public void Regist(int evt, Act listener)
{
if (listener == null)
{
return;
}
AddDelegate(evt, listener);
}
public void UnRegist(int evt, Act listener)
{
if (listener == null)
{
return;
}
RemoveDelegate(evt, listener);
}
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);
}
static EventDispatcher GameWorldEventDispatcher = new EventDispatcher();
public static EventDispatcher GameEvent
{
get
{
return GameWorldEventDispatcher;
}
}
}
在遊戲需要調用的地方
最後說一下在遊戲退出後執行一下
public void ClearEventListener()
{
listeners.Clear();
}