ET游戏框架整理笔记1: 从main函数说起

摘要:
写这个主要是给自己梳理下这个框架省的看一遍回头又忘了加载dll都干了啥Game.EventSystem.Add(DLLType.Model,typeof(Game).Assembly);Game.EventSystem.Add(DLLType.Hotfix,DllHelper.GetHotfixAssembly());代码不贴了这里简单记下遍历程序集=˃遍历所有类=˃找到所有标记了BaseAttr

写这个主要是给自己梳理下这个框架 省的看一遍回头又忘了

加载dll都干了啥

Game.EventSystem.Add(DLLType.Model, typeof(Game).Assembly);
Game.EventSystem.Add(DLLType.Hotfix, DllHelper.GetHotfixAssembly());

代码不贴了 这里简单记下

遍历程序集 =>遍历所有类 =>找到所有标记了BaseAttribute及其子Attribute的类型 添加到types字典中 key=attributetype value =type

下面是目前框架内的所有标记有BaseAttribute的类型

image

然后遍历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接口方法(如果有的话)

免责声明:文章转载自《ET游戏框架整理笔记1: 从main函数说起》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Redis数据类型,持久化,回收策略ANSI、ASCII、Unicode和UTF-8编码下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

MySQL外键设置中的的 Cascade、NO ACTION、Restrict、SET NULL

1 . cascade方式  在父表上update/delete记录时,同步update/delete掉子表的匹配记录     2. set null方式 在父表上update/delete记录时,将子表上匹配记录的列设为null要注意子表的外键列不能为not null   3. No action方式 如果子表中有匹配的记录,则不允许对父表对应候选键进行...

unity中的update、Lateupdate和FixedUpdate。

MonoBehaviour.Update更新 当MonoBehaviour启用时,其Update在每一帧被调用。 MonoBehaviour.FixedUpdate固定更新 当MonoBehaviour启用时,其 FixedUpdate在每一帧被调用。 处理Rigidbody时,需要用FixedUpdate代替Update。例如:给刚体加一个作用力时,你必...

CentOS 命令大全

系统 # uname -a               # 查看内核/操作系统/CPU信息 # head -n 1 /etc/issue   # 查看操作系统版本# cat /proc/cpuinfo      # 查看CPU信息# hostname               # 查看计算机名# lspci -tv              # 列...

SQL SERVER锁(LOCK)知识及锁应用

提示:这里所摘抄的关于锁的知识有的是不同sql server版本的,对应于特定版本时会有问题。 一 关于锁的基础知识 (一). 为什么要引入锁 当多个用户同时对数据库的并发操作时会带来以下数据不一致的问题: ◆丢失更新 A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果,比如订票系统 ◆脏读 A用户修改了数据,随后B用户又...

在Linux下安装ADT

现在网络上的好像都是旧版的,我也写一下。 首先说一下eclipse的版本。我们知道,Java EE是企业版,我前面下载Eclipse时还考虑我使用Java SE能否使用。其实可以! 第一步:点开Install New Software来安装插件 第二步:在type or select a site的地方写下: https://dl-ssl.google...

Eclipse 配置SVN

首先,检查一下你的Eclipse装了SVN插件没 依次点击:Window -> show view -> other 如果你看到的和我一样,就不用装了!!!! 没有就走这一步!!! 依次点击: Help -> Install new software 把这个网址拷到地址栏:http://subclipse.tigris.org/upda...