写这个主要是给自己梳理下这个框架 省的看一遍回头又忘了
加载dll都干了啥
Game.EventSystem.Add(DLLType.Model, typeof(Game).Assembly);
Game.EventSystem.Add(DLLType.Hotfix, DllHelper.GetHotfixAssembly());
代码不贴了 这里简单记下
遍历程序集 =>遍历所有类 =>找到所有标记了BaseAttribute及其子Attribute的类型 添加到types字典中 key=attributetype value =type
下面是目前框架内的所有标记有BaseAttribute的类型
然后遍历types =>找到标记了ObjectSystem的类 =>根据其实现的不同接口 添加到不同的字典中 key=type value=类的实例
比如下面这个
[ObjectSystem]
public class AppManagerComponentAwakeSystem : AwakeSystem<AppManagerComponent>
{
public override void Awake(AppManagerComponent self)
{
self.Awake();
}
}
object obj = Activator.CreateInstance(type);
switch (obj)
{
case IAwakeSystem objectSystem:
this.awakeSystems.Add(objectSystem.Type(), objectSystem);
break;
case IUpdateSystem updateSystem:
this.updateSystems.Add(updateSystem.Type(), updateSystem);
break;}
AwakeSystem 是实现了IAwakeSystem 接口的
同理找到所有标记 EventAttribute的type 添加到字典中 这个就一个类标记有该标签 暂时忽略
这些字典是挂在 Game上面的 算是全局变量 把标记了ObjectSystemAttribute标签的类的实例缓存起来做什么? 这里还看不出来
Game.Scene 挂载组件
Options options = Game.Scene.AddComponent<OptionComponent, string[]>(args).Options;
挂载组件会先创建一个component对象 然后添加到组件字典中 key=type value=component实例
创建component代码贴下
//创建组件
K component = ComponentFactory.CreateWithParent<K, P1>(this, p1, this.IsFromPool);
public static T CreateWithParent<T, A>(Component parent, A a, bool fromPool = true) where T : Component
{
Type type = typeof (T);
T component;
if (fromPool)
{
component = (T)Game.ObjectPool.Fetch(type);
}
else
{
component = (T)Activator.CreateInstance(type);
}
Game.EventSystem.Add(component);
component.Parent = parent;
if (component is ComponentWithId componentWithId)
{
componentWithId.Id = component.InstanceId;
}
Game.EventSystem.Awake(component, a);
return component;
}
注意这一句 Game.EventSystem.Add(component);
public void Add(Component component)
{
this.allComponents.Add(component.InstanceId, component);Type type = component.GetType();
if (this.loadSystems.ContainsKey(type))
{
this.loaders.Enqueue(component.InstanceId);
}if (this.updateSystems.ContainsKey(type))
{
this.updates.Enqueue(component.InstanceId);
}if (this.startSystems.ContainsKey(type))
{
this.starts.Enqueue(component.InstanceId);
}if (this.lateUpdateSystems.ContainsKey(type))
{
this.lateUpdates.Enqueue(component.InstanceId);
}
}
这里用到了上面缓存的类型,把挂载的组件的instanceid根据分类添加到了不同队列中 那这个队列中的缓存这些组件instanceid干嘛呢 这里不知道
最后一个操作 Game.EventSystem.Awake(component, a);
下面根据之前加载dll时候 缓存的类的实例 比如 上面贴的 AppManagerComponentAwakeSystem 然后调用 IAwake接口
所以所有 标记了ObjectSystem特性标签 && 实现IAwake接口的类 都会在实例化时候 调用它的Awake方法
public void Awake<P1>(Component component, P1 p1)
{
List<IAwakeSystem> iAwakeSystems = this.awakeSystems[component.GetType()];
if (iAwakeSystems == null)
{
return;
}foreach (IAwakeSystem aAwakeSystem in iAwakeSystems)
{
if (aAwakeSystem == null)
{
continue;
}
IAwake<P1> iAwake = aAwakeSystem as IAwake<P1>;
if (iAwake == null)
{
continue;
}try
{
iAwake.Run(component, p1);
}
catch (Exception e)
{
Log.Error(e);
}
}
}
之后再把刚刚创建的组件添加到component字典中
根据不同的应用程序类型加载不同组件
服务器类型大概分为 realm gate map location 等
每种服务器需要挂载的组件不同 根据配置文件配置 挂载不同组件
然后死循环调用 update方法
while (true)
{
try
{
Thread.Sleep(1);
OneThreadSynchronizationContext.Instance.Update();
Game.EventSystem.Update();
}
catch (Exception e)
{
Log.Error(e);
}
}
还记得上面标记绿色的疑问吗
下面就把之前缓存的instanceid取出去组件字典中获取组件
然后获取之前缓存的实现了IUpdateSystem 接口的实例 调用update方法
比如下面这个
[ObjectSystem]
public class TimerComponentUpdateSystem : UpdateSystem<TimerComponent>
{
public override void Update(TimerComponent self)
{
self.Update();
}
}
public void Update()
{
this.Start();
while (this.updates.Count > 0)
{
long instanceId = this.updates.Dequeue();
Component component;
if (!this.allComponents.TryGetValue(instanceId, out component))
{
continue;
}
if (component.IsDisposed)
{
continue;
}
List<IUpdateSystem> iUpdateSystems = this.updateSystems[component.GetType()];
if (iUpdateSystems == null)
{
continue;
}this.updates2.Enqueue(instanceId);
foreach (IUpdateSystem iUpdateSystem in iUpdateSystems)
{
try
{
iUpdateSystem.Run(component);
}
catch (Exception e)
{
Log.Error(e);
}
}
}ObjectHelper.Swap(ref this.updates, ref this.updates2);
}
在此前 会调用this.Start();方法
这里不贴了 和update逻辑一样的 就是在update前 调用component实现的IStartSystem接口方法
然后把instanceid放到了另一个队列中 this.updates2.Enqueue(instanceId); 为什么放到新队列中 不知道
框架每隔一毫秒就调用一次 标记有ObjectSystem标签 并实现了IUpdateSystem接口的类方法 并在此调用IStartSystem接口方法(如果有的话)