[question] Initializing FTimerManager inside UObject inherited class?

So my question is how to make use of this thing, inside UObject derived class ? In other classes I can get access to trough:

GetWorld()->GetTimerManager()

or

GetWorldTimerManager()

But not inside class that directly inherit from UObject.

So far I have timer defined in header file:

class FTimerManager TimerManager;

And make use of it here:

	FTimerDynamicDelegate tdd;
	tdd.BindDynamic(this, &URPGEffectBase::RemoveFromArray);
	TimerManager.SetTimer(tdd, 5.0f, false);

But it clearly doesn’t work. As the binded function is not called, and in debug timer looks like uninitialized (although it compile and doesn’t crash).

Unless there is some alternative to firing up functions after set amount of time ?

While you can get A world context in the manner Rama outlines, you are taking great risks for situations in which multiple worlds exist (multiple PIE worlds, editor preview worlds, etc.) We’ve done an enormous amount of work to try and eliminate the use of GWorld (the previous short cut way to getting the current (or hopefully current, and thus the problem) world).

For blueprint node functions you should be providing a world context object. Our blueprint functions that require a world look something like:

UFUNCTION(BlueprintPure, Category="Game", meta=(HidePin="WorldContextObject", DefaultToSelf="WorldContextObject" ) )
static class AGameMode* GetGameMode(UObject* WorldContextObject);


AGameMode* UGameplayStatics::GetGameMode(UObject* WorldContextObject)
{
	UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject);
	return World ? World->GetAuthGameMode() : NULL;
}

The meta data indicates that that the pin named WorldContextObject should be hidden and default to self. From that we can use GetWorldFromContextObject to get the actual world from whatever that context object is. There are a few cases, AnimNotifies chiefly among them, where there is no valid way of determining the World from self, in those cases the class is marked up with meta=(ShowHiddenSelfPins) which will display the WorldContextObject pin and force something to be connected to it that will have context (in the case of AnimNotifies that will generally be the Component passed in).

For all other types of UObject inherited classes I highly recommend that you have a path back to the World. Any kind of singleton static class manager type object that tries to exist independent of the Worlds is prone to have issues in a multiple World environment.

This is awesome, thanks for sharing the code Marc!

Copy-pasted to my notes on things you say :slight_smile:

Rama

Thanks. Nice solution, I already wrapped it inside function for ease of use inside class.

Dear Lukasz,

Hi there!

#Getting World in UObject or Static Function

the way I get the world context during runtime via a static or UObject class is this way:

I use ObjectIterator to get the player controller

you could use any actor really :slight_smile:

//Get an actor to GetWorld() from
TObjectIterator Itr;
if (!Itr) return;
//~~~~~~~~~~~~
	
//Get World
UWorld* TheWorld = Itr->GetWorld();
if (!TheWorld) return;
//~~~~~~~~~~~~~~~~~

//TheWorld->GetTimerManager()->//....

I use this method extensively in my Static Blueprint Node Library to access world() for things ranging from DrawDebugLine to doing traces :slight_smile:

:slight_smile:

Rama

Thanks you. It works!
But I have question, not sure if you can answer, but how about performance of it ? Especially since it is possible that it’s going to replicated among hundreds of objects as the same time.

Are you working within a static function?

As Marc said below, you should probably pass in the world context to your UObject. (I’m copying his code below)

void UYourObject::YourFunction(UObject* WorldContextObject)
{
UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject);
   if(!World) return;

   //World->GetTimerManager()->/////
}

I would probably resist the urge to make a permanent World reference as part of the custom UObject class, and pass in the world every time**, calling GetWorld() from whatever Actor is using the UObject.**

My method should not be too slow though, if you are not using the Editor.

If you are running the actual game by itself, as all end users will be, then ObjectIterator is not that slow.

ObjectIterator can cause allllll kinds of confusion if you run your game from the Editor, as it picks up all objects and all worlds, as Marc mentioned :slight_smile:

#Alternate if Not BP

I personally dont know where to get the WorldContextObject to pass into the function above, if not using a BP setup

so I would actually end up doing this at moment:

void UYourObject::YourFunction(UWorld* World)
{
   if(!World) return;

   //World->GetTimerManager()->/////
}