Open TheContainer opened 9 months ago
This was also proposed in https://github.com/godotengine/godot-proposals/issues/7775, but I'll leave this one open as to make the discussion more specific in this proposal.
with physics movement for example, you can't.
You can, by modifying the delta
. Though it's not possible with move_and_slide()
until https://github.com/godotengine/godot/pull/84665
I sorta agree with this, but I wonder if it could be expanded to be a float multiplier, instead of a boolean. The problem with both solutions may hurt performance a bit even for nodes that are set to the default.
I had a need for this exact thing, and in the end I just did this (I'm in .NET world so I'll show a C# example, but I imagine this is perfectly doable in GDScript)
Create an Autoload (in my example, FrameTimer
). Define an event
and a DateTime
private field:
public partial class FrameTimer : Node
{
public static event Action<double> FrameRendered;
private DateTime _lastFrameDt;
}
In that Autoload's _EnterTree()
, set your _frameTimeDt
initial value, and hook the RenderingServer
's FramePostDraw
event, which you'll use to calculate the delta:
public override void _EnterTree()
{
_lastFrameDt = DateTime.Now;
// Hook the event with a lambda (or assign an Action delegate)
RenderingServer.FramePostDraw += () => {
var now = DateTime.Now;
var delta = (now - _lastFrameDt).TotalSeconds;
_lastFrameDt = now; // Set your last frame time to now
FrameRendered?.Invoke(delta); // safely invoke the event (does nothing if not hooked)
};
}
And that's pretty much it... Now all you have to do is in any script where you want the delta independent of Engine.TimeScale
, just define a handler, and in your _EnterTree()
or _Ready()
, hook the event in FrameTimer
(or whatever you called it) and use that handler instead of _Process(double delta)
:
public partial class SomeClass : Node
{
/*... other class stuff ...*/
public override void _Ready()
{
FrameTimer.FrameRendered += TimeScaleIndependent_Process;
// other _Ready() stuff...
}
private void TimeScaleIndependent_Process(double delta)
{
// whatever you want to do independent of Engine.TimeScale
}
/*... other class stuff ...*/
}
The one caveat to this advice: I've literally been using Godot for like, 3 weeks and am not fully aware of any subtleties I may be tripping over - but this seems to be working just fine for me so far.
I sorta agree with this, but I wonder if it could be expanded to be a float multiplier, instead of a boolean. The problem with both solutions may hurt performance a bit even for nodes that are set to the default.
This was proposed before and rejected: https://github.com/godotengine/godot/pull/29861
Describe the project you are working on
A 3D sandbox game where you will be able to slow down time around you but not yourself.
Describe the problem or limitation you are having in your project
With
Engine.time_scale
, you can slow down time, but you can't add exceptions, which means that not only you as the Player will be in slowmotion speeds (which I don't want), but also every UI element.Describe the feature / enhancement and how it helps to overcome the problem or limitation
Each node will have a boolean variable, and when this variable is set to true, the time_scale variable will be ignored, and the node will run at normal speed, similar to
process_mode.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
The variables value can be changed in the property editor of the node, maybe in the "process" tab.
If this enhancement will not be used often, can it be worked around with a few lines of script?
For simple animations, tweens for example, you can balance the speed out with some math manually, to give it the illusion of ignoring the
time_scale
value, but with physics movement for example, you can't.Is there a reason why this should be core and not an add-on in the asset library?
This is very useful overall and belongs to the core in my opinion.