EventCore 事件模块
特点
EventCore 是一个简单,易于使用的 Unity 事件管理方案 EventCore 基于 QFramework 的事件管理思路,独立演化而成 EventCore 能够自动进行注销事件操作,降低开发者的考虑角度 EventCore 仅需输入一次字符串,之后操作可以使用 IDE 自动代码补全 EventCore 可以快速监测关键数据的变化,触发事件
构建思路
核心类对象 EventBlock
整个事件系统的核心数据结构,作为流通在事件系统中的最小单元 定制类对象 BindableProperty
基于 EventBlock 的封装数据结构,用于监测基础数据变化的类,比如 int,float,string
文件结构
EventCore
Editor Example Prefab Scripts
快速使用,存在 ZFramework 架构的情况下
创建任意脚本,类名为 EventCoreUseTest
,修改 Mono
为 ZFController
使用 ZFramework
表现层接口(继承 Mono
不影响正常使用 EventCore
,ZFController
也继承 Mono
) 声明一个 EventBlock
变量,并在声明时初始化(推荐在此处直接初始化),原则上只要在注册任何方法之前进行名称赋值即可,EventBlock<T>
最多可以接受四个参数,代表有参数的委托模块。 然后在 Mono
的生命周期中,执行方法的注册,可以直接使用 Lambda
表达式 然后再使用 AutoUnsubscribeWhenGameObjectDestroyed(this)
方法,表示在传入的物体上挂载一个自动注销的方法,这个表示物体销毁时自动注销,避免造成空引用 另外还有AutoUnsubscribeWhenGameObjectOnDisable(gameObject)
方法,表示物体隐藏时自动注销,*该方法为仅作用一次 * 如果重新显示,需要重新注册新的方法 甚至可以传入其他物体,将该脚本的自动注销与其他物体关联。参数可以是 Mono
和 GameObject
在 Awake
和 Start
中都注册一个方法。 把这个脚本挂载到对应的物体上,启动 Unity ,按键 Y ,发送事件 声明 -> 注册 -> 订阅自动注销 -> 触发事件,整个流程已经完成 以下部分为演示
脚本演示
using System ;
using System. Collections ;
using System. Collections. Generic ;
using UnityEngine ;
using ZFramework. CoreComponent. EventCore ;
using ZFramework. Example ;
using ZFramework. Framework ;
public class EventCoreUseTest : ZFController
{
protected override IArchitecture GetArchitectureInterface ( )
{
return PointGame. Interface;
}
public EventBlock TestUse = new EventBlock ( ) . InitPrefixName ( nameof ( TestUse) ) ;
void Awake ( )
{
TestUse. Register ( ( ) =>
{
Debug. Log ( "测试 Awake " ) ;
} ) . AutoUnsubscribeWhenGameObjectDestroyed ( this ) ;
}
void Start ( )
{
TestUse. Register ( ( ) =>
{
Debug. Log ( "测试 Start 注册" ) ;
} ) . AutoUnsubscribeWhenGameObjectOnDisable ( gameObject) ;
}
void Update ( )
{
if ( Input. GetKeyDown ( KeyCode. Y) )
{
TestUse. SendEvent ( ) ;
}
}
}
截图演示
截图解析
左边包含了架构的层级(调用了架构核心就会自动生成),可以找到 EventCore
查看全局委托模块信息 右边则是 EventCoreUseTest
的面板信息,可以发现 TestUse
已经序列化,可以查看委托模块的名称,以及当前一共订阅了多少个方法 物体还挂载了两个注销委托的触发器 Trigger
脚本,开发者不用理会,无感自动注销 输出了两个日志,表示 Awake
和 Start
中注册均可,推荐在 Start
中
使用规则
只能使用委托块注册事件,仅提供这个方法,从编写阶段杜绝同名的可能 可以使用字符串名称和委托块发送事件 委托块的订阅数为 0 时会自动销毁对象,释放内存 在注册阶段选择是否需要进行自动注销 一个委托块不要同时存在手动注销和自动注销,如果不选择自动注销,则需要自定义注销时机
使用技巧推荐
全局事件中心
创建一个静态类,用来存放所有的 EventBlock
声明静态的 EventBlock
变量 所有变量声明在一个类中,且默认使用变量名转化为字符串,作为 EventBlock
的名称 从编写代码层面直接解决了可能不唯一的问题,因为不可存在同名的变量
using Sirenix. OdinInspector ;
using UnityEngine ;
using ZFramework. CoreComponent. EventCore ;
using ZFramework. Framework ;
namespace ZFramework. Example
{
public static class PointGameEventView
{
public static EventBlock CompleteClick = new EventBlock ( ) . InitPrefixName ( nameof ( CompleteClick) ) ;
public static EventBlock Example = new EventBlock ( ) . InitPrefixName ( nameof ( Example) ) ;
public static EventBlock< int > ExampleInt = new EventBlock< int > ( ) . InitPrefixName ( nameof ( ExampleInt) ) ;
public static EventBlock< int , string > ExampleIntString = new EventBlock< int , string > ( ) . InitPrefixName ( nameof ( ExampleIntString) ) ;
}
}
using Sirenix. OdinInspector ;
using UnityEngine ;
using ZFramework. CoreComponent. EventCore ;
using ZFramework. Framework ;
namespace ZFramework. Example
{
public class Test
{
void Start ( )
{
PointGameEventView. CompleteClick. Register ( ( ) =>
{
Debug. Log ( "测试 Start 注册" ) ;
} ) . AutoUnsubscribeWhenGameObjectOnDisable ( gameObject) ;
}
}
}
只读静态变量,避免后期误赋值
public static readonly EventBlock PressedA = new EventBlock ( ) . InitPrefixName ( nameof ( PressA) ) ;
void Start ( )
{
PressA. Register ( EventCoreDebug) ;
EventCore. Register ( PressedA, EventCoreDebug) ;
EventCore. Register ( PressedA, ( ) =>
{
Debug. LogFormat ( "这是一个 Lambda 表达式方法的订阅调用" ) ;
} ) ;
}
void Update ( )
{
if ( Input. GetKeyDown ( KeyCode. A) )
{
PressA. SendEvent ( ) ;
EventCore. SendEvent ( PressedA) ;
EventCore. SendEvent ( PressedA. GetName ( ) ) ;
}
}
BindableProperty 特殊委托模块 用于监测数据的变化
基于 EventBlock<T>
的封装,T 为泛型,可以使用任何 能够直接比较 的类 where T : IEquatable<T>
当监测数据的值发生改变时,自动触发事件,主要用于数据层的发送事件
简单示例
在注册时选择是否要立刻触发一次,以及是否要自动注销
public readonly BindableProperty< int > Number =
new BindableProperty< int > ( )
. InitValue ( 0 )
. InitEventName ( nameof ( Number) ) ;
public readonly BindableProperty< int > Number =
new BindableProperty< int > ( ) . InitProperty ( nameof ( Number) , 0 ) ;
void Start ( )
{
Number. Register ( num =>
{
Debug. LogFormat ( "当前 Number 数据的值为: {0} " , num) ;
} )
. JustTriggerOnce ( Number. Value)
. AutoUnsubscribeWhenGameObjectDestroyed ( gameObject) ;
Number. RegisterJustTriggerOnce ( num =>
{
CountText. text = $"当前 Number 数据的值为: { Number. Value } " ;
Debug. LogFormat ( " 使用 JustTriggerOnce 立刻触发一次委托模块,当前值为: {0} " , num) ;
} )
. AutoUnsubscribeWhenGameObjectDestroyed ( gameObject) ;
}
Example 示例场景
可以在 Example 文件夹中查看更加完整的示例
API 详细文档
EventCore
public static UnsubscribeRecord Register(EventBlock eventBlock, Action action)
注册委托模块 拥有多个重载,分别对应不同的 EventBlock 事件块
EventCore. Register ( EventBlock eventBlock, Action action) ;
public static void UnRegister(string eventBlockName, Action action)
注销委托模块中的单个订阅方法(直接使用字符串必须有前缀 ) 拥有多个重载,分别对应不同的 EventBlock 事件块
EventCore. UnRegister ( string eventBlockName, Action action) ;
EventCore. UnRegister ( EventBlock eventBlock, Action action) ;
public static void UnRegister(EventBlock eventBlock, Action action)
注销委托模块中的单个订阅方法(直接使用字符串必须有前缀 ) 拥有多个重载,分别对应不同的 EventBlock 事件块
EventCore. UnRegister ( string eventBlockName, Action action) ;
EventCore. UnRegister ( EventBlock eventBlock, Action action) ;
public static void SendEvent(string eventBlockName)
触发委托模块(直接使用字符串必须有前缀 ) 拥有多个重载,分别对应不同的 EventBlock 事件块
EventCore. SendEvent ( string eventBlockName, Action action) ;
EventCore. SendEvent ( EventBlock eventBlock, Action action) ;
public static void UnRegisterEventBlock<T>(T baseEventBlock)
EventCore. UnRegisterEventBlock ( string eventBlockName, Action action) ;
EventCore. UnRegisterEventBlock ( EventBlock eventBlock, Action action) ;
public static void UnRegisterEventBlock(string eventBlockName)
EventCore. UnRegisterEventBlock ( string eventBlockName, Action action) ;
EventCore. UnRegisterEventBlock ( EventBlock eventBlock, Action action) ;
public static Transform EnsureEventCore()
public static bool QueryDictionaryIsHas(string eventBlockName)
特殊调试情况用于查询全局事件字典中是否包含这个委托块
EventBlock
EventBlock 预设最多4个参数的方法 声明时设置 EventBlock 名称字符串
public string GetName()
var blockName = PressedA. GetName ( ) ;
public int GetActionCount()
var count = PressedA. GetActionCount ( ) ;
public EventBlock InitPrefixName(string name)
初始化名称,会自动附加前缀 针对不同的 EventBlock 方法名相同
public EventBlock PressedA = new EventBlock ( ) . InitPrefixName ( nameof ( PressedA) ) ;
public UnsubscribeRecord Register(Action action)
EventBlock 的直接注册方法 针对不同的 EventBlock 方法名相同
PressedS. Register ( EventCoreDebugOneParam) ;
public void UnRegister(Action action)
EventBlock 注销单个方法的订阅 针对不同的 EventBlock 方法名相同
PressedA. UnRegister ( EventCoreDebug) ;
public void UnRegisterEventBlockSelf()
EventBlock 快速注销自身块的所有方法订阅 针对不同的 EventBlock 方法名相同
PressedS. UnRegisterEventBlockSelf ( ) ;
public void SendEvent()
EventBlock 的事件触发 针对不同的 EventBlock 方法名相同
PressedA. SendEvent ( ) ;
BindableProperty 监测数据机制
BindableProperty<T> : IBindableProperty<T> where T : IEquatable<T>
基于 EventBlock<T>
的封装,T 为泛型,可以使用任何 能够直接比较 的类 where T : IEquatable<T>
public EventBlock<T> GetEventBlock()
获取 BindableProperty 中的 EventBlock
var block = Number. GetEventBlock ( ) ;
public string ToStringValue()
var str = Number. ToStringValue ( ) ;
public BindableProperty<T> InitProperty(string eventBlockName, T initialValue = default)
初始化 Number 数据,使用初始化方法,会使用 Int 的默认值作为初始值
public readonly BindableProperty< int > Number =
new BindableProperty< int > ( ) . InitProperty ( nameof ( Number) ) ;
public BindableProperty<T> InitValue(T initialValue)
public readonly BindableProperty< int > Count =
new BindableProperty< int > ( )
. InitValue ( 10 )
. InitEventName ( "Count" ) ;
public BindableProperty<T> InitEventName(string eventBlockName)
public readonly BindableProperty< int > Count =
new BindableProperty< int > ( )
. InitValue ( 10 )
. InitEventName ( "Count" ) ;
public void SetValueWithoutEvent(T newValue)
Number. SetValueWithoutEvent ( 10 ) ;
Number. Value = 20 ;
public UnsubscribeRecord<T> Register(Action<T> onValueChanged)
Number. Register ( num =>
{
Debug. LogFormat ( "当前 Number 数据的值为: {0} " , num) ;
} )
. JustTriggerOnce ( Number. Value)
. AutoUnsubscribeWhenGameObjectDestroyed ( gameObject) ;
public void UnRegister(Action<T> actionOne)
PressedA. UnRegister ( EventCoreDebug) ;
public IUnsubscribeRecord RegisterJustTriggerOnce(Action<T> actionOne)
Count. RegisterJustTriggerOnce ( num =>
{
CountText. text = $"当前 Count 数据的值为: { Count. Value } " ;
Debug. LogFormat ( " 使用 JustTriggerOnce 立刻触发一次委托模块,当前值为: {0} " , num) ;
} )
. AutoUnsubscribeWhenGameObjectDestroyed ( gameObject) ;
AutoUnsubscribeOnDestroyTrigger 自动注销机制
IUnsubscribeRecord. AutoUnsubscribeWhenGameObjectDestroyed ( UnityEngine. GameObject gameObject) ;
IUnsubscribeRecord. AutoUnsubscribeWhenGameObjectDestroyed ( MonoBehaviour mono) ;
PressedF. Register ( EventCoreDebugThreeParam) . AutoUnsubscribeWhenGameObjectDestroyed ( gameObject) ;
IUnsubscribeRecord. AutoUnsubscribeWhenGameObjectOnDisable ( UnityEngine. GameObject gameObject) ;
IUnsubscribeRecord. AutoUnsubscribeWhenGameObjectOnDisable ( MonoBehaviour mono) ;
PressedD. Register ( EventCoreDebugTwoParam) . AutoUnsubscribeWhenGameObjectOnDisable ( gameObject) ;
说明和扩展
简要提醒
有部分公开方法为 EventCore 内部搭建使用,可以不用理会 已经通过接口隔离限制部分方法,遵循直接给出的方法使用规则即可正常运转 EventCore 系统
参数限制
通常 4 个参数可以满足绝大部分需求 如有需要可以自定义扩展更多参数的委托模块
扩展步骤
根据 AbstractEventBlock<T>
的模板创建一个抽象类,继承 IBaseEventBlock
补充声明 UnityAction<T> mCachedAction
缓存 Action 和 UnityAction<T> mEventAction
事件 Action,以及T mData
根据需要的参数数量进行补充说明 根据 EventBlock<T>
创建一个实现类,补充完善 InitPrefixName(string name)
并返回EventBlock<T>
根据需要的参数数量进行补充 在 EventCore 中新增参数前缀常量 EventCore.TwoParamPrefix
即可正常使用