This commit is contained in:
2026-07-07 03:34:56 +08:00
parent e7891d7e00
commit ecb20cf370
81 changed files with 2108 additions and 293 deletions
@@ -0,0 +1,66 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
namespace Architecture.Core
{
/// <summary>
/// 无参事件通道(ScriptableObject 资产)。
/// 系统 / UI 在 Inspector 中拖入同一个资产实例即可实现解耦通信,
/// 彻底替代 static Action 事件与单例方法调用。
/// 注意:资产实例是项目级资源,跨场景天然存活,无需 DontDestroyOnLoad。
/// </summary>
[CreateAssetMenu(menuName = "Architecture/Events/Game Event", fileName = "NewGameEvent")]
public class GameEvent : ScriptableObject
{
private readonly List<GameEventListener> _listeners = new List<GameEventListener>();
private event System.Action _codeListeners;
public void Raise()
{
// Inspector 监听器(设计师配置的 UnityEvent 响应)优先于代码监听器触发,
// 保证表现层(UI 动画/音效)在逻辑层之前响应事件。
for (int i = _listeners.Count - 1; i >= 0; i--)
_listeners[i].OnEventRaised();
_codeListeners?.Invoke();
}
/// <summary>Inspector 监听器(GameEventListener 组件)注册。</summary>
public void RegisterListener(GameEventListener listener)
{
if (!_listeners.Contains(listener)) _listeners.Add(listener);
}
public void UnregisterListener(GameEventListener listener)
{
if (_listeners.Contains(listener)) _listeners.Remove(listener);
}
/// <summary>代码监听器(Action)注册,便于 MonoBehaviour 在 OnEnable 中订阅,
/// 是替换 static Action 事件的主要入口。</summary>
public void Register(System.Action listener)
{
if (listener != null) _codeListeners += listener;
}
public void Unregister(System.Action listener)
{
if (listener != null) _codeListeners -= listener;
}
}
/// <summary>
/// 无参事件监听器(设计师友好,纯 Inspector 配置)。
/// 监听某个 GameEvent,触发时调用绑定的 UnityEvent 响应。
/// </summary>
public class GameEventListener : MonoBehaviour
{
[SerializeField] private GameEvent _event;
[SerializeField] private UnityEvent _response;
private void OnEnable() => _event?.RegisterListener(this);
private void OnDisable() => _event?.UnregisterListener(this);
public void OnEventRaised() => _response?.Invoke();
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: Dy4XvCj+VnPPG8II9z1gbnWGNyb39F6pQKS/CfIEjQntIaaEOm2XcP4=
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
namespace Architecture.Core
{
/// <summary>
/// 带载荷的泛型事件通道。用于在调用方之间传递数据,而无需 static 事件或单例。
/// 具体类型(IntEvent / FloatEvent 等)可在 Inspector 右键 Create。
/// 系统内部订阅用 event.Register(Action&lt;T&gt;);设计师驱动用对应 *EventListener 组件。
/// </summary>
public abstract class GameEvent<T> : ScriptableObject
{
private readonly List<Action<T>> _listeners = new List<Action<T>>();
public void Raise(T payload)
{
for (int i = _listeners.Count - 1; i >= 0; i--)
_listeners[i]?.Invoke(payload);
}
public void Register(Action<T> listener)
{
if (!_listeners.Contains(listener)) _listeners.Add(listener);
}
public void Unregister(Action<T> listener)
{
if (_listeners.Contains(listener)) _listeners.Remove(listener);
}
}
[CreateAssetMenu(menuName = "Architecture/Events/Int Event", fileName = "NewIntEvent")]
public class IntEvent : GameEvent<int> { }
[CreateAssetMenu(menuName = "Architecture/Events/Float Event", fileName = "NewFloatEvent")]
public class FloatEvent : GameEvent<float> { }
[CreateAssetMenu(menuName = "Architecture/Events/Vector3 Event", fileName = "NewVector3Event")]
public class Vector3Event : GameEvent<Vector3> { }
[CreateAssetMenu(menuName = "Architecture/Events/String Event", fileName = "NewStringEvent")]
public class StringEvent : GameEvent<string> { }
[CreateAssetMenu(menuName = "Architecture/Events/GameObject Event", fileName = "NewGameObjectEvent")]
public class GameObjectEvent : GameEvent<GameObject> { }
// ===== 带载荷的监听器组件(Inspector 驱动)=====
public class IntEventListener : MonoBehaviour
{
[SerializeField] private IntEvent _event;
[SerializeField] private UnityEvent<int> _response;
private void OnEnable() => _event?.Register(Respond);
private void OnDisable() => _event?.Unregister(Respond);
private void Respond(int v) => _response?.Invoke(v);
}
public class FloatEventListener : MonoBehaviour
{
[SerializeField] private FloatEvent _event;
[SerializeField] private UnityEvent<float> _response;
private void OnEnable() => _event?.Register(Respond);
private void OnDisable() => _event?.Unregister(Respond);
private void Respond(float v) => _response?.Invoke(v);
}
public class Vector3EventListener : MonoBehaviour
{
[SerializeField] private Vector3Event _event;
[SerializeField] private UnityEvent<Vector3> _response;
private void OnEnable() => _event?.Register(Respond);
private void OnDisable() => _event?.Unregister(Respond);
private void Respond(Vector3 v) => _response?.Invoke(v);
}
public class GameObjectEventListener : MonoBehaviour
{
[SerializeField] private GameObjectEvent _event;
[SerializeField] private UnityEvent<GameObject> _response;
private void OnEnable() => _event?.Register(Respond);
private void OnDisable() => _event?.Unregister(Respond);
private void Respond(GameObject v) => _response?.Invoke(v);
}
/// <summary>
/// 字符串事件监听器组件。补齐 Int/Float/Vector3/GameObject 之后遗漏的 String 通道监听器,
/// 使策划能在 Inspector 里为 StringEvent 连线响应(例如传递场景名、提示文本)。
/// </summary>
public class StringEventListener : MonoBehaviour
{
[SerializeField] private StringEvent _event;
[SerializeField] private UnityEvent<string> _response;
private void OnEnable() => _event?.Register(Respond);
private void OnDisable() => _event?.Unregister(Respond);
private void Respond(string v) => _response?.Invoke(v);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: Wn0Y43n4BSqQmCBSQfcVumlArfA4ONJNN2iHuAFNyRze987Ocx2MGyY=
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: