[迪迪教程-DataDriven插件使用-02] 框架生命周期详细解析

迪迪教程-DataDriven插件使用-02

NOTE 食用此文章的前提是已经看过迪迪老师的UE4教程UE4全反射零耦合框架开发坦克游戏

NOTE 本文放到博客里宽度有点容不下,可以复制到Markdown中观看

如果你是UE4新手,相信突然从框架开发转为用框架开发游戏都有点不适应吧,鉴于迪迪老师目前还没有出DataDriven框架的实战教程。而现在又想要用框架做开发。现在JFor就带你们从零开始使用DataDriven提供的功能搭建一款游戏。

再来说一下整个框架的生命周期是如何与UE4的Actor相配合的:

我们知道DDDriver是继承自AActor的,所以只要将其蓝图实例拖进场景,它就开始了它完整的UE4的Actor的生命周期,而整个DataDriven框架的生命周期就是由DDDriver的生命周期驱动的:

具体而言,涉及到四个函数:

ADDDriver();

virtual void PostInitializeComponents() override;

virtual void BeginPlay() override;

virtual void Tick(float DeltaTime) override;

挨个看:

  1. 构造函数ADDDriver()作用:

    • 实例化根组件 RootScene

    • 实例化中央模组组件 Center

就是我们图片中看到的黄色的这两个:

 

 

  1. PostInitializeComponents()中的动作:

    1. 注册自己到DDCommon

    • [DDDriver] UDDCommon::Get()->InitDriver(this);

    1. 填充所有模组组件的子模组数据ChildModule,同时对照枚举设定每个模组组件的模组ID,ModuleIndex

    • [DDDriver] Center->IterChangeModuleType(Center, ModuleType)

      • [DDCenterModule] Module->ChangeModuleType(ModType); #递归

        • [DDModule]

    1. 获取所有的模组组件,并按照每个模组的模组ModuleIndex的顺序填充到Center的所有模组组件数组ModuleGroup中

    • [DDDriver] Center->TotalGatherModule(ModuleType);

      • [DDCenterModule] GatherGroup.Push(Module); #递归

    1. 所有模组组件的DDMessage,DDModel,DDWealth的创建

    • [DDDriver] Center->IterCreateManager(Center);

      • [DDCenterModule] Module->CreateManager(); #递归

        1. UDDModule::CreateManager()中的动作:

          1. 实例化Model组件

          2. 实例化Message组件

          3. 实例化Wealth组件

          4. 避免销毁Model组件

          5. 避免销毁Message组件

          6. 避免销毁Wealth组件

          7. 为Model指定模组

            • [DDModule] Model->AssignModule(this);

              • [DDMM]/[DDModel]

          8. 为Message指定模组

            • [DDModule] Message->AssignModule(this);

              • [DDMM]/[DDMessage]

          9. 为Wealth指定模组

            • [DDModule] Wealth->AssignModule(this);

              • [DDMM]/[DDWealth]

  2. BeginPlay()中的动作:

    1. 注册GamePlay到框架(将GameInstance以及PlayerController注册到框架)

    • [DDDriver] RegisterGamePlay();

    1. 调用所有模组所有组件所有对象的Init函数

    • [DDDriver] Center->IterModuleInit(Center);

      • [DDCenterModule] Module->ModuleInit(); #递归

        1. UDDModule::ModuleInit()中的动作:

          1. 调用Model的Init函数

            • [DDModule] Model->ModelInit();

              • [DDModel] 暂时什么也没有做

          2. 调用Message的Init函数

            • [DDModule] Message->MessageInit();

              • [DDMessage] 暂时什么也没有做

          3. 调用Wealth的Init函数

            • [DDModule] Wealth->WealthInit();

              • [DDWealth] 暂时什么也没有做

  3. Tick(float DeltaTime)中的动作:

    1. 第一帧运行所有模组所有组件所有对象的BeginPlay函数

    • [DDDriver] Center->IterModuleBeginPlay(Center);

      • [DDCenterModule] Module->ModuleBeginPlay(); #递归

        1. UDDModule::ModuleBeginPlay()中的动作:

          1. 给Wealth指定资源

            • [DDModule] Wealth->AssignData(WealthData);

              • [DDWealth]

          2. 调用Model的BeginPlay函数

            • [DDModule] Model->ModelBeginPlay();

              • [DDModel] 暂时什么也没有做

          3. 调用Message的BeginPlay函数

            • [DDModule] Message->MessageBeginPlay();

              • [DDMessage] 从UDDCommon获取Controller

          4. 调用Wealth的BeginPlay函数

            • [DDModule] Wealth->WealthBeginPlay();

              • [DDWealth] 根据前面指定的资源,生成Object对象,Actor对象,Widget对象

    1. 第二帧开始循环运行所有模组所有组件所有对象的Tick函数

    • [DDDriver] Center->IterModuleTick(Center, DeltaTime);

      • [DDCenterModule] Module->ModuleTick(DeltaSeconds);

        1. UDDModule::ModuleTick(float DeltaSeconds)中的动作:

          1. 调用Model的Tick函数

            • [DDModule] Model->ModelTick(DeltaSeconds);

              1. UDDModel::ModelTick(float DeltaSeconds)中的动作:

                1. 调用对象的Tick函数

                  • [DDModule] ObjectTickGroup[i]->DDTick(DeltaSeconds);

                    • [DDOO]/[xxx] DDTick(float DeltaSeconds)

                2. 调用ActiveLife函数从而一次一个地执行对象Tick函数之前的生命周期函数

                  • [DDModule] ObjectActiveGroup[i]->ActiveLife()

                    1. IDDOO::ActiveLife()中的动作:

                      1. 调用对象的Init函数

                        • [DDOO]/[xxx] DDInit();

                      2. 调用对象的Loading函数

                        • [DDOO]/[xxx] DDLoading();

                      3. 调用对象的Register函数

                        • [DDOO]/[xxx] DDRegister();

                      4. 调用对象的Enable函数

                        • [DDOO]/[xxx] DDEnable();

                3. 调用对象的Release函数

                  • [DDModule] ObjectReleaseGroup[i]->DDRelease();

                    • [DDOO]/ 注销所有协程, 延时以及按键事件

                4. 调用对象的Destroy函数从而一次一个地执行对象Release函数之前的生命周期函数

                  • [DDModule] ObjectDestroyGroup[i]->DestroyLife()

                    1. IDDOO::DestroyLife()中的动作:

                      1. 调用对象的DDDisable函数

                        • [DDOO]/[xxx] DDDisable();

                      2. 调用对象的DDUnRegister函数

                        • [DDOO]/[xxx] DDUnRegister();

                      3. 调用对象的DDUnLoading函数

                        • [DDOO]/[xxx] DDUnLoading();

          2. 调用Wealth的Tick函数

            • [DDModule] Wealth->WealthTick(DeltaSeconds);

              • [DDWealth] 处理各种类型的 资源加载栈

          3. 调用Message的Tick函数

            • [DDModule] Message->MessageTick(DeltaSeconds);

              • [DDMessage] 处理协程系统 和 延时系统

总结:

BeginPlay函数之前

在BeginPlay函数之前进行的是DataDriven框架的创建工作,将顶层DDDriver与第二层DDModule, 第二层DDModule与第三层 DDModel、DDMessage、DDWealth的框架进行了创建。

BeginPlay函数

在BeginPlay函数之中进行的是第二层DDModule以及第三层DDModel、DDMessage、DDWealth的Init工作,不过初始化的内容暂时是空的。(一些对象实例因为也是在场景中,所以其BeginPlay函数会在同一时间被调用,其中有注册到框架的调用)

Tick函数的第一帧

在Tick函数的第一帧进行的是第二层DDModule以及第三层DDModel、DDMessage、DDWealth的BeginPlay工作,主要是DDWealth将一些对象资源注册到框架。

Tick函数的第二帧及以后

在Tick函数的第二帧进行的是第二层DDModule以及第三层DDModel、DDMessage、DDWealth以及最底层的对象(可以是从UE4的BeginPlay中注册进框架的,也可以是从DDWealth中注册进框架的,而且后面还可以动态添加)的tick工作。在这个tick里面则实现了对象的完整生命周期。

posted @ 2020-04-09 20:33  JFor  阅读(324)  评论(0编辑  收藏  举报