UTickableWorldSubsystem: Tickable subsystem tried to tick when not initialized

Hi everyone. I’m having trouble creating my own TickableWorldSubsystem.
No matter what I do, I keep getting the error: “Tickable subsystem … tried to tick when not initialized! Check for missing Super call.” I’ve included Super::Initialize(Collection), but the error persists.

Option 1:

void UMyTickableWorldSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
}

void UMyTickableWorldSubsystem::Deinitialize()
{
Super::Deinitialize();
}

ETickableTickType UMyTickableWorldSubsystem::GetTickableTickType() const
{	
return ETickableTickType::Always;
}

TStatId UMyTickableWorldSubsystem::GetStatId() const
{
RETURN_QUICK_DECLARE_CYCLE_STAT(UMyTickableWorldSubsystem, STATGROUP_Tickables);
}

void UMyTickableWorldSubsystem::Tick(float DeltaTime)
{
UE_LOG(LogTemp, Log, TEXT(“— Hello!”));
}

In the second approach, I decided to use ETickableTickType::Conditional and return the tick start time in IsTickable if the system has been initialized:

bool UMyTickableWorldSubsystem::IsTickable() const
{
return IsInitialized();
}

ETickableTickType UMyTickableWorldSubsystem::GetTickableTickType() const
{
return ETickableTickType::Conditional;
}

Please help me figure out what’s going on.

UE5.6

Option 1 is a problem because you return Always from GetTickableTickType. What this will do is cause the CDO for UMyTickableWorldSubsystem to try and tick. Which you don’t want. You’ll even see in the TickableWorldSubsystem that its implementation checks for IsTemplate and returns Never.

Option 2 is hitting the error because you’re returning Conditional which causes IsAllowedToTick to be called prior to the World being initialized (somehow). And even though that function is deprecated, it’s still being used.

If your subsystem is meant to always tick, adding:

if (IsTemplate() || !bInitialized)
{
	return ETickableTickType::Never;
}

before the return of Always is probably the way to go.

Or you could not override GetTickableType at all, let the super version be used and override IsTickable to return true unconditionally. The GetTickableType should prevent anything that shouldn’t tick (CDO, uninitialized) from trying to tick.