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();
}