-
-
Notifications
You must be signed in to change notification settings - Fork 101
Description
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:
physics_step = physics_ticks_per_second
for 0 to physics_steps:
in_physics = true
physics_process(physics_step)
in_physics = false
process(delta)
What I'm proposing is something like:
physics_step = physics_ticks_per_second
for 0 to physics_steps:
in_physics = true
physics_process(physics_step)
in_physics = false
in_physics = true
physics_frame_process(delta)
in_physics = false
process(delta)
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:
if !fixed_physics:
in_physics = true
physics_process(delta)
in_physics = false
else:
physics_step = physics_ticks_per_second
for 0 to physics_steps:
in_physics = true
physics_process(physics_step)
in_physics = false
process(delta)
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.