Table of contents
foreword
The event system is implemented by the delegate of C#.
For an overview of the event system and the use of delegation, you can read other articles or official documents. I won’t say much here, just go to the code directly.
EventSystem definition
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Util
{
public class EventData
{
//key:变量名字,value:变量值
public Dictionary<string, object> parms {
get; private set; }
public EventData(Dictionary<string, object> parms_in)
{
parms = parms_in;
}
}
public static class EventSystem
{
//key:事件名字,value:注册该事件的所有函数
private static Dictionary<string, Action<EventData>> event_dict = new Dictionary<string, Action<EventData>>();
public static void AddEventListener(string event_type, Action<EventData> cb)
{
if (event_dict == null)
{
throw new Exception("EventSystem.event_dict is null");
}
Action<EventData> action = null;
event_dict.TryGetValue(event_type, out action);
action += cb;
event_dict[event_type] = action;
}
public static void RemoveEventListener(string event_type, Action<EventData> cb)
{
if (event_dict == null)
{
throw new Exception("EventSystem.event_dict is null");
}
Action<EventData> action = null;
if(event_dict.TryGetValue(event_type, out action))
{
action -= cb;
event_dict[event_type] = action;
}
else
{
throw new Exception($"EventSystem.event_dict is not have key : {
event_type}, {
cb.Method}");
}
}
public static void Dispatch(string event_type, EventData event_data = null)
{
if (event_dict == null)
{
throw new Exception("EventSystem.event_dict is null");
}
Action<EventData> action = null;
if (!event_dict.TryGetValue(event_type, out action))
{
throw new Exception($"EventSystem.event_dict is not have event : {
event_type}");
}
action.Invoke(event_data);
}
}
}
Application Scenario
- The initialization operation is performed when the game first starts.
- Now suppose the player has multiple states, say Win and Dead. When the player is in a different state, the specified sound effect needs to be played, and the UI needs to be updated.
Registration issue
- PlayerState.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace State
{
public enum PlayerState
{
Win,
Dead
}
}
Note The Singleton
in the code below is a singleton template class written by myself. For details, please refer to my previous article: Talking about design patterns and their applications in Unity: 1. Singleton mode
- AudioManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Util;
using State;
public class AudioManager : Singleton<AudioManager>
{
private void Awake()
{
EventSystem.AddEventListener("GameStart", GameStartPlayAudio);
EventSystem.AddEventListener("PlayerStateChange", PlayerStateChange);
}
private void GameStartPlayAudio(EventData ed)
{
print($"AudioManager : GameStartPlayAudio, ed = {
ed}");
}
private void PlayerStateChange(EventData ed)
{
PlayerState player_state = (PlayerState)ed.parms["PlayerCurrentState"];
switch (player_state)
{
case PlayerState.Win:
print("WinAudio");
break;
case PlayerState.Dead:
print("DeadAudio");
break;
}
}
}
- UIManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Util;
using State;
public class UIManager : Singleton<UIManager>
{
private void Awake()
{
EventSystem.AddEventListener("GameStart", GameStartPlayUI);
EventSystem.AddEventListener("PlayerStateChange", PlayerStateChange);
}
private void GameStartPlayUI(EventData ed)
{
print($"UIManager : GameStartPlayUI, ed = {
ed}");
}
private void PlayerStateChange(EventData ed)
{
PlayerState player_state = (PlayerState)ed.parms["PlayerCurrentState"];
switch (player_state)
{
case PlayerState.Win:
print("WinUI");
break;
case PlayerState.Dead:
print("DeadUI");
break;
}
}
}
throw event
It's a little simpler here, press the button in Update to simulate the transition of the player's state
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Util;
using State;
public class GameManager : Singleton<GameManager>
{
private void Start()
{
EventSystem.Dispatch("GameStart");
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.W))
{
EventData ed = new EventData(new Dictionary<string, object>()
{
{
"PlayerCurrentState", PlayerState.Win },
});
EventSystem.Dispatch("PlayerStateChange", ed);
}
if (Input.GetKeyDown(KeyCode.S))
{
EventData ed = new EventData(new Dictionary<string, object>()
{
{
"PlayerCurrentState", PlayerState.Dead },
});
EventSystem.Dispatch("PlayerStateChange", ed);
}
}
}