Subsystem

Table of contents

Explanation

For the sake of convenience Systems Architecture provides handy wrapper over USystemsWorld global instances as a USystemsSubsystem that is basically a registry of systems worlds accessible from any place in the code.

All user needs to do is to register and setup systems world using USystemsSubsystem::AcquireSystemsWorld when certain game phase starts (either game, level, menu, etc) before adding/removing/querying actor components, and unregister systems world using USystemsSubsystem::ReleaseSystemsWorld when given game phase ends.

Examples

The most common game phases where systems might exists are game instance and game mode.

  • You register systems world in game instance when there are systems are possible to run during entire game lifetime. This is the easiest and safest option.
  • You register systems world in game mode when there are systems that are possible to run during given game level lifetime. This is useful if we for example have completely separate pipelines set for each level or game mode.

Game instance

Since game instance has a lifetime of entire game run, we only care here about registering systems world to subsystem on UGameInstance::Init.

UCLASS()
class EXAMPLE_API UExampleGameInstance : public UGameInstance
{
	GENERATED_BODY()

private:
	virtual void Init() override;
};

void UExampleGameInstance::Init()
{
	Super::Init();

	auto* Subsystem = USystemsSubsystem::Get(GetWorld());
	if (IsValid(Subsystem))
	{
		Subsystem->AcquireSystemsWorld(FName(),
			[&](auto& Systems)
			{
				Systems.RegisterComponent<UShiaComponent>();

				Systems.InstallResource<UShiaSettings>();

				Systems.InstallLambdaSystem(JustDoItSystem, FInstallSystemOptions("JustDoIt"));
			});
	}
}

Game mode

When it comes to game mode, we should register systems world on AGameModeBase::InitGame (it runs before any actor BeginPlay - if we register it on BeginPlay, then some actors placed on level might try to register to yet non-existing systems world) and unregister it on AGameModeBase::EndPlay.

UCLASS()
class EXAMPLE_API AExampleGameMode : public AGameModeBase
{
	GENERATED_BODY()

private:
	virtual void InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) override;

	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
};

void AExampleGameMode::InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage)
{
	Super::InitGame(MapName, Options, ErrorMessage);

	auto* Subsystem = USystemsSubsystem::Get(GetWorld());
	if (IsValid(Subsystem))
	{
		Subsystem->AcquireSystemsWorld(FName(),
			[&](auto& Systems)
			{
				Systems.RegisterComponent<UShiaComponent>();

				Systems.InstallResource<UShiaSettings>();

				Systems.InstallLambdaSystem(JustDoItSystem, FInstallSystemOptions("JustDoIt"));
			});
	}
}

void AExampleGameMode::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	Super::EndPlay(EndPlayReason);

	auto* Subsystem = USystemsSubsystem::Get(GetWorld());
	if (IsValid(Subsystem))
	{
		Subsystem->ReleaseSystemsWorld(ThisClass::SYSTEMS_WORLD);
	}
}

Documentation built with Unreal-Doc v1.0.8 tool by PsichiX