一.子系统概述
参考官方文档
虚幻引擎编程子系统 | 虚幻引擎 5.7 文档 | Epic Developer Community
游戏实例子系统 是子系统中的一种,目前用最多。编辑器的更多涉及到编辑器开发。

更多优点,去看大钊的文章。

二.子系统生命周期的优势 在关卡切换中
子系统几乎和引擎同步,所以游戏里喜欢把核心的跨关卡的数据放到 子系统里保存管理。一是方便获得,蓝图直接拿,C++有模块包个头就能用,爽,进而修改同步。二是 生命周期够长,即使是切换关卡后,也许物体没了,但子系统里的数据依然保留,方法指针等也会保留。也方便做后续的类似存档,读档。
以下是案例
在关卡蓝图里,调用子系统里的东西。
Map1 +11

Map2 +11

切换关卡,依然会执行。


三.子系统 与多播
通过子系统方便全局获得委托,并且进行绑定 和 呼叫执行。它俩简直绝配。
以下是案例。
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "GWXGameInstanceSubsystem.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FWXSubsystemLocation, FString ,InActionName, int32 ,InActionIndexTime);
/**
*
*/
//UGWXGameInstanceSubsystem* UGWXGameInstanceSubsystem::MySubsystem = nullptr;
UCLASS()
class THIRDLEARN_API UGWXGameInstanceSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
virtual bool ShouldCreateSubsystem(UObject* Outer) const override;
/** Implement this for initialization of instances of the system */
virtual void Initialize(FSubsystemCollectionBase& Collection)override;
/** Implement this for deinitialization of instances of the system */
virtual void Deinitialize()override;
UFUNCTION(BlueprintCallable)
void CallLocation(FString InActionName,int32 InActionIndex);
UFUNCTION(BlueprintCallable)
UGWXGameInstanceSubsystem* GetGWXSubsystemself();
UPROPERTY(BlueprintAssignable)
FWXSubsystemLocation WXSubsystemLocationDelegate;
void AddHealth(int num);
private:
//static UGWXGameInstanceSubsystem* MySubsystem;
int Health = 0;
};
cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "GWXGameInstanceSubsystem.h"
bool UGWXGameInstanceSubsystem::ShouldCreateSubsystem(UObject* Outer) const
{
return true;
}
void UGWXGameInstanceSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
//MySubsystem = this;
}
void UGWXGameInstanceSubsystem::Deinitialize()
{
//MySubsystem = nullptr;
Super::Deinitialize();
}
void UGWXGameInstanceSubsystem::CallLocation(FString InActionName, int32 InActionIndex)
{
WXSubsystemLocationDelegate.Broadcast(InActionName, InActionIndex);
}
UGWXGameInstanceSubsystem* UGWXGameInstanceSubsystem::GetGWXSubsystemself()
{
//return MySubsystem;
return nullptr;
}
void UGWXGameInstanceSubsystem::AddHealth(int num)
{
Health += num;
}
在关卡蓝图中,通过子系统呼叫

在Actor里,通过子系统,绑定。很轻松就完成跨类委托

四.获得子系统的多种方式
A类获取,可以直接GetGameInstance->GetSubsystem获取
cpp
void AGWXGamieInstance_TestActor::BeginPlay()
{
Super::BeginPlay();
UGameInstance* MyGameInstance = GetGameInstance();
if (MyGameInstance)
{
UGWXGameInstanceSubsystem* MySimpleSubsystem = MyGameInstance->GetSubsystem<UGWXGameInstanceSubsystem>();
MySimpleSubsystem->AddHealth(998);
}
}
U类获取,需要获得World,再拿到GetGameInstance->GetSubsystem获取
cpp
void AGWXGamieInstance_TestActor::ObjectGetSubsystem(const UObject* InWorldContextObject)
{
if (InWorldContextObject && InWorldContextObject->GetWorld())
{
UGameInstance* MyGameInstace = InWorldContextObject->GetWorld()->GetGameInstance();
if (MyGameInstace)
{
UGWXGameInstanceSubsystem* MySimpleSubsystem = MyGameInstace->GetSubsystem<UGWXGameInstanceSubsystem>();
MySimpleSubsystem->AddHealth(2000);
}
}
}
传统static 获取,会有安全隐患
头文件
cpp
UFUNCTION(BlueprintCallable)
static UGWXGameInstanceSubsystem* GetXGSubsystemMySelf();
private:
int32 CurrentHealth = 100;
bool bFirstTick = true;
static UGWXGameInstanceSubsystem* MySubsystemPtr;
源文件,跟随生命周期赋值。
cpp
#include "GWXGameInstanceSubsystem.h"
UGWXGameInstanceSubsystem* UGWXGameInstanceSubsystem::MySubsystemPtr = nullptr;
void UGWXGameInstanceSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
MySubsystemPtr = this;
}
void UGWXGameInstanceSubsystem::Deinitialize()
{
MySubsystemPtr = nullptr;
Super::Deinitialize();
}
UGWXGameInstanceSubsystem* UGWXGameInstanceSubsystem::GetXGSubsystemMySelf()
{
return MySubsystemPtr;
}
其他类测试
UGWXGameInstanceSubsystem* MySimpleSubsystem = UGWXGameInstanceSubsystem::GetXGSubsystemMySelf();
MySimpleSubsystem->AddHealth(666);
五.子系统的Tick
很简单在子系统里集成一个public FTickableGameObject类,重写Tick就行。还有些其它函数也可重写,如
cpp
virtual void Tick(float DeltaTime) override;
virtual bool IsTickable() const override;
virtual TStatId GetStatId() const override;
然后
cpp
void UGWXGameInstanceSubsystem::Tick(float DeltaTime) //无需super 虚方法
{
UE_LOG(LogTemp,Warning,TEXT("12345"));
}
bool UGWXGameInstanceSubsystem::IsTickable() const
{
return !IsTemplate();
}
TStatId UGWXGameInstanceSubsystem::GetStatId() const
{
RETURN_QUICK_DECLARE_CYCLE_STAT(UGWXGameInstanceSubsystem, STATGROUP_Tickables);
}
就能每帧执行一次
