c4.Subsystem|子系统
大约 9 分钟
/** Subsystems are auto instanced classes that share the lifetime of certain engine constructs
*
* Currently supported Subsystem lifetimes are:
* Engine -> inherit UEngineSubsystem
* Editor -> inherit UEditorSubsystem
* GameInstance -> inherit UGameInstanceSubsystem
* World -> inherit UWorldSubsystem
* LocalPlayer -> inherit ULocalPlayerSubsystem
*
*
* Normal Example:
* class UMySystem : public UGameInstanceSubsystem
* Which can be accessed by:
* UGameInstance* GameInstance = ...;
* UMySystem* MySystem = GameInstance->GetSubsystem<UMySystem>();
*
* or the following if you need protection from a null GameInstance
* UGameInstance* GameInstance = ...;
* UMyGameSubsystem* MySubsystem = UGameInstance::GetSubsystem<MyGameSubsystem>(GameInstance);
*
*
* You can get also define interfaces that can have multiple implementations.
* Interface Example :
* MySystemInterface
* With 2 concrete derivative classes:
* MyA : public MySystemInterface
* MyB : public MySystemInterface
*
* Which can be accessed by:
* UGameInstance* GameInstance = ...;
* const TArray<UMyGameSubsystem*>& MySubsystems = GameInstance->GetSubsystemArray<MyGameSubsystem>();
*
*/
文档翻译
注
子系统是自动实例化的类,与特定引擎构造的生命周期共享
当前支持的子系统生命周期有:
- 引擎 -> 继承 UEngineSubsystem
- 编辑器 -> 继承 UEditorSubsystem
- 游戏实例 -> 继承 UGameInstanceSubsystem
- 世界 -> 继承 UWorldSubsystem
- 本地玩家 -> 继承 ULocalPlayerSubsystem
常规示例:
class UMySystem : public UGameInstanceSubsystem
可通过以下方式访问:
UGameInstance* GameInstance = ...;
UMySystem* MySystem = GameInstance->GetSubsystem<UMySystem>();
或者,如果需要防止空 GameInstance 的情况,可以使用以下方式:
UGameInstance* GameInstance = ...;
UMyGameSubsystem* MySubsystem = UGameInstance::GetSubsystem<MyGameSubsystem>(GameInstance);
您还可以定义具有多个实现的接口。 接口示例:
MySystemInterface
具有两个具体的派生类:
MyA : public MySystemInterface
MyB : public MySystemInterface
可通过以下方式访问:
UGameInstance* GameInstance = ...;
const TArray<UMyGameSubsystem*>& MySubsystems = GameInstance->GetSubsystemArray<MyGameSubsystem>();
实践
ExorcistGameInstanceSubsystem.h
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "ExorcistGameInstanceSubsystem.generated.h"
UCLASS()
class EXORCIST_API UExorcistGameInstanceSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
};
ExorcistGameInstanceSubsystem.cpp
#include "ExorcistGameInstanceSubsystem.h"
GameInstanceSubsystem.h
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Subsystems/Subsystem.h"
#include "GameInstanceSubsystem.generated.h"
class UGameInstance;
/**
* UGameInstanceSubsystem
* Base class for auto instanced and initialized systems that share the lifetime of the game instance
*/
UCLASS(Abstract, Within = GameInstance)
class ENGINE_API UGameInstanceSubsystem : public USubsystem
{
GENERATED_BODY()
public:
UGameInstanceSubsystem();
UGameInstance* GetGameInstance() const;
};
GameInstanceSubsystem.cpp
// Copyright Epic Games, Inc. All Rights Reserved.
#include "Subsystems/GameInstanceSubsystem.h"
#include "Engine/GameInstance.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(GameInstanceSubsystem)
UGameInstanceSubsystem::UGameInstanceSubsystem()
: USubsystem()
{
}
UGameInstance* UGameInstanceSubsystem::GetGameInstance() const
{
return Cast<UGameInstance>(GetOuter());
}
UGameInstanceSubsystem
类是一个抽象基类,继承自USubsystem
。这是一个用于定义游戏实例子系统的基础类。
UCLASS(Abstract, Within = GameInstance)
构造函数
UGameInstanceSubsystem::UGameInstanceSubsystem()
初始化了子系统对象,调用基类USubsystem
的构造函数。UGameInstance* UGameInstanceSubsystem::GetGameInstance() const
方法返回与该子系统关联的游戏实例指针。它使用GetOuter()
函数获取该子系统的外部对象,并将其转换为UGameInstance
类型。
UGameInstance* GetGameInstance() const;
常函数&常量指针
提示
常函数
常函数(const member function)是一种承诺,表明在该函数内部不会修改调用对象的成员变量。这是通过在函数声明和定义中使用 const 关键字实现的。
常量指针
const int*p
常量指针,是一种被限制(只读)修改指向值能力的指针。
UGameInstance* UGameInstanceSubsystem::GetGameInstance() const
{
return Cast<UGameInstance>(GetOuter());
}
#defineFORCEINLINE__forceinline
继承特性
提示
在C++中,继承分为公有继承、保护继承和私有继承三种方式。 对于公有继承(public inheritance),子类可以调用父类的公开(public)成员函数.
UObject————————————————————————————
| |
USubsystem |
| |
UGameInstanceSubsystem——Cast<UGameInstance>(GetOuter())
UObject
是 Unreal Engine 中所有对象的基类。USubsystem
是一个子系统抽象类,继承自UObject
。UGameInstanceSubsystem
也是是一个子系统抽象类,继承自USubsystem
。
抽象类
注
在C++中,学习继承和多态时我们知道,如果一个类包含至少一个纯虚函数,那么这个类就被认为是一个抽象类。
USubsystem.h
// USubsystem 类是 UObject 的子类,用于定义子系统的基本结构。
UCLASS(Abstract)//抽象类
class ENGINE_API USubsystem : public UObject
{
GENERATED_BODY()
public:
USubsystem();//默认构造
/** 重写此函数以控制是否应创建子系统。
* 例如,您可以仅在服务器上创建系统。
* 需要注意的是,如果使用此功能,每次获取子系统时都很重要进行空指针检查。
*
* 注意:在创建实例之前,此函数在 CDO 上调用!
*
*/
virtual bool ShouldCreateSubsystem(UObject* Outer) const { return true; }
/** 实例构造 */
virtual void Initialize(FSubsystemCollectionBase& Collection) {}
/** 析构 */
virtual void Deinitialize() {}//纯虚函数
/** 重写以检查全局网络上下文 */
virtual int32 GetFunctionCallspace(UFunction* Function, FFrame* Stack) override;
private:
friend class FSubsystemCollectionBase;
FSubsystemCollectionBase* InternalOwningSubsystem;
};
/** DynamicSubsystem 在模块加载和卸载时自动填充/清除现有集合的动态子系统
*
* 只有 UEngineSubsystems 和 UEditorSubsystems 允许动态加载。
*
* 如果您的子系统实例未被创建,可能是因为它们所在的模块未被显式加载,
* 确保有一个 LoadModule("ModuleName") 来加载该模块。
*/
UCLASS(Abstract)
class ENGINE_API UDynamicSubsystem : public USubsystem
{
GENERATED_BODY()
public:
UDynamicSubsystem();
};
USubsystem.cpp
// Copyright Epic Games, Inc. All Rights Reserved.
#include "Subsystems/Subsystem.h"
#include "Engine/Engine.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(Subsystem)
USubsystem::USubsystem()
{
}
int32 USubsystem::GetFunctionCallspace(UFunction* Function, FFrame* Stack)
{
return GEngine->GetGlobalFunctionCallspace(Function, this, Stack);
}
UDynamicSubsystem::UDynamicSubsystem()
: USubsystem()
{
}
USubsystem
中定义了两个类 USubsystem
和 UDynamicSubsystem
。
USubsystem 类:
- 继承自
UObject
。 - 使用
UCLASS(Abstract)
宏标记为抽象类,表示不能直接实例化该类。 - 包含一个默认构造函数
USubsystem()
。 - 提供了虚函数
ShouldCreateSubsystem
,用于确定是否应该创建该子系统的实例。 - 包含虚函数
Initialize
用于实例初始化,和Deinitialize
用于析构。 - 重写了
GetFunctionCallspace
函数,用于检查全局网络上下文。 - 包含一个私有成员
InternalOwningSubsystem
,被声明为友元类FSubsystemCollectionBase
的一个私有成员。
- 继承自
UDynamicSubsystem 类:
- 继承自
USubsystem
,是USubsystem
的一个子类。 - 使用
UCLASS(Abstract)
宏标记为抽象类,表示不能直接实例化该类。 - 包含一个默认构造函数
UDynamicSubsystem()
。
- 继承自
ExorcistGameInstanceSubsystem.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "ExorcistGameInstanceSubsystem.generated.h"
class UGameSingleton;
/**
*
*/
UCLASS()
class EXORCIST_API UExorcistGameInstanceSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
//是否创建这个子系统
virtual bool ShouldCreateSubsystem(UObject* Outer) const override;
//初始化
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
//销毁
virtual void Deinitialize() override;
public:
UPROPERTY(BlueprintReadWrite)
int32 HP;
private:
UGameSingleton* UGameSingleton;
};
ExorcistGameInstanceSubsystem.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "ExorcistGameInstanceSubsystem.h"
#include "GameSingleton.h"
bool UExorcistGameInstanceSubsystem::ShouldCreateSubsystem(UObject* Outer) const
{
return Super::ShouldCreateSubsystem(Outer);
}
void UExorcistGameInstanceSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
UGameSingleton = UGameSingleton::GetInstance();
UGameSingleton->InstanceCount++;
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("InstanceCount:%d"), UGameSingleton->InstanceCount));
}
void UExorcistGameInstanceSubsystem::Deinitialize()
{
Super::Deinitialize();
UGameSingleton->InstanceCount++;
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("InstanceCount:%d"), UGameSingleton->InstanceCount));
}
GameSingleton.h
#pragma once
#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "GameSingleton.generated.h"
UCLASS(Blueprintable,BlueprintType)
class EXORCIST_API UGameSingleton : public UObject
{
GENERATED_BODY()
private:
UGameSingleton() {}
public:
UFUNCTION(BlueprintCallable)
static UGameSingleton* GetInstance();
public:
UPROPERTY(BlueprintReadWrite)
int32 InstanceCount = 30;
};
GameSingleton.cpp
#include "GameSingleton.h"
UGameSingleton* UGameSingleton::GetInstance()
{
static UGameSingleton* instance=nullptr;
if (instance==nullptr)
{
instance=NewObject<UGameSingleton>();
instance->AddToRoot();
}
return instance;
}
编译运行后任意关卡启动。