UFL4-1——事件中心具体实现

具体实现

  1. 创建EventCenter​ 继承 不继承MonoBehaviour的单例模式基类

  2. 声明管理事件用容器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Events;

    /// <summary>
    /// 事件中心模块
    /// </summary>
    public class EventCenter : BaseManager<EventCenter>
    {
    private Dictionary<string, UnityAction> eventDic = new Dictionary<string, UnityAction>();

    private EventCenter() { }

  3. 实现关键方法

    • 触发(分发)事件 方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      private Dictionary<string, UnityAction> eventDic = new Dictionary<string, UnityAction>();

      /// <summary>
      /// 触发事件
      /// </summary>
      /// <param name="eventName">要触发的事件名字</param>
      public void EventTrigger(string eventName)
      {
      //如果没有对象监听这个事件,则直接返回
      if (!eventDic.ContainsKey(eventName))
      return;
      eventDic[eventName]?.Invoke();
      }
    • 添加事件监听者 方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      private Dictionary<string, UnityAction> eventDic = new Dictionary<string, UnityAction>();

      private EventCenter() { }

      /// <summary>
      /// 添加事件监听者
      /// </summary>
      /// <param name="eventName">要监听的事件</param>
      /// <param name="action">监听到事件后要执行的方法</param>
      public void AddEventListener(string eventName, UnityAction action)
      {
      if (eventDic.ContainsKey(eventName))
      eventDic[eventName] += action;
      else
      {
      //eventDic.Add(eventName, new UnityAction(action)); //不要这样写,会无法移除传入的方法
      eventDic.Add(eventName, null);
      eventDic[eventName] += action;
      }
      }
    • 移除事件监听者 方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      private Dictionary<string, UnityAction> eventDic = new Dictionary<string, UnityAction>();

      /// <summary>
      /// 移除事件监听
      /// </summary>
      /// <param name="eventName">要移除监听的事件</param>
      /// <param name="action">要移除监听的方法</param>
      public void RemoveEventListener(string eventName, UnityAction action)
      {
      if (eventDic.ContainsKey(eventName))
      eventDic[eventName] -= action;
      }
    • 清除所有事件监听者 方法

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      private Dictionary<string, UnityAction> eventDic = new Dictionary<string, UnityAction>();

      /// <summary>
      /// 清除所有事件的监听
      /// </summary>
      public void Clear()
      {
      eventDic.Clear();
      }

      /// <summary>
      /// 清除某一个事件的监听
      /// </summary>
      /// <param name="eventName"></param>
      public void Clear(string eventName)
      {
      if (eventDic.ContainsKey(eventName))
      eventDic.Remove(eventName);
      }

使用方法

Monster​类对象“死亡”时,让其他相关对象执行对应的方法,旧写法如下

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
using UnityEngine;

public class Monster : MonoBehaviour
{
void Start()
{
Dead();
}

void Dead()
{
Debug.Log("怪物死亡了");
//其他对象在怪物死亡时要做的事情
//1.任务更新
GameObject.Find("Task").GetComponent<Task>().TaskWaitMonsterDeadDo();
//2.玩家得奖励
GameObject.Find("Player").GetComponent<Player>().PlayerWaitMonsterDeadDo();
//3.其他相关系统
GameObject.Find("Other").GetComponent<Other>().OtherWaitMonsterDeadDo();
//n个其他相关处理..
//...
}
}

public class Task : MonoBehaviour
{
public void TaskWaitMonsterDeadDo()
{
Debug.Log("任务更新了");
}
}

public class Player : MonoBehaviour
{
public void PlayerWaitMonsterDeadDo()
{
Debug.Log("玩家得到奖励");
}
}

public class Other : MonoBehaviour
{
public void OtherWaitMonsterDeadDo()
{
Debug.Log("其他相关处理");
}
}

而如果使用事件中心,则写法如下:

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
using UnityEngine;

public class Monster : MonoBehaviour
{
void Start()
{
Dead();
}

void Dead()
{
Debug.Log("怪物死亡了");
//其他对象在怪物死亡时要做的事情
EventCenter.Instance.EventTrigger("MonsterDead");
}
}

public class Task : MonoBehaviour
{
private void Awake()
{
EventCenter.Instance.AddEventListener("MonsterDead", TaskWaitMonsterDeadDo);
}

public void TaskWaitMonsterDeadDo()
{
Debug.Log("任务更新了");
}
}

public class Player : MonoBehaviour
{
private void Awake()
{
EventCenter.Instance.AddEventListener("MonsterDead", PlayerWaitMonsterDeadDo);
}

public void PlayerWaitMonsterDeadDo()
{
Debug.Log("玩家得到奖励");
}
}

public class Other : MonoBehaviour
{
private void Awake()
{
EventCenter.Instance.AddEventListener("MonsterDead", OtherWaitMonsterDeadDo);
}

public void OtherWaitMonsterDeadDo()
{
Debug.Log("其他相关处理");
}
}

可以发现,使用事件中心的Monster​类无需再从实现需要执行哪些对象的哪些方法,它只需要向事件中心触发怪物死亡事件
而监听怪物死亡事件的类需要主动将要执行的方法传入到事件中心的委托内,而不再需要被其他类直接获取并调用自身的方法

值得一提的是,监听事件,有加就有减,当被销毁或者不再需要监听事件的时候必须要将监听事件移除出委托

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using UnityEngine;

public class Other : MonoBehaviour
{
private void Awake()
{
EventCenter.Instance.AddEventListener("MonsterDead", OtherWaitMonsterDeadDo);
}

public void OtherWaitMonsterDeadDo()
{
Debug.Log("其他相关处理");
}

private void OnDestroy()
{
EventCenter.Instance.RemoveEventListener("MonsterDead", OtherWaitMonsterDeadDo);
}
}

//其他类不再重复书写

事件中心完整代码

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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

/// <summary>
/// 事件中心模块
/// </summary>
public class EventCenter : BaseManager<EventCenter>
{
private Dictionary<string, UnityAction> eventDic = new Dictionary<string, UnityAction>();

private EventCenter() { }

/// <summary>
/// 触发事件
/// </summary>
/// <param name="eventName">要触发的事件名字</param>
public void EventTrigger(string eventName)
{
//如果没有对象监听这个事件,则直接返回
if (!eventDic.ContainsKey(eventName))
return;
eventDic[eventName]?.Invoke(info);
}

/// <summary>
/// 添加事件监听者
/// </summary>
/// <param name="eventName">要监听的事件</param>
/// <param name="action">监听到事件后要执行的方法</param>
public void AddEventListener(string eventName, UnityAction action)
{
if (eventDic.ContainsKey(eventName))
eventDic[eventName] += action;
else
{
//eventDic.Add(eventName, new UnityAction(action)); //不要这样写,会无法移除传入的方法
eventDic.Add(eventName, null);
eventDic[eventName] += action;
}
}

/// <summary>
/// 移除事件监听
/// </summary>
/// <param name="eventName">要移除监听的事件</param>
/// <param name="action">要移除监听的方法</param>
public void RemoveEventListener(string eventName, UnityAction action)
{
if (eventDic.ContainsKey(eventName))
eventDic[eventName] -= action;
}

/// <summary>
/// 清除所有事件的监听
/// </summary>
public void Clear()
{
eventDic.Clear();
}

/// <summary>
/// 清除某一个事件的监听
/// </summary>
/// <param name="eventName"></param>
public void Clear(string eventName)
{
if (eventDic.ContainsKey(eventName))
eventDic.Remove(eventName);
}
}