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.

I fixed it as you said, but it didn’t help. The problem persists, and the editor stops here.

ensureMsgf(bInitialized, TEXT("Tickable subsystem %s tried to tick when not initialized! Check for missing Super call"), *GetFullName());

You should post the line from the log which has the object name included and the updated code you’re actually running that is still not working.

I’m getting the following in the log:

Warning LogOutputDevice Script Stack (0 frames) :
Error LogOutputDevice Ensure condition failed: bInitialized [File:C:\UE\5.6src\Engine\Source\Runtime\Engine\Private\Subsystems\WorldSubsystem.cpp] [Line: 83]
Error LogOutputDevice Tickable subsystem UMyTickableWorldSubsystem /Script/MyTickableWorld.Default__UMyTickableWorldSubsystem tried to tick when not initialized! Check for missing Super call

Code after changes:

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

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

ETickableTickType UMyTickableWorldSubsystem::GetTickableTickType() const
{
    if (IsTemplate() || !IsInitialized())
    {
        return ETickableTickType::Never;
    }

    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!”));
}

Beats me. The code you shared works just fine for me if I use it to implement a tickable world subsystem.

Maybe share your header? or it isn’t recompiling your changes. You may need to breakpoint GetTickableTickType to figure out why your CDO is ticking (based on the object name from the log, that’s what’s happening).

Hello,

I tried debugging the code as you suggested. The GetTickableTickType function is called twice when UnrealEditor starts up. Once when the load reaches 98%, and the second time immediately after the editor launches. In both cases, the ETickableTickType::Always flag is returned, since IsTemplate() returns false and IsInitialized() returns true. Immediately after these two breakpoints, execution stops at ensureMsgf, but I still don’t understand why bInitialized is set to false there.