|
|
|
|
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.)