UE4运用C++和框架开发坦克大战教程笔记(七)(第20~22集)
20. 框架对象类
接下来我们要创建剩余的所有要用到的框架 Object 类。
选择目标模块为 DataDriven (Runtime),在 Public/DDObject/ 路径下创建以下 C++ 类:(如果有弹窗则选 No)
创建 ActorComponent,取名为 DDActorComponent。
创建 AIController,取名为 DDAIController。
创建 CameraActor,取名为 DDCameraActor。
创建 Character,取名为 DDCharacter。
创建 GameInstance,取名为 DDGameInstance。
创建 GameModeBase,取名为 DDGameModeBase。
创建 GameStateBase,取名 DDGameStateBase。
创建 HUD,取名 DDHUD。
创建 LevelScriptActor,取名 DDLevelScriptActor。
创建 Pawn,取名 DDPawn。
创建 PlayerCameraManager,取名 DDPlayerCameraManager。
创建 PlayeController,取名 DDPlayerController。
创建 PlayerState,取名 DDPlayerState。
创建 SceneComponent,取名 DDSceneComponent。
创建 WheeledVehicle,取名 DDWheeledVehicle。
创建完以上所有类后,不用急着编译代码,为了让它们变成受框架控制的类,给它们执行如下操作:
- 引入 DDOO 头文件,继承 DDOO 接口。
- 去掉
Tick()相关的函数,添加构造函数并在里面关闭原生 Tick(如果原本有Tick()相关内容的话)。 - 添加三个 FName 变量。
- 在
BeginPlay()里自动注册。(没有BeginPlay()就重写一个) - 重写
DDRelease()(这一步取决于类是否需要自动销毁)。
DDActorComponent 类的示例如下:
DDActorComponent.h
#include "DDOO.h" // 引入头文件
#include "DDActorComponent.generated.h"
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class DATADRIVEN_API UDDActorComponent : public UActorComponent, public IDDOO // 继承接口
{
GENERATED_BODY()
public:
UDDActorComponent();
// 重写释放函数
virtual void DDRelease() override;
public:
// 模组名字,如果为空,说明要手动指定,不为空就是自动指定
UPROPERTY(EditAnywhere, Category = "DataDriven")
FName ModuleName;
// 对象名字,如果为空,说明要手动指定,不为空就是自动指定
UPROPERTY(EditAnywhere, Category = "DataDriven")
FName ObjectName;
// 类名字,如果为空,说明要手动指定,不为空就是自动指定
UPROPERTY(EditAnywhere, Category = "DataDriven")
FName ClassName;
// 去掉 TickComponent()
};
DDActorComponent.cpp
UDDActorComponent::UDDActorComponent()
{
PrimaryComponentTick.bCanEverTick = false; // 关闭原生 Tick
// 设置允许销毁(只有 Component 类需要)
bAllowAnyoneToDestroyMe = true;
}
void UDDActorComponent::BeginPlay()
{
Super::BeginPlay();
// 自动注册
RegisterToModule(ModuleName, ObjectName, ClassName);
}
void UDDActorComponent::DDRelease()
{
IDDOO::DDRelease();
// 从组件中删除自己,并标记为准备被 gc 回收(只有 Component 类需要)
DestroyComponent();
}
// 删除 TickComponent()
不过有些类在上面的操作上有差异,以下是注意事项:
- 只有 Component 类需要在构造函数里设置允许销毁;在
DDRelease()里调用DestroyComponent()。 - 除了 Component 以外的类,它们的
DDRelease()内的释放语句替换如下:
// 能调用这个方法那么一定是注册到了框架,获取的世界一定不为空
GetDDWorld()->DestroyActor(this);
- 需要重写
DDRelease()的类:DDActorComponent、 DDCameraActor、DDCharacter、DDPawn、DDSceneComponent、DDWheeledVehicle 。其他的不需要。(需要注意的是类似 DDObject、DDUserWidget 等先前已经写过的类就不列出来了) - 除了 Component 以外的类,关闭原生 Tick 的调用对象是 PrimaryActorTick,示例如下:
PrimaryActorTick.bCanEverTick = false;
- DDCharacter 和 DDPawn 除了
Tick()要去掉以外,绑定输入的SetupPlayerInputComponent()也要去掉,因为后续会专门写一套绑定方法。 - DDGameInstance 只需要引入 DDOO 头文件并继承 DDOO 接口就行了。
- DDPlayerController 需要开启 Tick,示例如下:
DDPlayerController.cpp
ADDPlayerController::ADDPlayerController()
{
// 必须开启 Controller 或者 Character 的帧函数才能够检测按键,本框架只开启 Controller 的
PrimaryActorTick.bCanEverTick = true;
}
上面的内容如果读者不放心的话建议查看 DataDriven 源码或者根据视频对比着填写。
刚刚创建的载具类依赖 PhysXVehicles 模块,但是在 4.26~4.27 版本里这个模块即将被 ChaosVehicles 取代,不过后者在 UE4 处于 Beta 版,可能会在功能上出现不稳定性。
此外,笔者发现有用户遇到过 4.26~4.27 版本使用 ChaosVehicles 时出现问题:UE4.26 UE4.27 Chaos Vehicle 车辆运动组件无法控制车轮 不能正常使用的问题
需要在源码版引擎才能解决。衡量之下笔者决定还是采用旧版的 PhysXVehicles。
来到插件的 .Build.cs 文件,添加以下依赖:
DataDriven.Build.cs
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"UMG",
// 添加下面三个模块依赖
"AIModule",
"GameplayTasks",
"PhysXVehicles",
}
);
因为 DataDriven 本身是一个插件,PhysXVehicles 也是插件,插件间互相引用需要在 .uplugin 添加说明代码:
DataDriven.uplugin
{
"Modules": [
{
"Name": "DataDriven",
"Type": "Runtime",
"LoadingPhase": "Default"
}
], // 记得加这个逗号
// 添加下面这些代码
"Plugins": [
{
"Name": "PhysXVehicles",
"Enabled": true
}
]
}
PlayerController 经常会被调用到,我们可以把 DDPlayerController 注册到 DDCommon,以便可以在任何地方获取到。
再添加两个暂停游戏相关的方法。
DDCommon.h
class APlayerController; // 声明类
UCLASS()
class DATADRIVEN_API UDDCommon : public UObject
{
GENERATED_BODY()
public:
void InitController(APlayerController* InController);
APlayerController* GetController();
// 暂停游戏
void SetPauseGame(bool IsPause);
// 获取是否暂停了游戏
const bool IsPauseGame() const;
private:
APlayerController* PlayerController;
};

本文围绕UE4展开,先介绍创建框架Object类,如DDActorComponent等,对其进行相关操作使其受框架控制,还处理了载具类模块依赖问题。接着构建模组反射事件系统,包括对象调用所属模组方法、用引用形参作返回值、调用其他模组方法,最后用宏优化反射方法。
605

被折叠的 条评论
为什么被折叠?



