[迪迪教程-DataDriven插件使用-03] 有关框架的DDActor使用以及生命周期

迪迪教程-DataDriven插件使用-03 有关框架的DDActor使用以及生命周期

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

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

提要

有些地方真的的要用到了才会有深刻印象,有些坑真的踩到了才会知道有多深,爬了半天才发现原来旁边有梯子呢!

问题描述1

我当时的需求是要创建一系统动态生成的Actor, 所以就用了框架的资源加载系统(之前的随笔提到过),而框架中已经写好了一个DDActor类,于是我就基于这个类为父类创建了我自己的CEBasicActionActor类,在其中写一些处理Actor行为动作的逻辑代码。再基于这个CEBasicActionActor类我创建了不同的蓝图类,附给不同的StaticMesh。现在资源写好了,我就将其放在基于框架创建的资源字典PlayerData中。放在ClassWealthData下,类型是Actor。

然后再创建了一个框架Actor类, 用来管理这些资源的加载和实例化(具体就是使用框架的BuildSingleClassWealth或BuildMultiClassWealth接口),以及将实例化好的Actor设置它的动作什么的并注册到框架(具体是使用框架的RegisterToModule接口)。

而我们的框架的DDActor其实本来就已经有自动注册功能了,它是放在BeginPlay中的,以保证一个DDActor类拖放到场景中可以在原生UE4的生命周期中就自动注册到框架,所以在BuildSingleClassWealth或BuildMultiClassWealth之后,生成的Actor就已经随着BeginPlay的运行已经注册到框架了,而我们框架的是允许重复注册同一个对象的。

具体代码在DDOO中:

 void IDDOO::RegisterToModule(FName ModName, FName ObjName /*= FName()*/, FName ClsName /*= FName()*/)
 {
  //判断是否已经注册到框架了
  if (IDriver && IModule)
  return;
    ...
 }

可以看到,若重复注册,它直接就返回了,并没有报任何的信息,恰好当时我也没有注意到会有重复注册的问题,所以其实它在BeginPlay中就已经注册到框架了,而且使用的注册信息也是那边暴露在蓝图中的三个变量,如果没写的话,就自动填充。而我想要用另一组信息注册到框架,比如给它们一个指定的ClsName为“AtomClsName0”什么的。所以后面通过这个ClsName获取这些Actor自然就不会成功。比如我的使用框架的DestroyObject接口销毁这些ClsName为“AtomClsName0”的Actor就没有任何效果(压根就没有这些ClsName为“AtomClsName0”的Actor)。

解决方案1

我基于IDDOO创建了一个新的Actor类,命名为DDActor2。保留了释放函数,去除了自动注册到框架的代码,以及暴露给蓝图的三个变量,因为并不需要它们。这个类专门用于资源加载系统的ClassWealthData使用。

然后将CEBasicActionActor类的父类改成了这个DDActor2类。现在就不会自动注册到框架了。

为了下次可能的重复注册情况的出现,我在注册代码中添加了提示信息:

 void IDDOO::RegisterToModule(int32 ModIndex, FName ObjName /*= FName()*/, FName ClsName /*= FName()*/)
 {
  //判断是否已经注册到框架了
  if (IDriver && IModule)
  {
  DDH::Debug() << "Already registered. IObjectName: "<<IObjectName<<","<<"IClassName: "<< IClassName <<". [" << ObjName << "," << ClsName << "] can't register again" << DDH::Endl();
  return;
  }

问题描述2

在解决上面的问题的过程中其实还出现了另一个问题,是有关框架生命周期的。

我在CEBasicActionActor类中有一些控制Actor动作的布尔变量,比如说允许旋转的变量bRandomRotateEnabled。

如果允许了,它在它的DDTick生命周期函数中就会每次将Rotation加上一定值。

然后我在DDInit中就对这些布尔变量进行初始化,初始化为false。

然后我在这些Actor的Build之后,在将这些Actor注册到框架之后,设置其变量值。看起来没有什么问题,但其实它们的生命周期运行是在注册到框架之后的下一帧,我先对它的变量进行设置,下一帧往后运行到DDInit时又会对这些变量重新赋值,所以都会没有任何效果。

解决方案2

将布尔变量的初始化代码放在原生UE4的生命周期函数中或者是构造函数中,而不是框架的生命周期函数中,这样在BuildSingleClassWealth或BuildMultiClassWealth之后,这些变量已经初始化完毕,后面再更改就是有效的。不会出现运行框架生命周期时才初始化变量而覆盖前面的更改。

 

posted @ 2020-04-19 16:24  JFor  阅读(236)  评论(0编辑  收藏  举报