Skip to content
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

Add a setting to force _physics_process() to run in real-time (or flag up when it isn't) #3612

Open
goatchurchprime opened this issue Nov 29, 2021 · 6 comments

Comments

@goatchurchprime
Copy link

Describe the project you are working on

A 2D ping pong networking demo https://github.com/goatchurchprime/godot_multiplayer_networking_workbench

Describe the problem or limitation you are having in your project

A networked ping-pong ball game I am writing depends on the cumulative time from the _physics_process(delta) and the value of OS.get_ticks_msec() to agree.

This very simple piece of code shows how the cumulative time is consistent, until another window is put in front of the godot window for a few seconds.

var cumulativetime = 0.0
var Di = 0
func _physics_process(delta):
	cumulativetime += delta
	Di += 1
	if (Di % 60) == 0:
		print(OS.get_time(), " ", OS.get_ticks_msec()*0.001 - cumulativetime)

Output:

{hour:15, minute:30, second:31} 0.598
{hour:15, minute:30, second:32} 0.599
{hour:15, minute:30, second:33} 0.601
{hour:15, minute:30, second:34} 0.598
{hour:15, minute:30, second:35} 0.598
                _window hidden by another window_
{hour:15, minute:30, second:39} 3.278
{hour:15, minute:30, second:46} 9.294
{hour:15, minute:30, second:54} 16.312
{hour:15, minute:31, second:1} 22.328
               _window at front again_
{hour:15, minute:31, second:3} 24.070999
{hour:15, minute:31, second:4} 24.071999
{hour:15, minute:31, second:5} 24.071999
{hour:15, minute:31, second:6} 24.070999
{hour:15, minute:31, second:7} 24.069999
{hour:15, minute:31, second:8} 24.067999
{hour:15, minute:31, second:9} 24.068999

The problem is I can't find a setting to stop this slow-down from happening, or a signal to detect when it happens so that I can tell my algorithms to stop working and reset during the time when the relationship is not valid.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

The feature would make it easier to write+debug software that depends on the _physics_process() running predictably, or be flagged during periods when the timing is not going to agree.

Usually this applies whenever there is any networking. A single player app slowing down or speeding up doesn't matter. But when there are two players they are usually each going to assume that the other is running at roughly the same rate. A signal from one that it has gone into hidden mode/suspended animation could be transmitted to the other players to explain why the data streaming from it is no longer agreeing.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

A function such as: OS.set_priority(1)

Or a signal in OS that lets the software know that the state has changed between when _phsycis_process() is running properly, and when it is go-slow mode because of something it can't control with the Windows GUI manager.

The problem doesn't happen with the headless version, where there is no window to hide or be seen, so it's always running properly.

If this enhancement will not be used often, can it be worked around with a few lines of script?

It's possible to monitor the cumulative time and trigger my own signal when there is a slippage using the function above.

However, it's harder to detect when the slippage has ended and normal service has resumed. Possibly I have to watch for 5 seconds that the numbers aren't drifting before flagging that everything is back to normal.

Is there a reason why this should be core and not an add-on in the asset library?

This is a core function of the physics engine and timing.

@Calinou
Copy link
Member

Calinou commented Nov 29, 2021

I don't see why this slowdown would occur, especially in _physics_process() which is not affected by Engine.target_fps or the Force Fps project setting. Is low-processor usage mode enabled in your project?

I'm pretty sure Windows does not have built-in power saving mechanics that automatically apply to unfocused windows or windows covered by another window.

That said, for implementing server-authoritative physics with client-side prediction, you're probably looking for #2821 which is a more reliable solution. Fighting the operating system over priority or power saving issues rarely ends well… 🙂

@Calinou Calinou changed the title A setting to force the physics_process() to run in real time -- or flag up when it isn't A setting to force _physics_process() to run in real-time (or flag up when it isn't) Nov 29, 2021
@Calinou Calinou changed the title A setting to force _physics_process() to run in real-time (or flag up when it isn't) Add a setting to force _physics_process() to run in real-time (or flag up when it isn't) Nov 29, 2021
@goatchurchprime
Copy link
Author

I tried to replicate it on Windows. There was no change when the window went in and out of view (behind another window).

However, there is an even worse problem when the window gets minimized... It looks like the _physics_process(delta) runs ahead of the real time by half a second!

1 {hour:9, minute:44, second:18} -0.305
2 {hour:9, minute:44, second:19} -0.305
3 {hour:9, minute:44, second:20} -0.305
4 {hour:9, minute:44, second:21} -0.305
  --- Window minimized
5 {hour:9, minute:44, second:21} -0.14
6 {hour:9, minute:44, second:22} 0.17
7 {hour:9, minute:44, second:23} 0.169
8 {hour:9, minute:44, second:24} 0.169
9 {hour:9, minute:44, second:25} 0.168
   --- Window returned
10 {hour:9, minute:44, second:26} 0.161001
11 {hour:9, minute:44, second:27} 0.161001
12 {hour:9, minute:44, second:28} 0.161001

It's as though the code tries to compensate for the slippage during the minimization process, but gets it wrong.

The problem is intermittent. Sometimes it goes the other way and it loses 0.05seconds instead of gaining time.

It's easy to show this graphically with the following code:

extends Node2D

var cumulativetime = 0.0
var Di = 0

var mfac = 50
var mfacy = 400
var X = [ ]
func _physics_process(delta):
	cumulativetime += delta
	var t = OS.get_ticks_msec()*0.001
	X.append(Vector2(t*mfac, (cumulativetime-t)*mfacy+400))
	Di += 1
	if (Di % 60) == 0:
		print(Di/60, " ", OS.get_time(), " ", cumulativetime - t)
	if Di == 60*10:
		$Line2D.points = PoolVector2Array(X)

image

@Calinou
Copy link
Member

Calinou commented Dec 1, 2021

However, there is an even worse problem when the window gets minimized... It looks like the _physics_process(delta) runs ahead of the real time by half a second!

Please report this on the main Godot repository, and make sure to test this on both 3.3.4 and 3.4 (godotengine/godot#35617 may have introduced a regression here).

@Diddykonga
Copy link

Diddykonga commented Dec 9, 2021

However, there is an even worse problem when the window gets minimized... It looks like the _physics_process(delta) runs ahead of the real time by half a second!

I'm not sure if this is relevant, but could this Engine setting be the issue?
Engine.physics_jitter_fix

@goatchurchprime
Copy link
Author

Minimal example for reference
physics_process_problem.zip

@ChristianKaltenecker
Copy link

Hey,
I had a similar problem in a project of mine as pointed out here in the very first post. I have tried out the minimal example on version 4.2.1 on ArchLinux.
While trying out different settings in my project and in this minimal example, I encountered that disabling V-Sync actually solves the slowdown mentioned in the first post when the window is hidden by another window. While disabling V-Sync in the settings, I get similar delta values now.

Is this intended?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants