众所周知,在软件开发中(尤其是大型工程里),事件系统是必不可少的,它能帮助我们解耦,使项目中的逻辑更好的分离开来,这里给出我自己的一份解决方案。
方案基于C#和ecs架构,在unity里用强烈推荐升级到2017或以上,新兼容的await语法简直是异步的福音。
首先必不可少的,事件类型的枚举
public enum MyEventType { NumericChange, }
监听者的基类:
public abstract class MyeventWatcher:Component { public abstract MyEventType[] EventTypes { get; set; } public void Awake() { foreach(var type in EventTypes) { Game.Scene.GetComponent<MyEventWatcherComponent>().AddEvent(type, this); } } public abstract Task RunEvent(MyEventType eventType, params object[] param); }
事件的管理:
public class MyEventWatcherComponent:Component { public static MyEventWatcherComponent Single; Dictionary<MyEventType, List<MyeventWatcher>> allWatchers = new Dictionary<MyEventType, List<MyeventWatcher>>(); public void Awake() { Single = this; } public void AddEvent(MyEventType eventType, MyeventWatcher myeventWatcher) { List<MyeventWatcher> list = null; allWatchers.TryGetValue(eventType,out list); if (list == null) { list = new List<MyeventWatcher>(); allWatchers.Add(eventType, list); } list.Add(myeventWatcher); } public void RemoveEvent(MyEventType eventType, MyeventWatcher myeventWatcher) { try { allWatchers[eventType].Remove(myeventWatcher); } catch(Exception e) { Log.Debug($"删除事件失败。 {e}"); } } public async Task RunEvent(MyEventType eventType, params object[] param) { List<MyeventWatcher> list = null; allWatchers.TryGetValue(eventType, out list); if (list == null) return; for (int i = 0; i < list.Count; i++) { await list[i].RunEvent(eventType,param); } } }
总的来说是非常简单易懂的架构,呼唤事件调用
MyEventWatcherComponent.Single.RunEvent(...)
即可,事件的监听则继承MyeventWatcher并实现相应的方法,当然,事件的参数要事先规定好,进行相应的类型转换。
一个简单的监听例子:
public class EventWactcherSample : MyeventWatcher { public override MyEventType[] EventTypes { get; set; } = new MyEventType[] { MyEventType.NumericChange }; public override async Task RunEvent(MyEventType eventType, params object[] param) { Log.Debug($"type:{param[0]},value:{param[1]}"); } }