-
-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow locking the physics step to the rendered frame rate #10015
Comments
I once used this pattern in my project: extends Node
var should_emit: bool
var timer: float
signal lazy_process
func _process(delta: float) -> void:
timer += delta
if should_emit:
lazy_process.emit(timer)
should_emit = false
timer = 0
func _physics_process(delta: float) -> void:
should_emit = true Called it "lazy process". It allows to write logic in process frame, but synchronized with physics frame. Simply connect to the signal to use it. The timer acts as |
I think this is basically doing the opposite of what I want. This syncs up so process stuff only executes every physics frame. I want physics to execute every process frame. |
My 2 cents as a beginner: 1-update-per-frame seems to be simpler to reason about when learning the engine, I'm puzzled thinking about jittering, interpolation and smoothing add-ons instead of just thinking about my "game". Expanding on your idea: If you have the option for 1-update-per-frame, what about a lower and upper bound, for minimum and maximum physics FPS regardless of your FPS? Without flooding your proposal, here is my ideal solution (a superset of what I described).
|
I don't understand this issue 100%, if you want physics to happen at every process frame, can't you just use the The only problem I see is the user with a varying framerate without Vsync and you wanting to execute physics per process frame, but then again having the physics frame per second capped to the user's max monitor refresh rate would solve this,
This to me doesn't make sense, only if your frames per second is < physics framerate, but if perfomance is the issue and you want to update enemies at different intervals, we could optmize by allowing objects to skip processing entirely, this allows you to update them at different intervals inside the physics processing function, something like this:
|
This should already be achievable by setting Physics Ticks per Second to 1000 and Max Physics Steps per Frame to 1 in the Project Settings (or 2 if you want 2 iterations per frame). However, slowdown will occur if the physics tick rate can't be met, so there would need to be a setting to disable this behavior. You can set Physics Ticks per Second above 1,000 with a script if needed. |
That's effectively what I want, but the _physics_process() and _process() happen at different times in the engine update. _process() happens after things like animation, which is useful to do things like post-anim bone corrections and such, but it means if you put your gameplay logic in _process() all the feedback is going to be delayed by an extra frame. I want the equivalent of _process() that gets called when the _physics_process() does. I think there are some other things that are bad to do outside of the physics frame as well, like moving physics bodies and such.
This just makes the game run in slow motion. If you don't meet the physics framerate, the game slows down to compensate. Also, I think it might be good to have a set physics tick rate for things like rigid body simulations, so we have consistency, but the per-frame physics update would be called every frame in addition to that, so you could optionally do additional per-frame calculations and stagger them in your own way. So something like:
This would allow:
One drawback I can see is that certain things, like move_and_slide() and is_input_just_pressed() are tied specifically to if they're updating in the physics or process updates, and this new function would be ambiguous. |
I'm assuming you're looking for something like Unity's jobs system? I feel like having some form of deferred staggered callback or multithreading mechanism would be preferable to adding another process function to Node. I think having both
This is a very confusing name. First, what do you mean by frames? Display frames (what Godot calls idle)? That should be made explicit upfront. When I think of game logic frames, I usually think physics frames, not display frames. Second, the whole point of Aside: if you just want basic staggered updates of objects, you could do that using something like this: const UPDATE_RATE = 0.1;
# Could vary this across all your objects so they don't all update at once
var update_timer := 0.0;
func _physics_process(delta: float) -> void:
update_timer += delta;
if update_timer >= UPDATE_RATE:
update_timer -= UPDATE_RATE;
do_intensive_thing(); Admittedly retro, but it won't cause unexpected behavior between two machines running at different framerates. |
This comment was marked as resolved.
This comment was marked as resolved.
That's what I'm currently doing. The issue is that it doesn't stagger things evenly across rendered frames, only physics frames, and given that some physics can update 0-(8?) times per rendered frame, even if things are staggered within the physics frame, they can be heavily clustered on different render frames. So say your physics tick rate is set to 60 and you're rendering on a 120hz monitor. Every other frame is going to have a physics update, which, if the physics update rate is slow, could mean you have every other frame is like twice as long (or more), making the game feel stuttery even if the average framerate is 120. When you turn the camera every other frame takes longer to process so it's not a consistent turn speed. Alternatively, you could drop to sub-60 FPS where some frames are doing 2 physics updates per frame. Being able to distribute the physics load so it's not alternating between 2x and 1x would make the framerate a bit more smooth. I'm not sure what the ideal solution is. I could just put everything in the _process() function with staggering to distribute the stuff across multiple frames, but that would mean things like character movement would be happening after the physics update and also systems like animation, so animations would be delayed 1 frame from when I told them to play. Alternatively, maybe we could fix the physics performance so this wouldn't be necessary: godotengine/godot#93184 |
Describe the project you are working on
Retro FPS with lots of enemies active at once.
Describe the problem or limitation you are having in your project
Updating 100+ enemies every physics tick has huge performance issues, especially if physics update multiple times per frame. See: godotengine/godot#93184
It would be good to stagger the physics updates of things across multiple frames. For example, 5 enemy updates per frame, prioritized by distance, velocity, etc.
The problem is, the physics update at a set rate, which means if I have the physics updating at 60 hz and the user is running at 120hz, they'll only update enemies every other frame, and if players are running at 30fps, they'll be doing 10 enemy updates per frame instead of 5, which further hurts performance on a machine that's already struggling.
Right now the _physics_process() stuff is all or nothing. Either everything updates every physics update, or nothing does.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
Having a guaranteed physics update (or an update while the engine is in physics mode, _in_physics = true) will allow me to do staggered updates in a controlled manner such that the workload for large numbers of enemies is spread across multiple frames.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
What I want is an (optional) physics update call that happens every frame. This could possibly be in addition to the regular _physics_process() or an option to make _physics_process() run every frame instead of at a fixed rate.
So currently we have something in the main loop like:
What I'm proposing is something like:
This would add a new function that executed every frame prior to animations and such that could optionally be used instead of the _physics_process on scripts where I want to control things at varying rates.
Or:
This would add an option to allow the physics to update every single frame at whatever the framerate is at.
This is very similar to the semi-fixed timestep proposal: #236
It's also similar to the late physics process: #6795
And relevant to the swarm/mob proposal: #2380
And the different physics update rates at the same time: #439
Edit: Also found this issue which probably more clearly states the issues but was in the main repo, not the proposals, so it got closed: godotengine/godot#24769
So maybe it's not entirely necessary as a separate proposal, but I do want to have some way to guarantee an update while the engine is in physics mode every frame. The semi-fixed one seems like it would do 2 physics updates per frame, but maybe if the physics tick rate was set to 20hz or something, that would mean only one update per frame. Likely resolving one of these proposals would also address a handful of others.
If this enhancement will not be used often, can it be worked around with a few lines of script?
It's possible an autoload could handle this in _process(), but I'm not sure if that is the appropriate place to do things like move enemies around, and ideally this would happen before the animations play so there's not a delay in feedback. Could be possible, though.
Is there a reason why this should be core and not an add-on in the asset library?
This needs to be in the core loop of the engine in order to do per-frame updates in the physics.
The text was updated successfully, but these errors were encountered: