Work in progress

The content of this page was not yet updated for Godot 4.1 and may be outdated. If you know how to improve this page or you can confirm that it's up to date, feel free to open a pull request.

Optimization using Servers

Engines like Godot provide increased ease of use thanks to their high level constructs and features. Most of them are accessed and used via the Scene System. Using nodes and resources simplifies project organization and asset management in complex games.

There are, of course, always drawbacks:

  • There is an extra layer of complexity.

  • Performance is lower than when using simple APIs directly.

  • It is not possible to use multiple threads to control them.

  • More memory is needed.

In many cases, this is not really a problem (Godot is very optimized, and most operations are handled with signals, so no polling is required). Still, sometimes it can be. For example, dealing with tens of thousands of instances for something that needs to be processed every frame can be a bottleneck.

This type of situation makes programmers regret they are using a game engine and wish they could go back to a more handcrafted, low level implementation of game code.

Still, Godot is designed to work around this problem.

See also

You can see how using low-level servers works in action using the Bullet Shower demo project

Servers

One of the most interesting design decisions for Godot is the fact that the whole scene system is optional. While it is not currently possible to compile it out, it can be completely bypassed.

At the core, Godot uses the concept of Servers. They are very low-level APIs to control rendering, physics, sound, etc. The scene system is built on top of them and uses them directly. The most common servers are:

Explore their APIs and you will realize that all the functions provided are low-level implementations of everything Godot allows you to do.

RIDs

The key to using servers is understanding Resource ID (RID) objects. These are opaque handles to the server implementation. They are allocated and freed manually. Almost every function in the servers requires RIDs to access the actual resource.

Most Godot nodes and resources contain these RIDs from the servers internally, and they can be obtained with different functions. In fact, anything that inherits Resource can be directly casted to an RID. Not all resources contain an RID, though: in such cases, the RID will be empty. The resource can then be passed to server APIs as an RID.

Warning

Resources are reference-counted (see RefCounted), and references to a resource's RID are not counted when determining whether the resource is still in use. Make sure to keep a reference to the resource outside the server, or else both it and its RID will be erased.

For nodes, there are many functions available:

  • For CanvasItem, the CanvasItem.get_canvas_item() method will return the canvas item RID in the server.

  • For CanvasLayer, the CanvasLayer.get_canvas() method will return the canvas RID in the server.

  • For Viewport, the Viewport.get_viewport_rid() method will return the viewport RID in the server.

  • For 3D, the World3D resource (obtainable in the Viewport and Node3D nodes) contains functions to get the RenderingServer Scenario, and the PhysicsServer Space. This allows creating 3D objects directly with the server API and using them.

  • For 2D, the World2D resource (obtainable in the Viewport and CanvasItem nodes) contains functions to get the RenderingServer Canvas, and the Physics2DServer Space. This allows creating 2D objects directly with the server API and using them.

  • The VisualInstance3D class, allows getting the scenario instance and instance base via the VisualInstance3D.get_instance() and