05 - 编程子系统
本文主要说明了UE5中有关编程子系统SubSystem
的概念和基本用法。
有时需要实现一些在游戏运行时全局存在的功能,如果一直往GameInstance
中添加就会变得越来越臃肿。UE提供编程子系统来解决这一问题,它相当于GameInstance
的下位替代,是生命周期受控的自动实例化类,可和蓝图、Python联动。
为什么使用子系统
使用编程子系统有以下几个原因:
- 子系统可节省编程时间。
- 子系统使您无需覆盖引擎类。
- 子系统使您无需再已经很复杂的类上添加更多API。
- 子系统使您能通过用户友好的类型化节点来访问蓝图。
- 子系统允许访问Python脚本来编写编辑器脚本或编写测试代码。
- 子系统在代码库中提供模块化和一致性。
子系统在创建插件时尤为实用。您不需要代码相关的说明即可让插件工作。用户只需将插件添加到游戏中,就可以确切了解插件将在何时被实例化和初始化。
生命周期
子系统按照它的生命周期分类:
子系统 | 继承自 |
---|---|
引擎 | UEngineSubsystem 类 |
编辑器 | UEditorSubsystem 类 |
游戏实例 | UGameInstanceSubsystem 类 |
本地玩家 | ULocalPlayerSubsystem 类 |
例如,如果创建一个基于游戏实例子系统的类:
UCLASS()
class UMyGamesStatsSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
// Begin USubsystem
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
// End USubsystem
void IncrementResourceStat();
private:
// All my variables
};
将出现以下结果:
- 创建
UGameInstance
之后,还会创建一个名为UMyGamesSubsystem
的子系统实例。 UGameInstance
在模块初始化Startup()
后,将在子系统上调用Initialize()
。UGameInstance
在模块关闭Shutdown()
时,将在子系统上调用Deinitialize()
。- 此时将放弃对子系统的引用,如果不再有对子系统的引用,则其将被垃圾回收。
访问
引擎子系统通过GEngine
访问:
UMyEngineSubsystem* MySubsystem = GEngine->GetEngineSubsystem<UMyEngineSubsystem>();
编辑器子系统通过GEditor
访问:
UMyEditorSubsystem* MySubsystem = GEditor->GetEditorSubsystem<UMyEditorSubsystem>();
GameInstance
子系统通过UGameInstance
访问:
UGameInstance* GameInstance = ...;
UMyGameSubsystem* MySubsystem = GameInstance->GetSubsystem<UMyGameSubsystem>();
LocalPlayer
子系统通过ULocalPlayer
访问:
ULocalPlayer* LocalPlayer = ...;
UMyPlayerSubsystem * MySubsystem = LocalPlayer->GetSubsystem<UMyPlayerSubsystem>();