这个事件模块有些GF的味道。又或许是我学了GF之后看啥都像GF罢。
虽然在教程新建项目的时候我就发现Unity hub 的项目页面里有Star Force的身影。
GameEventArgs
GameEventArgs 继承 System.EventArgs 作为事件传参数的参数类, 这很正常不是吗?
但是教程里Args是这样设计的。
public abstract class GameEventArgs : System.EventArgs
{
public abstract int Id { get; }
public abstract void Clear();
}
多了一个ID 和 Clear方法,和GF的GameEventArgs一样欸。
GameFramwork是如何设计的
举例说明, 下面是GF的一个事件例子。
public class ExampleEventArgs : GameEventArgs
{
//将事件id与具体的数据类绑定
public static int EventId => typeof(ExampleEventArgs).GetHashCode();
public override int Id => EventId;
//要传递的数据
public object CustomData { get; set; }
// 引用池需要的无参构造函数
public ExampleEventArgs() => CustomData = null;
//从引用池获取的快捷方法
public static ExampleEventArgs Create(object customData)
{
var args = ReferencePool.Acquire<ExampleEventArgs>();
args.CustomData = customData;
return args;
}
//引用池对象的清理函数
public override void Clear()
{
CustomData = null;
}
}
- GF里的ID是事件类型的哈希,作为唯一ID用来标识方法类型用于注册的。
- GF的Clear方法是配合其引用池的,用于清空引用方便引用池回收重复利用的。
那么这个智械危机教程是怎么做的呢?
答案是唯一是引用是其父类,这俩纯摆设。
这个ID不用来注册那么事件是怎么注册的呢?
答案是额外定义了事件枚举作为事件ID。
综上,上面Args里的俩个参数完全没啥用,抄了,但没完全抄。
EventPool
定义了一个EventPool作为事件池,提供事件订阅和广播功能。
核心是一个int , Eventhandler字典。为啥不用事件枚举作为key,这样还不用转换?
private Dictionary<int, EventHandler<T>> _dicEventHandlers = new Dictionary<int, EventHandler<T>>();
剩下的四个方法分别是
- Check 检查事件
- Subscribe 注册事件
- Unsubscribe 取消注册
- Fire 广播事件
比较基础就不贴代码了。
EventManager
EventManager是一个静态单例, 包装了一下上面的EventPool,提供全局访问点。
为什么不直接把EventPool集成到EventManager中?
当然是方便设立局部事件池啦。
比如UI模块,不是有很多UI事件嘛?就可以在UI模块New一个事件池专门管理UI事件。
又比如说玩家,玩家单位通常也会有很多和玩家相关事件需要订阅和方法,这时候也可以new一个局部事件池来管理对应的事件。
闲话
能看出是简化了GF的事件池,砍掉了GF事件池里例如多线程锁相关的设计,但是很明显没简化到位。
PS : 我个人认为GF事件池多线程那部分设计才是亮点设计。
这里贴一个相关的赏析贴。
GameFramework源码赏析-03事件 - 知乎 (zhihu.com)