Godot Version
4.3 (latest)
Question
Hi, I’m new here! I’m a seasoned programmer - got 2 decades of backend development under my belt - but I’ve always found game development fascinating and would like to try and make my first game in Godot. So I’m reading up on how things work, but there’s one fundamental piece I cannot wrap my head around. To clarify - I’m starting with 2D, but I think my question is valid for 3D as well.
What does the core game loop look like in Godot? The one that’s behind the scenes.
I feel like understanding this is crucial to figuring out what goes where and how to structure my own code. I have a mental model of how I think it should work; it’s how I would do it - but reading between the lines in various articles it seems that this is NOT how it works in reality.
Here’s what it looks like in my head. Can you spot my mistake?
There is one “game state” in the memory. That is a list of all the game objects with their properties. You have your player character, enemies, world objects, etc. They have relationships between each other, positions in the game world, state, whatever. Full description of what is where and doing what.
Then, as long as the game is running, you repeat this loop:
- Checkpoint. Note down the timestamp of this iteration.
- Compare the timestamp of this iteration with the timestamp of the previous iteration. This gives you your delta time. It’s the time elapsed between the starts of each iteration.
- Read inputs and update input map (possibly optional. depends on what API you’re using for input)
- Go through all your game objects and check which ones need some updating. Maybe something needs to move, maybe something needs to react to the inputs, whatever. Update your model accordingly. In the end the model is in the state which it should be in at the timestamp which you obtained at start of the iteration. The delta time is useful in this step, because you know that when you started, the model was in the state that was exactly <delta time> ago.
- Show! Don’t change the model anymore, just figure out what needs to be drawn and draw it to the screen. Possibly also start/stop sounds playing, although that might have been done in the previous step too. In the end, what you get on the screen is your model, as it was supposed to look like at the start of the iteration. If vsync is enabled, you might also wait here until the frame is sent to the screen. Or, if triple-buffering is enabled (which it should be by default these days, I think), you can just schedule that frame to be shown later and move on.
- Rinse and repeat.
I know that this is not the case in Godot, because physics processing is doing its own thing at a “framerate” different than drawing. I’m guessing that multithreading is involved there, because otherwise I cannot see how that could be reasonably pulled off on a single thread.
But how can it be if there is just one model in the memory? You can’t change the model while it’s being drawn. Does Godot duplicate the whole game state, process the physics on the copy, and then flip it in before the next drawing iteration? Is there some sort of copy-on-write going on? And if so, what copies of the model are seen in which callbacks? I’m guessing that at the least _process()
and _physics_process()
would need to see different realities then. And what about other events?
What’s going on here?