使用
当想要新增一个事件A时,首先需做如下2件事
- 在EventName类中新增一个事件名称
public partial class EventName
{
public const string PlayerGetHit = nameof(PlayerGetHit);
}
- 新增一个继承EventParam的类,里面的字段是和该事件有关的数据
public class EventParamPlayerGetHit : EventParam
{
public string PlayerName;
public int HitValue;
}
使用
触发:EventSys.Trigger
EventSys.Instance.Trigger(EventName.PlayerGetHit, new EventParamPlayerGetHit() { PlayerName = Name, HitValue = value });
监听:EventSys.Listen
...
EventSys.Instance.Listen(EventName.PlayerGetHit, OnPlayerGetHit);
...
private void OnPlayerGetHit(EventParam param)
{
if (param is EventParamPlayerGetHit actualParam)
{
Debug.Log($"{Name} 听到 {actualParam.PlayerName} 受到 {actualParam.HitValue} 点伤害。");
}
}
取消监听:EventSys.Unlisten
EventSys.Instance.Unlisten(EventName.PlayerGetHit, OnPlayerGetHit);
测试
EventNamePlayerGetHit.cs:新增一个事件
public partial class EventName
{
public const string PlayerGetHit = nameof(PlayerGetHit);
}
EventParamPlayerGetHit.cs:新增事件的对应数据
public class EventParamPlayerGetHit : EventParam
{
public string PlayerName;
public int HitValue;
}
Player.cs:外部调用HitPlayer方法时,触发事件(传递事件对应数据)
public class Player
{
public readonly string Name;
public Player(string name) { Name = name; }
public void HitPlayer(int value)
{
EventSys.Instance.Trigger(EventName.PlayerGetHit, new EventParamPlayerGetHit() { PlayerName = Name, HitValue = value });
}
public void Destroy() { }
}
PlayerGetHitListener.cs:外部可使其开始监听、停止监听事件。监听事件期间,事件触发时,获取事件对应数据,执行相应逻辑。
using UnityEngine;
public class PlayerGetHitListener
{
public readonly string Name;
public PlayerGetHitListener(string name)
{
Name = name;
}
public void ListenPlayerGetHit()
{
Debug.Log($"{Name}尝试监听玩家受创事件。");
EventSys.Instance.Listen(EventName.PlayerGetHit, OnPlayerGetHit);
}
public void UnListenPlayerGetHit()
{
Debug.Log($"{Name}尝试移除对玩家受创事件的监听。");
EventSys.Instance.Unlisten(EventName.PlayerGetHit, OnPlayerGetHit);
}
private void OnPlayerGetHit(EventParam param)
{
if (param is EventParamPlayerGetHit actualParam)
{
Debug.Log($"{Name} 听到 {actualParam.PlayerName} 受到 {actualParam.HitValue} 点伤害。");
}
}
public void Destroy()
{ }
}
EventTest.cs:通过按键测试事件的触发、监听、取消监听。
using UnityEngine;
public class EventTest : MonoBehaviour
{
private Player _player;
private PlayerGetHitListener _listenerA;
private PlayerGetHitListener _listenerB;
private void Start()
{
Init();
}
private void Update()
{
MyUpdate();
}
private void OnDestroy()
{
MyDestroy();
}
private void Init()
{
_player = new Player("玩家");
_listenerA = new PlayerGetHitListener("监听者A");
_listenerB = new PlayerGetHitListener("监听者B");
}
private void MyUpdate()
{
if (Input.GetKeyDown(KeyCode.A))
{
_listenerA.ListenPlayerGetHit();
}
else if (Input.GetKeyDown(KeyCode.B))
{
_listenerA.UnListenPlayerGetHit();
}
else if (Input.GetKeyDown(KeyCode.C))
{
_listenerB.ListenPlayerGetHit();
}
else if (Input.GetKeyDown(KeyCode.D))
{
_listenerB.UnListenPlayerGetHit();
}
else if (Input.GetKeyDown(KeyCode.E))
{
_player.HitPlayer(UnityEngine.Random.Range(10, 100));
}
}
private void MyDestroy()
{
_listenerB.Destroy();
_listenerB = null;
_listenerA.Destroy();
_listenerA = null;
_player.Destroy();
_player = null;
}
}
实现
EventName.cs:部分类,里面是所有事件名称
public partial class EventName
{
}
EventParam.cs:事件数据的基类
public abstract class EventParam
{
}
EventSys.cs:事件系统,是一个单例,提供触发、监听、取消监听事件的方法。
using System;
using System.Collections.Generic;
using UnityEngine;
public class EventSys
{
private static EventSys _instance;
public static EventSys Instance
{
get
{
if (_instance == null)
{
_instance = new EventSys();
}
return _instance;
}
}
private Dictionary<string, List<Action<EventParam>>> _dict;
private EventSys()
{
_dict = new Dictionary<string, List<Action<EventParam>>>();
}
public void Destroy()
{
_dict.Clear();
_dict = null;
_instance = null;
}
public void Listen(string eventName, Action<EventParam> action)
{
if (!_dict.ContainsKey(eventName))
{
_dict.Add(eventName, new List<Action<EventParam>>());
Debug.Log($"新增事件:{eventName}");
}
if (!_dict[eventName].Contains(action))
{
_dict[eventName].Add(action);
}
else
{
Debug.Log($"监听事件 {eventName} 失败:重复监听!");
}
}
public void Unlisten(string eventName, Action<EventParam> action)
{
if (_dict.ContainsKey(eventName))
{
if (!_dict[eventName].Remove(action))
{
Debug.Log($"移除监听失败,因为当前action并未监听事件 {eventName}。");
}
else if (_dict[eventName].Count == 0)
{
_dict.Remove(eventName);
}
}
else
{
Debug.Log($"移除监听失败,因为不存在事件 {eventName}。");
}
}
public void Trigger(string eventName, EventParam param)
{
if (_dict.ContainsKey(eventName))
{
foreach (var action in _dict[eventName])
{
action?.Invoke(param);
}
}
}
}
网友评论