Unity框架之事件中心模块

本文引入一种常见的设计模式:观察者模式。

事件中心模块作用

在玩游戏时经常有这样的场景,你打死了一只怪:怪物爆金币、角色经验提升、角色天赋升级。假如你是游戏开发者,会怎么处理这些逻辑?我最先的想法是这样的:写一个void MonsterDead(){},在里面添加各种方法,GetMoney()、PlayerUpdate()。
这样写貌似也没问题,但是当逻辑多起来、维护起来就比较困难了,又杂又乱。用专业的语言来说,就是我们“代码耦合性高”。因此引入事件中心模块。

思路

在军队中,有着指挥部。我们是不是也可以在代码里建立个“指挥部”,把各种命令都交给指挥部来做?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//既然是指挥部,那就只有一个,继承单例模式基类
public class EventMgr : SingletonBase<EventMgr>
{
//我们用字典来存储,思路是,用string来存储游戏里的事件,UnityAction执行触发事件后的一系列方法,比如爆金币、玩家升级
private Dictionary<string,UnityAction> eventmgr = new Dictionary<string,UnityAction>();
//我们写事件监听函数
public void AddEventListener(string name,UnityAction action)
{
if (eventmgr.ContainsKey(name))
{
eventmgr[name] += action;
}
else
{
eventmgr.Add(name, action);
}
}
//游戏事件触发后执行的一系列逻辑
public void EventTrigger(string name)
{
if (!eventmgr.ContainsKey(name))
{
Debug.Log("指定方法不存在!");
}
else
{
eventmgr[name].Invoke();
}
}
}
//我们假设有个怪物类,触发事件“MonsterDead”
public class Monster : MonoBehaviour
{
private void Start()
{
EventMgr.GetInstance().EventTrigger("MonsterDead");
}
}
//之后我们玩家,只需要往这个事件里添加方法逻辑就好,往MonsterDead事件里添加函数MonsterDeadDo
public class Player : MonoBehaviour
{
void Start()
{
EventMgr.GetInstance().AddEventListener("MonsterDead", MonsterDeadDo);
}

/// <summary>
/// 怪物死时要做些什么
/// </summary>
public void MonsterDeadDo()
{
Debug.Log("玩家得奖励");
}
}

就这样,我们的基础事件中心模块就写好了。

进阶优化版

之前写了个简单的事件管理中心,但它其实是有局限性的,只能传入无参的函数,对于有参的函数就不行了,于是有了v2.0版本。
最先想到的是,多声明几个字典,但这样就破坏了管理中心的理念,应该是只有一个字典、能装载不同的函数才对。那么新的思路就是把有参的、无参的都封装成一个,继承同一个接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
using System;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Events;

public class GameEventManager : Single<GameEventManager>
{
public delegate void MyAction<T1, T2, T3, T4, T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
private interface IEventHelp
{

}

private class EventHelp : IEventHelp
{
public event UnityAction Action;

public void AddCall(UnityAction action)
{
Action += action;
}

public void Call()
{
Action?.Invoke();
}

public void RemoveCall(UnityAction action)
{
Action -= action;
}
}

private class EventHelp<T> : IEventHelp
{
public event UnityAction<T> Action;

public void AddCall(UnityAction<T> action)
{
Action += action;
}

public void Call(T param)
{
Action?.Invoke(param);
}

public void RemoveCall(UnityAction<T> action)
{
Action -= action;
}
}

private class EventHelp<T1, T2, T3> : IEventHelp
{
public event UnityAction<T1, T2, T3> Action;

public void AddCall(UnityAction<T1, T2, T3> action)
{
Action += action;
}

public void Call(T1 param1, T2 param2, T3 param3)
{
Action?.Invoke(param1, param2, param3);
}

public void RemoveCall(UnityAction<T1, T2, T3> action)
{
Action -= action;
}
}

private class EventHelp<T1, T2, T3, T4, T5> : IEventHelp
{
public event MyAction<T1, T2, T3, T4, T5> Action;

public void AddCall(MyAction<T1, T2, T3, T4, T5> action)
{
Action += action;
}

public void Call(T1 param1, T2 param2, T3 param3, T4 param4, T5 param5)
{
Action?.Invoke(param1, param2, param3, param4, param5);
}

public void RemoveCall(MyAction<T1, T2, T3, T4, T5> action)
{
Action -= action;
}
}

private Dictionary<string, IEventHelp> eventManager = new Dictionary<string, IEventHelp>();

// 添加事件监听
public void AddEventListening(string eventName, UnityAction action)
{
if (!eventManager.ContainsKey(eventName))
{
eventManager[eventName] = new EventHelp();
}
((EventHelp)eventManager[eventName]).AddCall(action);
}

// 添加带参数的事件监听
public void AddEventListening<T>(string eventName, UnityAction<T> action)
{
if (!eventManager.ContainsKey(eventName))
{
eventManager[eventName] = new EventHelp<T>();
}
((EventHelp<T>)eventManager[eventName]).AddCall(action);
}

public void AddEventListening<T1, T2, T3>(string eventName, UnityAction<T1, T2, T3> action)
{
if (!eventManager.ContainsKey(eventName))
{
eventManager[eventName] = new EventHelp<T1, T2, T3>();
}
((EventHelp<T1, T2, T3>)eventManager[eventName]).AddCall(action);
}

public void AddEventListening<T1, T2, T3, T4, T5>(string eventName, MyAction<T1, T2, T3, T4, T5> action)
{
if (!eventManager.ContainsKey(eventName))
{
eventManager[eventName] = new EventHelp<T1, T2, T3, T4, T5>();
}
((EventHelp<T1, T2, T3, T4, T5>)eventManager[eventName]).AddCall(action);
}

// 删除事件监听
public void RemoveEvent(string eventName, UnityAction action)
{
if (eventManager.ContainsKey(eventName))
{
var eventHelp = eventManager[eventName] as EventHelp;
if (eventHelp != null)
{
eventHelp.RemoveCall(action);
}
}
}

// 删除带参数的事件监听
public void RemoveEvent<T>(string eventName, UnityAction<T> action)
{
if (eventManager.ContainsKey(eventName))
{
var eventHelp = eventManager[eventName] as EventHelp<T>;
if (eventHelp != null)
{
eventHelp.RemoveCall(action);
}
}
}

public void RemoveEvent<T1, T2, T3>(string eventName, UnityAction<T1, T2, T3> action)
{
if (eventManager.ContainsKey(eventName))
{
var eventHelp = eventManager[eventName] as EventHelp<T1, T2, T3>;
if (eventHelp != null)
{
eventHelp.RemoveCall(action);
}
}
}

public void RemoveEvent<T1, T2, T3, T4, T5>(string eventName, MyAction<T1, T2, T3, T4, T5> action)
{
if (eventManager.ContainsKey(eventName))
{
var eventHelp = eventManager[eventName] as EventHelp<T1, T2, T3, T4, T5>;
if (eventHelp != null)
{
eventHelp.RemoveCall(action);
}
}
}

// 触发事件
public void InvokeEvent(string eventName)
{
if (eventManager.ContainsKey(eventName))
{
var eventHelp = eventManager[eventName] as EventHelp;
if (eventHelp != null)
{
eventHelp.Call();
}
}
}

// 触发带参数的事件
public void InvokeEvent<T>(string eventName, T param)
{
if (eventManager.ContainsKey(eventName))
{
var eventHelp = eventManager[eventName] as EventHelp<T>;
if (eventHelp != null)
{
eventHelp.Call(param);
}
}
}

public void InvokeEvent<T1, T2, T3>(string eventName, T1 param1, T2 param2, T3 param3)
{
if (eventManager.ContainsKey(eventName))
{
var eventHelp = eventManager[eventName] as EventHelp<T1, T2, T3>;
if (eventHelp != null)
{
eventHelp.Call(param1, param2, param3);
}
}
}

public void InvokeEvent<T1, T2, T3, T4, T5>(string eventName, T1 param1, T2 param2, T3 param3, T4 param4, T5 param5)
{
if (eventManager.ContainsKey(eventName))
{
var eventHelp = eventManager[eventName] as EventHelp<T1, T2, T3, T4, T5>;
if (eventHelp != null)
{
eventHelp.Call(param1, param2, param3, param4, param5);
}
}
}
}