跳到主要内容

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
};

将出现以下结果:

  1. 创建 UGameInstance 之后,还会创建一个名为 UMyGamesSubsystem 的子系统实例。
  2. UGameInstance 在模块初始化Startup()后,将在子系统上调用 Initialize()
  3. UGameInstance 在模块关闭Shutdown()时,将在子系统上调用 Deinitialize()
  4. 此时将放弃对子系统的引用,如果不再有对子系统的引用,则其将被垃圾回收。

访问

引擎子系统通过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>();

参考资料