Timers not affected by Time Dilation

Sadly it is not possible by default as far as I know.

An alternative you could use is Timeline component and bind only OnFinish. Timeline has a boolean to “Ignore time dilation”

Individual actors can be set to ignore time dilation. Additionally you can set their time scale so that if your global time dilation is 0.5 you can set other things to 2.0 to make it as if theyre normal speed.

That does not work if the time dilatation is changing after the timer has been set

Hello, we are using timers to do things not related to gameplay and we want them to not be affected by time dilation.
Does anyone know if that’s possible or do we have to implement a custom timer for this?

Ah you mean the timer itself is set to run for certain amount of time, so even if you adjusted the time it was to run for, you would have to do that BEFORE starting the timer. That makes sense.

What I did in my game was instead of setting a timer, I set a float variable to zero and add deltatime to it every tick, until it reaches or exceeds another float variable which is the amount of time to wait before triggering the effect. I multiply each additional amount of deltatime by the inverse of the global time dilation if I don’t want it to be affected by the time dilation, or put it into an actor that ignores time dilation.

All that being said, using a timeline that ignores time dilation sounds like the easiest solution so your answer is good.

Hey sorry for necro but I was able to create a quick macro for a delay node that ignores time dilation. Would be useful for use guys! You will have to create either a ActorMacro bp, or a ActorComponentMacro bp depending on where you want to use this node. Here is the setup for the macro.

Then this can be used like like any normal delay. Keep in mind this is definitely less efficient. The last check for game instance is solve issue we had that would fire when switching levels while loop was running. Can probably be left out as our game does some extra weird stuff there.

You can do it in C++ by calling an AsyncTask that creates a sleeping thread for the amount of seconds specified, and that calls a delegate. Not the best way but it works for most case and you can be sure Time Dilation or Pause won’t interfere.

void SetAbsoluteTimer(FTimerDelegate Delegate, float Delay,
	bool bLooping)
{
	float UsedDelay = Delay;
	AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, [&, Delegate, UsedDelay, bLooping]()
   {
	   while (true)
	   {
		   FPlatformProcess::Sleep(UsedDelay);

		   AsyncTask(ENamedThreads::GameThread, [&, Delegate]()
		   {
			   Delegate.ExecuteIfBound();
		   });

		   if (!bLooping)
		   	break;
	   }
   });
}

void SetAbsoluteTimer(TFunction<void()>&& Callback, float Delay, bool bLooping)
{
	SetAbsoluteTimer(FTimerDelegate::CreateLambda(Callback), Delay, bLooping);
}

You can then use it like any Timer

SetAbsoluteTimer([&]
{
	// Do Stuff ...
			
}, 1.0f, false);

EDIT : It can cause a crash if the game is stopped or the current level is changed during a timer. I haven’t dug into it yet.

1 Like

You can do it when you simply safe the current time and then check if the time elapsed is greater than the limit you wanted. Maybe the performance is worse but it works :wink: