zoukankan      html  css  js  c++  java
  • ET游戏框架整理笔记1: 从main函数说起

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

    加载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接口方法(如果有的话)

  • 相关阅读:
    .NET Framework 4.5 中新增的'可移植类库'功能
    使用visual sutdio右键菜单封装字段
    Visual Studio 2008的“组织using”菜单
    HTML5与HTML4的区别
    【百度地图API】如何制作公交线路的搜索?如331路
    【百度地图API】如何给自定义覆盖物添加事件
    【百度地图API】如何制作自定义样式的公交导航结果面板?
    【百度地图API】如何制作可拖拽的沿道路测距
    透过【百度地图API】分析双闭包问题
    【百度地图API】如何用圆形搜索获取中心点周围100米内全部关键点?如天安门附近所有的餐厅、加油站、宾馆、大厦等
  • 原文地址:https://www.cnblogs.com/xtxtx/p/11167334.html
Copyright © 2011-2022 走看看