Download

TimerHandle does not call function after Garbage Collection

Hello,

I have been trying to create a building system. In my system, a preview of object that will be placed is displayed and position of this object is updated with a function called “UpdatePreviewTransform” which is tied to timer.

Everything works fine until garbage collection. But after GC my function is not being called anymore. My game does not crash or give any errors. It is just that timer stops calling the function.

My code in BuildingManager class is as follows.



// Spawn object
CurrentBuilding = World->SpawnActor<ABuilding>(TempClass, BuildingLocation, FRotator::ZeroRotator);

// Set timer to call UpdatePreviewTransform every 0.15 seconds.
World->GetTimerManager().SetTimer(TimerHandle, this, &UBuildingManager::UpdatePreviewTransform, 0.15f, true);


UpdatePreviewTransform function:



// Just to see if method gets called or not
UE_LOG(LogTemp, Warning, TEXT("Function called."));
...
// Updating position


But nothing is printed to console after GC. I forced GC with “GEngine->ForceGarbageCollection()” to see if GC is really the cause and confirmed that after first GC the problem occurs.

I did not placed this class into my world. So if I call GetWorld() it returns null. To solve that I pass pointer returned from GetWorld() to this object when creating BuildingManager class in my Character class.

What am I doing wrong?

Likely your BuildingManager object is being cleaned up. Someone has to hold on to that reference via a UPROPERTY or the GC will clean it up (since it has no references). Assuming this BuildingManager is more of a singleton, you may want to try the new Subsystems that came in with 4.22 - which are automatically allocated and destroyed as specific times.

https://docs.unrealengine.com/en-US/…ems/index.html

Thanks, you are right. I tried BuildingManager->AddToRoot() to prevent it from getting garbage collected and now it works fine even after GC.

However, I don’t think this is a good solution that I made and try to find a better solution.

Like ExtraLifeMatt mentioned, something needs to hold a hard reference to the BuildingManager or it will be GC’d, anything it references but doesn’t manage should also be a TWeakObjectPtr (or a UPROPERTY’d pointer, which converts it automatically) as well, and properly checked against before being used or you’ll have crashing issues when what it manages gets GC’d or invalidated. I would recommend making the BuildingManager an UObject, or an AActor if it ever needs to replicate any data to client instances of itself, and store the reference somewhere appropriate for the network environments its used in.