Any way to manipulate time scale?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By daeww
:warning: Old Version Published before Godot 3 was released.

Is there any way to alter the game’s time scale? Engines like construct have this option out of the box, which makes a slowdown “bullet-time” sort of effect possible. I’ve considered dividing the speed of physics objects by a slow down factor, but that only affects the objects’ movement and not other effects such as animations and particles. Keeping track of all these atributes and altering their speed individually seems like too big of a hassle, so I’m wondering if there’s another more effective way to achieve this effect that I’m not aware of.

:bust_in_silhouette: Reply From: eaglecat
> OS.set_time_scale(0.5)#slow down the game 2 times

damn, do I feel dumb lol, thanks!

would there be a way to only alter it on specific game objects?

daeww | 2016-05-28 23:16

alter each component as you mentioned. maybe it’s only way to apply on specific node

eaglecat | 2016-05-29 00:47

:bust_in_silhouette: Reply From: Jesus05

in godot 3.0 use Engine.time_scale = 2 to double speed or Engine.time_scale = 0.5 for half speed.

There is a formatting issue with this answer, and is not showing correctly (an underscore has been interpreted as a formatting character)

The actual property is:

Engine.time_scale

Gerard Ruiz | 2018-06-17 17:07

How is this done in C#, Godot 3.1?

Edit: It was Godot.Engine.TimeScale = 1;

jarlowrey | 2019-08-27 04:20

thanks, this works for me.

morningkingdom | 2021-03-22 17:21

:bust_in_silhouette: Reply From: idbrii

Here’s a cool solution from SnailRhymer that adds time scale zones to the map:

I don’t think this solution is great, hopefully there’s someone with a better one. It does work though.


A crude fix could be to loop through physics steps in a single frame, incrementing by the object’s “local” delta until enough time has elapsed in the real world:

func _physics_process(delta):
	# Will be doing physics steps every delta seconds from the perspective of the object.
	# Need to keep track of real wotld time that has elapsed and stop once it reaches delta.
	var actual_time_elapsed = 0

	while actual_time_elapsed < delta:
		# Update the time scale
		var time_scale = get_time_scale()

		# Make sure we don't overshoot, e.g. if 4.3 loops needed, don't do 5 full loops
		var step_size
		var actual_step_time_if_full_step = delta/time_scale
		if actual_time_elapsed + actual_step_time_if_full_step < delta:
			step_size = 1.0
		else:
			step_size = (delta - actual_time_elapsed)/time_scale
		
		# Now do the physics for this object as if time were passing normally for it.
		do_physics(step_size * delta)

		# Update how much real world time has passed
   		actual_time_elapsed += step_size/time_scale

This approach would still have the problem that if you have e.g. two objects moving very fast as a result of a high time_scale, the physics for one will happen entirely before the physics for the other, so they could fail to interact.

To resolve that issue, I think you’d need to do something similar but work out the timescales of all objects, find the minimum step size, then change the physics_fps to default_fps*max_time_scale.

Then each object’s physics process should look like

func _physics_process(delta):
    var base_delta = 1.0/60.0 # If it would normally be 60fps
    var delta_to_use = base_delta * step_size * time_scale_for_this_object / highest_time_scale
    # Now do physics with this delta

Note that delta_to_use is never larger than base_delta, so no object will do a physics step larger than delta in its own local time.

It is this second approach that I implemented here.


(Note that you could equivalently use

var delta_to_use = _delta * step_size * time_scale_for_this_object

since delta = base_delta/max_time_scale.)