[迪迪教程-DataDriven插件实战-01] 框架原理和使用

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

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

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

先来说一下框架的各个对象是如何注册进框架的:

DDObject文件夹下:

概括:DDObject文件夹下一些类的实例通过手动填写的额外信息指定要注册到框架的哪个模组组件DDModule下。

原理:

DDObject文件夹中的所有的文件都是继承自IDDOO以及另一个UE4内置类,可以按照这个内置类的类型对这些类进行分类,如:

  • 此内置类是UE4提供的AActor类以及子类(暂时称为A类)

    ADDActor继承自IDDOO和AACtor #

    ADDPawn继承自IDDOO和APawn #

    ...

  • 此内置类是UE4提供的UObject类以及子类(暂时称为B类)

    UDDObject 继承自IDDOO和UObject

    UDDGameInstance 继承自IDDOO和UGameInstance

    UDDSceneComponent 继承自 IDDOO和USceneComponent #

    UDDActorComponent 继承自IDDOO和UActorComponent #

    UDDUserWidget 继承自IDDOO和UUserWidget

其中IDDOO是DataDriven框架的,而AActor、APawn、UGameInstance等是UE4提供的内置类。这就是这些类同时被两套框架所拥有的机制了(多继承)。

但是光有类文件不行,我们还需要将实例的类对象注册到框架中去。我们将一个Actor拖放到场景中到UE4就可以获取它注册到自己的框架中这是UE4帮我们实现好的,我们无需关注底层实现,而我们的DataDriven框架则规定了需要类的实例提供一些额外的信息来注册到DataDriven框架。(在其BeginPlay函数中会自动使用这些信息来注册到DataDriven框架)

可以注意到,这些类中的一些类向编译器暴露了三个变量:

 public:
 
  //模组名字,如果为空,说明要手动指定,不为空就是自动指定
  UPROPERTY(EditAnywhere, Category = "DataDriven")
  FName ModuleName;
  //对象名字,如果为空,说明要手动指定,不为空就是自动指定
  UPROPERTY(EditAnywhere, Category = "DataDriven")
  FName ObjectName;
  //类名字,如果为空,说明要手动指定,不为空就是自动指定
  UPROPERTY(EditAnywhere, Category = "DataDriven")
  FName ClassName;

结果:(以DDPawn为例)

  1. 继承DDPawn类创建一个蓝图类。打开此蓝图类你会看到:

  2. 就是根据这三个可填的信息注册到DataDriven框架。当你将蓝图拖放到场景中时,此蓝图会同时被注册到UE4和DataDriven两个框架。(如何填可以看DDCore中的DDDriver介绍)

DDCore文件夹下:

概括:DDDriver使用UE4的Actor与Component之间的层级关系实现了DDDriver与DDModule的层级关系,增加了一个枚举保存了各模组组件DDModule的位置信息。

原理:

DDCore文件夹下的DDDriver是我们要关注的焦点。它同样是继承自AActor。但它并没有同时继承自IDDOO。因为为了重新定义自己的生命周期,所有继承自IDDOO的这些类都主动禁止了各自的tick,如:

 ADDPawn::ADDPawn()
 {
  // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
  PrimaryActorTick.bCanEverTick = false;
 
 }

而使用IDDOO定义的生命周期函数。现在需要一个驱动这些自定义生命周期函数的AActor,它就是DDDriver,所以它当然不用继承IDDOO,其各生命周期函数也必须是完备的,当然这一点已经是AActor自带的。如果说原来的是每个轮子都有一个电动机的话,现在就是只有一个轮子有一个电动机,其他轮子的动力则由这个轮子带动。

作为整个DataDriven框架的驱动器,DDDriver负责的并不是自己要注册到框架的哪个地方,而是自己来搭建的这个框架的结构。它也提供了三个变量,其中前两个会在代码中创建并指定,只有最后一个变量需要手动指定:

 public:
 
  UPROPERTY(EditAnywhere, NoClear, BlueprintReadOnly, Category = "DataDriven")
  USceneComponent* RootScene;
 
  UPROPERTY(EditAnywhere, NoClear, BlueprintReadOnly, Category = "DataDriven")
  UDDCenterModule* Center;
 
  //模组对应的枚举名字
  UPROPERTY(EditDefaultsOnly, Category = "DataDriven")
  FName ModuleType;

结果:

  1. 继承自DDDriver创建一个蓝图(我命名为GameDriver)。打开此蓝图类你会看到(我选中的黄色的部分):

    其中GameDriver就是这个Actor本身。

    RootScene是在代码中创建并指定的一个USceneComponent实例,仅仅充当根组件的作用。

    Center也是在代码中创建并指定的,它是UDDCenterModule的的实例(UDDCenterModule继承自UDDModule继承自USceneComponent)。负责沟通GameDriver和其上各组件,(包括它本身)。

     

     

  2. 你可以在Center组件的同级创建你自己的DDModule。上面我创建了另外的5个DDModule,分别命名为了HUD、Data...(上图未选中部分)

  3. 这些DDModule的实例其实是框架中用来分类的第一层,它们继承自USceneComponent的目的是为了可以当作组件一个一个可视化地添加到DDDriver这个AActor上,这样的层级关系是UE4提供好的,但并没有在组件下再加Actor的实现,我们的框架要想将这第一层与第二层以及最底层的对象联系起来,同样需要额外的关联机制,我们使用的就是枚举:在DDGame文件夹下的DGTypes.h文件中,定义一个自己的枚举:

     //示例模组枚举, 模组约定, 如果要使用DataDriven本身的UI框架, 请一定要把HUD模组放在第二位, UIFrame框架管理器始终在HUD模组下
     UENUM()
     enum class ECEModule : uint8
     {
      Center = 0,    //中央模组, 约定放在第一位
      HUD,           //UI模组, 约定放在第二位, UI框架会直接使用序号1去获取HUD模组, 如果不使用UI框架, 不需要强制在第二位
      Data,          //数据模组
      Player,        //玩家模组
      NPC,           //NPC模组
      Bots,          //敌对模组
     };
  4. 这个枚举可以说就是路由器,是模组组件名字与位置的路由器,在这个蓝图的Details面板下就可以指定我们在代码中声明的那个第三个变量ModuleType的值为这个枚举的名字“ECEModule”。(GameDriver可以根据这个名字获取到这个枚举)

  5. DDDriver的实例创建和搭建的基本框架到这里就配置好了。

  6. 还记得之前DDObject文件夹下的DDPawn实例注册到框架要填写的信息吗,第一个就是ModuleName,它其实就是指明该对象实例要注册到哪个DDModule实例下,这里就可以填”NPC"、“Bots”、“HUD”等等。注册函数代码会使用这里的ModuleName的值对照着GameDriver中保存的那个枚举,指明一下自己注册到的DDModule实例的ID, 如你指定为Center,那你保存的ModuleIndex就会设置为0,指定为HUD,那就是1等等。

    这个ID蕴含的信息其实是该模组组件在RootScene下的位置,这样只要知道要访问的模组的名字(如“Center”),就可以直接找到这个模组组件(RootScece的第0个子组件)。这也是我们的实现的零耦合反射系统 的基础所在。(我们不使用指针可以去除耦合,我们使用int32类型的ModuleIndex保存模组组件的位置可以更加方便地找到模组)

待更新

posted @ 2020-04-08 19:32  JFor  阅读(...)  评论(...编辑  收藏