Unity 事件广播与监听
编辑
225
2023-12-08
脚本下载
广播系统优点
-
简化代码结构: 该事件处理系统可以帮助更轻松地管理事件和监听器,从而简化代码结构。可以将不同部分的代码分开,以实现更好的代码组织和可维护性。
-
低耦合性: 通过使用事件处理系统,不同的游戏对象或组件可以通过事件通信,而无需直接引用彼此。这降低了代码的耦合性,使得项目更加灵活和可扩展。
-
易于扩展: 可以轻松地添加新的事件类型和监听器,以响应不同的游戏事件。这使得项目的功能扩展变得相对容易,无需大规模修改现有代码。
-
代码可读性: 使用事件处理系统,可以更清晰地看到哪些部分的代码响应了特定类型的事件,从而提高了代码的可读性和维护性。
调用方法
using UnityEngine;
using Event;
public class TestEventScript : MonoBehaviour
{
private (EventType, long) listenerIdentifier;
private void Awake()
{
// 在 Awake 方法中添加监听器,并存储返回的唯一标识符
listenerIdentifier = EventDispose.AddListener<string>(EventType.ShowText, ShowTextMethod);
}
private void ShowTextMethod(string text)
{
// 当 ShowText 事件被触发时,执行此方法
Debug.Log($"ShowText Event Triggered: {text}");
}
private void OnDestroy()
{
// 注意,若使用匿名函数添加监听器,只能使用 方法1 取消监听
// 移除监听器 - 方法1: 使用事件类型和唯一标识符 (建议使用)
EventDispose.RemoveListener(listenerIdentifier.Item1, listenerIdentifier.Item2);
// 移除监听器 - 方法2: 使用事件类型和监听器操作
EventDispose.RemoveListener<string>(EventType.ShowText, ShowTextMethod);
}
// 调用这个方法来测试广播事件
public void TestBroadcast()
{
// 广播 ShowText 事件
EventDispose.Broadcast<string>(EventType.ShowText, "Hello, World!");
}
}
详细代码
EventType 脚本
namespace Event
{
/// <summary>
/// 定义可能的事件类型
/// </summary>
public enum EventType
{
ShowText,
}
}
EventDispose 脚本
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
namespace Event
{
/// <summary>
/// EventDispose类提供了一个用于管理事件监听器的集中式事件处理系统。
/// </summary>
public static class EventDispose
{
/// <summary>
/// 存储不同事件类型和ID的事件处理程序的字典。
/// </summary>
private static readonly ConcurrentDictionary<EventType, Dictionary<long, Delegate>> EventDic = new();
/// <summary>
/// 用于监听器的唯一标识符。
/// </summary>
private static long _listenerId = 0;
/// <summary>
/// 为指定的事件类型添加新的监听器。监听器与唯一标识符关联。
/// </summary>
/// <typeparam name="T">事件负载的类型。</typeparam>
/// <param name="eventType">要监听的事件类型。</param>
/// <param name="action">事件触发时要调用的操作。</param>
/// <returns>包含事件类型和监听器的唯一标识符的元组。</returns>
public static (EventType, long) AddListener<T>(EventType eventType, Action<T> action)
{
long key = Interlocked.Increment(ref _listenerId);
// 获取或创建事件类型对应的字典
var value = EventDic.GetOrAdd(eventType, _ => new());
// 添加到内部字典
value[key] = action;
return (eventType, key);
}
/// <summary>
/// 为指定的事件类型添加新的监听器。监听器与唯一标识符关联。
/// </summary>
/// <param name="eventType">要监听的事件类型。</param>
/// <param name="action">事件触发时要调用的操作。</param>
/// <returns>包含事件类型和监听器的唯一标识符的元组。</returns>
public static (EventType, long) AddListener(EventType eventType, Action action)
{
long key = Interlocked.Increment(ref _listenerId);
// 获取或创建事件类型对应的字典
var value = EventDic.GetOrAdd(eventType, _ => new());
// 添加到内部字典
value[key] = action;
return (eventType, key);
}
/// <summary>
/// 将指定类型的事件广播给所有已注册的监听器。
/// </summary>
/// <param name="eventType">要广播的事件类型。</param>
/// <param name="arg">要传递给事件监听器的参数。</param>
/// <typeparam name="T">参数的类型。</typeparam>
public static void Broadcast<T>(EventType eventType, T arg)
{
if (!EventDic.TryGetValue(eventType, out var value))
{
Debug.LogWarning($"不存在事件类型{eventType}的监听,无法广播事件");
return;
}
foreach (var item in value)
{
if (item.Value is Action<T> action)
{
action.Invoke(arg);
}
else
{
Debug.LogError($"事件类型不匹配,请检查事件类型{eventType}的监听的参数类型是否和广播的参数类型一致");
}
}
}
/// <summary>
/// 将指定类型的事件广播给所有已注册的监听器。
/// </summary>
/// <param name="eventType">要广播的事件类型。</param>
public static void Broadcast(EventType eventType)
{
if (!EventDic.TryGetValue(eventType, out var value))
{
Debug.LogWarning($"不存在事件类型{eventType}的监听,无法广播事件");
return;
}
foreach (var item in value)
{
if (item.Value is Action action)
{
action.Invoke();
}
else
{
Debug.LogError($"事件类型不匹配,请检查事件类型{eventType}的监听的参数类型是否和广播的参数类型一致");
}
}
}
/// <summary>
/// 从指定的事件类型和键中删除监听器。
/// </summary>
/// <param name="eventType">要从中删除监听器的事件类型。</param>
/// <param name="key">与监听器关联的唯一键。</param>
public static void RemoveListener(EventType eventType, long key)
{
if (EventDic.TryGetValue(eventType, out var value) && value.ContainsKey(key))
{
value.Remove(key);
}
}
/// <summary>
/// 从指定的事件类型中删除监听器。
/// </summary>
/// <typeparam name="T">事件的类型。</typeparam>
/// <param name="eventType">事件类型。</param>
/// <param name="action">监听器操作。</param>
public static void RemoveListener<T>(EventType eventType, Action<T> action)
{
if (EventDic.TryGetValue(eventType, out var value))
{
foreach (var item in value)
{
if (item.Value.Equals(action))
{
value.Remove(item.Key);
break;
}
}
}
}
/// <summary>
/// 从指定的事件类型中删除监听器。
/// </summary>
/// <param name="eventType">事件类型。</param>
/// <param name="action">监听器操作。</param>
public static void RemoveListener(EventType eventType, Action action)
{
if (EventDic.TryGetValue(eventType, out var value))
{
foreach (var item in value)
{
if (item.Value.Equals(action))
{
value.Remove(item.Key);
break;
}
}
}
}
}
}
- 0
- 0
-
分享