Godot: Time manipulation / Speed mode in Node

Created on 21 Oct 2016  Â·  34Comments  Â·  Source: godotengine/godot

I would like to have the ability of slow-mo in my games and change it where and when I like (like in some particular events)
Maybe a SPEED member that comes built-in in a Node and other nodes will have the ability to inherit it (like pause mode) and if it reaches 0 it will pause the game
And maybe the delta argument in the process function will be multiplied by SPEED:

func _process(delta):
    var time_passed = delta # delta is actually old delta * speed

Or process will have another argument in case you want to know how much time passed in real time:

func _process(delta, real_delta):
    var time_passed = real_delta
    var time_passed_in_game = delta

Include _fixed_process too.
The thing is it should affect all child nodes and all type of nodes like AnimationPlayer, SamplePlayer, Tween, Physics, Particles etc..
That sounds like it could be done just by implementing something to Node...

archived feature proposal pr welcome core

Most helpful comment

I did a little research if you don't mind.

Unreal Engine has a console command slowmo that receives a positive float argument that slows down (when between 0.0 and 1.0) or speeds up (when above 1.0) the entire engine. It does not change the rendering frequency, and does not change the physics loop frequency.

Unity has the Time.timeScale static property which scales the delta time used for frame rendering and for physics loop. But it seems it also slows down the physics loop frequency, and to fix that Time.fixedDeltaTime should be changed together:

Time.timeScale = slowMotionFactor;
Time.fixedDetaTime = slowMotionFactor * 0.02f;  // magic ratio

Another thing that Unity has is the Time.unscaledDeltaTime static property that can be used to do stuff with the "real delta time", such as tweening in to (or out of) the slow motion.


Updating my practical suggestion: I suggest to recover the OS.set_time_scale() method and expose OS.unscaled_process_delta and OS.unscaled_physics_process_delta to be able to access unscaled deltas.

I saw it is possible to scale the speed of animations, particles and tweens, and I can think of fun stuff to do with these plus the time scaling. Maybe one of the few things it would be nice to have is a use_unscaled_time property in the Timer and Tween classes. Or maybe implement separate RealtimeTimer and RealtimeTween classes. For example there could be a countdown timer to constraint the ammount of real-life time the player has to accomplish a certain task. And there could be timers to trigger traps after a certain ammount of in-game-time. And it would be nice to use Tween (in real-life-time) to fade between timescales.

All 34 comments

There's the OS.set_time_scale() function. Not sure how much it affects though.

It looks like time scale would affect the whole tree, not just a subtree.

Can this potentially break the physics engine, since it runs on a different thread? Or it just won't affect it at all?

Another approach would be the ability to tell a nodes (or a hierarchy) not to be affected by time scale changes, since the usage here is to slow down the game, not the UI or anything else that is not the game world itself.

A time scale variable for Node? Sounds nice but it could break several things...

Maybe a new type of _process?
_bullet_time_process?

Another type of process would not be relevant since the only change here is delta time. The actual problem is how do we make it apply to a specific set of nodes.

But thinking about it, if your game is driven by _fixed_process (physics and movement almost always are), we could simply have a fixed_time_scale, which will modify the delta parameter. It's even less intrusive since it doesn't require to add a property or change existing code. The game motions will run in slow-mo out of the box. But that's a theory of course :)

I like to do slow-mo to as well, but i also want it to be possible by doing as few additions as possible to the engine, because adding a property or a new function call everywhere just for that use case that not everybody needs could bloat nodes (doesn't seems like much, but it adds up), while delta is already supposed to do that.

@Zylann I agree, I can think of the need to get slow motion like is used a lot on new games for effects, but the UI, Input and other parts need to be at normal rate.

Could be something like "pause" too, affecting the delta of some nodes, none by default (but again, is the "Input-in-process" problem there).

If it affects only _fixed_process, the UI will be fine, and if the UI uses _fixed_process for some reason it will be slowed down, that's it.

It could indeed work like the pause mode, yeah. I like this because it's just a flag, it shouldn't take up space as memory is allocated 8 by 8 bits. However I wonder how much it would impact the _process() flow in case someone doesn't uses the feature.

What do you mean by "Input-in-process problem"?

@Zylann when you use Input in _process or _fixed_process, if the process is slowed down the application could appear unresponsive to the user input, but it could be solved in the design.

@eon-s no, it would still be responsive. The only thing that change is delta (for concerned nodes), which will be smaller, not the rate at which _process is called. It will still run at 60 fps.

there is an OS function for this (I can't remember)

On Thu, Oct 20, 2016 at 9:26 PM, Barina [email protected] wrote:

I would like to have the ability of slow-mo in my games and change it
where and when I like (like in some particular events)
Maybe a SPEED member that comes built-in in a Node and other nodes will
have the ability to inherit it (like pause mode) and if it reaches 0 it
will pause the game
And maybe the delta argument in the process function will be multiplied by
SPEED:

func _process(delta):
var time_passed = delta # delta is actually old delta * speed

Or process will have another argument in case you want to know how much
time passed in real time:

func _process(delta, real_delta):
var time_passed = real_delta
var time_passed_in_game = delta

Include _fixed_process too.
The thing is it should affect all child nodes and all type of nodes like
AnimationPlayer, SamplePlayer, Tween, Physics, Particles etc..
That sounds like it could be just implementing something to Node...

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/godotengine/godot/issues/6885, or mute the thread
https://github.com/notifications/unsubscribe-auth/AF-Z28phGbCdFDzIMnjASMVps58vBqXZks5q2AaqgaJpZM4KcvgH
.

Yes there is but it affect the whole tree
What I was thinking about is slow down (or double up) time for individual nodes (and their children) or maybe even create an area so every node (or a scene) entering will scale its time accordingly

@Barina an area with a delta override like the gravity? that would be great (don't know if possible but the idea sounds great)

I'm agreed with this request. Actually I'm tying to make that effects in a project but is hard right now. So please include this feather in the engine.

Just dropping a use case: slow down everything but some nodes, like when players use a special ability.

I read what I wrote above and while it would work on KinematicBodies, Rigidbodies are updated by the engine so you can't control individually which velocity scale they will experience.

As mentioned in #7521, it might behave similarly to pause modes.

Or, maybe it can function as CanvasItem's Opacity Modulate in 3.0 -- with Time scale and Self time scale properties.

I concur - and with the ability to put an "slow-mo" effect on everything inside an Area/Area2D :)

What's the status on this?

@Zireael07 I wanted to tackle it, but never got to it. I guess it should be "pr welcome"

How could be the approach for this?

Should this affect rigid bodies only?
Timescale that alters delta on selected nodes? (including shaders?)
Should affect sound too?

OS.set_time_scale() is not good since it slows down everything. This means that if you want to slow the game for 0.3 seconds real time it's more complicated than it needs to be since you need to actually set the timer to 0.3/slowdown_factor since the clock would also slow down. Good luck changing game speed on a curve and compensating for it then. It requires some non trivial calculus to figure out how to compensate.

Did some investigation. To get most objects to work like this you can just modify Node::get_process_delta_time() to account for some delta_time_fract up the tree like position vs global_position.

The main issues is physics where it doesn't make sense for this to happen in the tree since it isn't clear what happens when things that move in different time scales interact since even though they appear to be moving slower they still have high velocities. It makes more sense for you to just set it for the entire physical world and in any case physics modification is done for areas and not subtrees.

First of all thank you for your report and sorry for the delay.

We released Godot 3.0 in January 2018 after 18 months of work, fixing many old issues either directly, or by obsoleting/replacing the features they were referring to.

We still have hundreds of issues whose relevance/reproducibility needs to be checked against the current stable version, and that's where you can help us.
Could you check if the issue that you described initially is still relevant/reproducible in Godot 3.0 or any newer version, and comment about it here?

For bug reports, please also make sure that the issue contains detailed steps to reproduce the bug and, if possible, a zipped project that can be used to reproduce it right away. This greatly speeds up debugging and bugfixing tasks for our contributors.

Our Bugsquad will review this issue more in-depth in 15 days, and potentially close it if its relevance could not be confirmed.

Thanks in advance.

Note: This message is being copy-pasted to many "stale" issues (90+ days without activity). It might happen that it is not meaningful for this specific issue or appears oblivious of the issue's context, if so please comment to notify the Bugsquad about it.

I'm trying to do slo-mo right now :)

I think it is weird to think about the interaction of objects in different time scales. Eg. one body inside the slo-mo area interacting with another body outside the area. One of the bodies would be half inside and half ouside the area, what would be the correct force-scaling of the body? Maybe you could handle it like a body half in the water and half in the air.

If you think about it in real life (past/future/relativity) it becomes much harder and open to [mis]interpretations.

In practice, it would be enough to be able to scale time of the physics engine, and to be able to modulate the speed of animations, particles, sound, etc. And let the developer tie the scaling as desired :) . To make it easier, things like animations could have checkboxes to "sync with physics time scale", so the developer could opt-in (or out of) it.

I did a little research if you don't mind.

Unreal Engine has a console command slowmo that receives a positive float argument that slows down (when between 0.0 and 1.0) or speeds up (when above 1.0) the entire engine. It does not change the rendering frequency, and does not change the physics loop frequency.

Unity has the Time.timeScale static property which scales the delta time used for frame rendering and for physics loop. But it seems it also slows down the physics loop frequency, and to fix that Time.fixedDeltaTime should be changed together:

Time.timeScale = slowMotionFactor;
Time.fixedDetaTime = slowMotionFactor * 0.02f;  // magic ratio

Another thing that Unity has is the Time.unscaledDeltaTime static property that can be used to do stuff with the "real delta time", such as tweening in to (or out of) the slow motion.


Updating my practical suggestion: I suggest to recover the OS.set_time_scale() method and expose OS.unscaled_process_delta and OS.unscaled_physics_process_delta to be able to access unscaled deltas.

I saw it is possible to scale the speed of animations, particles and tweens, and I can think of fun stuff to do with these plus the time scaling. Maybe one of the few things it would be nice to have is a use_unscaled_time property in the Timer and Tween classes. Or maybe implement separate RealtimeTimer and RealtimeTween classes. For example there could be a countdown timer to constraint the ammount of real-life time the player has to accomplish a certain task. And there could be timers to trigger traps after a certain ammount of in-game-time. And it would be nice to use Tween (in real-life-time) to fade between timescales.

IMO, this is useful in case of showing slow motion of playing but not UI.
like showing the last hit with slow motion but showing result UI in the normal speed.

EDIT: nevermind OS.set_time_scale() is now Engine.time_scale

As @Zylann suggested above, just a separate multiplier to control all _fixed_process calls would be good.

Any updates?
I think this feature is useful

as part of this, I would like to control the time step of each frame so I can do something like:

screengrab
step the game forward 0.1 second
screengrab
.....

to record things at a controlled frame rate.

@Zireael07 I wanted to tackle it, but never got to it. I guess it should be "pr welcome"

Is this still the status of this? If so I can probably dive in and see what needs to get done.

@supagu You can likely achieve this with the --fixed-fps command-line option, which disables real-time synchronization. See this merged pull request for more information.

Update: See godot-video-rendering-demo for an example.

I have an implementation that I have tested and works, but without the inheritance part. That wouldn't be too difficult to add, but before I even bother, can someone help me out with how to do the process of making a pull request? This is my first time doing a public contribution.

@KokaKnut See Pull request workflow in the documentation :slightly_smiling_face:

Feature and improvement proposals for the Godot Engine are now being discussed and reviewed in a dedicated Godot Improvement Proposals (GIP) (godotengine/godot-proposals) issue tracker. The GIP tracker has a detailed issue template designed so that proposals include all the relevant information to start a productive discussion and help the community assess the validity of the proposal for the engine.

The main (godotengine/godot) tracker is now solely dedicated to bug reports and Pull Requests, enabling contributors to have a better focus on bug fixing work. Therefore, we are now closing all older feature proposals on the main issue tracker.

If you are interested in this feature proposal, please open a new proposal on the GIP tracker following the given issue template (after checking that it doesn't exist already). Be sure to reference this closed issue if it includes any relevant discussion (which you are also encouraged to summarize in the new proposal). Thanks in advance!

Was this page helpful?
0 / 5 - 0 ratings