godotengine / godotengine/godot

Enabling both `process_in_physics` and `ignore_timescale` on a SceneTreeTimer causes timer slowdown at high framerates

Open
#94,355 1 comment 0 reactions 0 assignees View on GitHub
bug topic:core
Dominant language
C++
Stars
117k
Forks
26.8k
PR merge metrics
PR metrics pending

Description

### Tested versions

4.3-beta3, 4.3.stable

### System information

Windows 10.0.22631 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 4060 Laptop GPU (NVIDIA; 31.0.15.5152) - 13th Gen Intel(R) Core(TM) i7-13700H (20 Threads)

### Issue description

When creating a SceneTreeTimer via `get_tree().create_timer()`, setting both `process_in_physics` and `ignore_timescale` makes the timer take longer to complete if your framerate is higher than the physics tick rate. This does not happen if you enable either individually, only when both are enabled at once.

For example: if I were to make a project with a tick rate of 60 and a maximum framerate of 60, a 0.1 second timer with both of these parameters enabled takes roughly 100ms to complete when timed with `Time.get_ticks_msec()`. If I increase the max framerate to 240, it will now take roughly 400ms (4x longer than it's supposed to). The amount of time the timer takes to complete seems to be equal to the max FPS divided by the tick rate.

### Steps to reproduce

A setup to reproduce the bug has been provided in the MRP. Instructions on how to use it are also shown in the project.

If you want to reproduce it on your own, you can do so with this function:
```gdscript
func start_timer() -> void:
var start = Time.get_ticks_msec()
await get_tree().create_timer(0.1,true,true,true).timeout
var end = Time.get_ticks_msec()
print(end-start)
```
Just don't execute it from `_ready()`, since there will be a bit of lag from loading the scene that throws the timing off.

### Minimal reproduction project (MRP)

[mrp-timer-framerate-issue.zip](https://github.com/user-attachments/files/17162223/mrp-timer-framerate-issue.zip)

Contributor guide

Open the contributing guide

Research direction

Start with the provided MRP and the `start_timer()` entry point, then reproduce the timing difference while changing the maximum framerate and physics tick rate. Trace `get_tree().create_timer(0.1, true, true, true)` through the SceneTreeTimer implementation. Done means the timer completes near the requested duration when both `process_in_physics` and `ignore_timescale` are enabled, regardless of framerate.

Written by the indexing model from the issue text.

Assessment

Domain
game-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.