解析ET6的事件的使用
1.事件原理
1.Entry.cs
将所有反射类型添加到EventSystem中
//将dll中的反射类型添加到EventSystem中
Game.EventSystem.Add(CodeLoader.Instance.GetTypes());
2.EventSystem.cs
解析并处理所有EventAttribute标签的类存入allEvents字典,并使用publish分发事件
public void Add(Type[] addTypes)
{
this.allTypes.Clear();
foreach (Type addType in addTypes)
{
this.allTypes[addType.FullName] = addType;
}
this.types.Clear();
//获取所有继承BaseAttribute的类型
List<Type> baseAttributeTypes = GetBaseAttributes(addTypes);
foreach (Type baseAttributeType in baseAttributeTypes)
{
foreach (Type type in addTypes)
{
if (type.IsAbstract)
{
continue;
}
object[] objects = type.GetCustomAttributes(baseAttributeType, true);
if (objects.Length == 0)
{
continue;
}
//将同类型的特性存在一个字典
this.types.Add(baseAttributeType, type);
}
}
this.typeSystems = new TypeSystems();
//遍历所有ObjectSystemAttribute
foreach (Type type in this.GetTypes(typeof (ObjectSystemAttribute)))
{
object obj = Activator.CreateInstance(type);
if (obj is ISystemType iSystemType)
{
//将每个类打上ObjectSystem标签的类存字典
OneTypeSystems oneTypeSystems = this.typeSystems.GetOrCreateOneTypeSystems(iSystemType.Type());
oneTypeSystems.Add(iSystemType.SystemType(), obj);
}
}
this.allEvents.Clear();
//遍历所有EventAttribute
foreach (Type type in types[typeof (EventAttribute)])
{
IEvent obj = Activator.CreateInstance(type) as IEvent;
if (obj == null)
{
throw new Exception($"type not is AEvent: {obj.GetType().Name}");
}
Type eventType = obj.GetEventType();
if (!this.allEvents.ContainsKey(eventType))
{
this.allEvents.Add(eventType, new List<object>());
}
//将同一个eventType的类存入allEvents字典
this.allEvents[eventType].Add(obj);
}
}
public async ETTask Publish<T>(T a) where T : struct
{
List<object> iEvents;
//从字典中取出所有eventType的事件类
if (!this.allEvents.TryGetValue(typeof (T), out iEvents))
{
return;
}
using (ListComponent<ETTask> list = ListComponent<ETTask>.Create())
{
foreach (object obj in iEvents)
{
if (!(obj is AEvent<T> aEvent))
{
Log.Error($"event error: {obj.GetType().Name}");
continue;
}
//将事件类的run方法存入list
list.Add(aEvent.Handle(a));
}
try
{
//等待执行所有的run方法
await ETTaskHelper.WaitAll(list);
}
catch (Exception e)
{
Log.Error(e);
}
}
}
2.事件使用
1.EventType.cs
注册事件结构体
namespace EventType
{
//注册结构体
public struct ChangePosition
{
public Unit Unit;
}
}
2.自定义脚本(例子ChangePosition_SyncGameObjectPos.cs)
编写事件触发方法
/继承AEvent<struct>
public class ChangePosition_SyncGameObjectPos: AEvent<EventType.ChangePosition>
{
//重写Run方法
protected override async ETTask Run(EventType.ChangePosition args)
{
//args使用结构体内容
GameObjectComponent gameObjectComponent = args.Unit.GetComponent<GameObjectComponent>();
if (gameObjectComponent == null)
{
return;
}
Transform transform = gameObjectComponent.GameObject.transform;
transform.position = args.Unit.Position;
await ETTask.CompletedTask;
}
}
3.触发点(事件触发的地方)
//publish传入结构体并初始化参数
Game.EventSystem.Publish(new EventType.ChangePosition() { Unit = this }).Coroutine();