Open-Source Wikis

/

Godot

/

Godot Engine

/

Architecture

godotengine/godot

Architecture

Godot is a layered C++ engine. The layers, from foundation to surface, are: core (object/variant/math/IO), servers (rendering, physics, audio, navigation, display, text, XR), scene (the scene tree and built-in node types), modules (optional engine extensions, including the scripting languages), drivers (platform-specific I/O backends), platform (per-OS entry points and OS abstraction), and editor (built on top of everything else, only included in tool builds).

This page summarizes how those layers connect. Each subsystem has a dedicated page under systems/.

Top-level layout

graph TD
    Platform["platform/<br/>per-OS entry, OS_* impl"] --> Main["main/<br/>Main::setup, setup2, iteration"]
    Main --> Core["core/<br/>Object, Variant, ClassDB, math, IO, OS"]
    Main --> Servers["servers/<br/>Rendering, Physics, Audio, Navigation,<br/>Display, Text, XR"]
    Servers --> Drivers["drivers/<br/>vulkan, d3d12, metal, gles3,<br/>alsa, wasapi, coreaudio, …"]
    Main --> Scene["scene/<br/>SceneTree, Node, Viewport, Window,<br/>2D / 3D / GUI / Animation / Audio nodes"]
    Scene --> Servers
    Modules["modules/<br/>gdscript, mono, gltf, openxr,<br/>jolt_physics, multiplayer, …"] --> Core
    Modules --> Scene
    Modules --> Servers
    Editor["editor/<br/>Project manager, EditorNode, docks,<br/>importers, exporters"] --> Scene
    Editor --> Modules

The arrows reflect "depends on / calls into" — core/ does not import any of the higher-level layers; editor/ is at the top and is compiled out when the engine is built as an export template (tools=no).

Boot sequence

Boot is split between a platform-specific entry point and the cross-platform Main class.

sequenceDiagram
    participant OS as platform/<os>/godot_os.cpp
    participant Main as main/main.cpp
    participant Core as core/
    participant Servers as servers/
    participant Scene as scene/
    participant Editor as editor/

    OS->>Main: Main::setup(execpath, argc, argv)
    Main->>Core: register_core_types()
    Main->>Core: ProjectSettings, GlobalConstants, Input
    Main->>OS: OS::initialize(), DisplayServer::create()
    OS-->>Main: window, GL/Vulkan/D3D12 context
    Main->>Main: Main::setup2()
    Main->>Servers: RenderingServer / PhysicsServer / AudioServer init
    Main->>Scene: register_scene_types(), SceneTree
    Main->>Editor: register_editor_types() (tool builds only)
    Main->>Main: Main::start()
    loop frame
        OS->>Main: iteration()
        Main->>Scene: SceneTree::process(delta)
        Main->>Servers: physics / audio / rendering steps
    end
    OS->>Main: Main::cleanup()

The split between setup() and setup2() exists because the display server (and therefore the rendering server) cannot be initialized until command-line options have been parsed, but setup2() may have to run on a different thread on some platforms. The comment in main/main.h notes that "The thread calling setup2() will effectively become the main thread."

The "server" pattern

A consistent pattern across Godot is that heavyweight subsystems expose two faces:

  1. A server in servers/ that defines the public API and a thread-safe wrapper (*ServerWrapMT) that marshals calls onto the dedicated server thread when running in multi-threaded mode.
  2. A driver/backend in drivers/ (or a server-internal renderer in servers/rendering/) that implements the API against a concrete graphics or platform library.

Examples:

Server API in Built-in backends
RenderingServer servers/rendering/ Forward+/Mobile/Compatibility renderers; RD backend in servers/rendering/renderer_rd/ over drivers/vulkan,d3d12,metal; GL backend in drivers/gles3
PhysicsServer3D servers/physics_3d/ modules/godot_physics_3d (built-in) and modules/jolt_physics (Jolt)
PhysicsServer2D servers/physics_2d/ modules/godot_physics_2d
AudioServer servers/audio/ drivers/alsa,pulseaudio,wasapi,coreaudio,xaudio2
DisplayServer platform-owned platform/<os>/display_server_<os>.cpp
NavigationServer servers/navigation_2d, servers/navigation_3d recast-based, single backend
TextServer servers/text/ modules/text_server_adv (HarfBuzz + ICU + FreeType), modules/text_server_fb (FreeType only)
XRServer servers/xr/ modules/openxr, modules/mobile_vr, modules/webxr

This pattern keeps the public API stable, lets the engine pick a backend at runtime (e.g., choose Vulkan or GL based on the rendering driver setting), and isolates threading so most engine code can stay single-threaded.

See Servers and the multi-threaded wrapper for details.

The Object/Variant/ClassDB triumvirate

Godot has its own RTTI and reflection system. The three pieces:

  • Object (core/object/object.h) — the universal base class. Owns properties, signals, _get/_set/_call virtual hooks, an ObjectID, and the script instance pointer. Almost everything that lives in the editor or a scene derives from Object.
  • ClassDB (core/object/class_db.h) — a registry that maps class names → constructors, methods, properties, signals, and inheritance. Built up by ClassDB::bind_method / ClassDB::add_property calls in static _bind_methods() functions per class. Drives serialization, scripting, and the editor inspector.
  • Variant (core/variant/variant.h) — a tagged union over ~30 built-in types (NIL, BOOL, INT, FLOAT, STRING, VECTOR2/3/4, RECT2, BASIS, TRANSFORM, COLOR, NODE_PATH, RID, CALLABLE, SIGNAL, OBJECT, DICTIONARY, ARRAY, packed array variants, …). It is the unit of currency between scripts and engine code.
graph LR
    Script["GDScript / C# / GDExtension"] -->|Variant args| MethodBind["MethodBind"]
    MethodBind -->|invokes| ObjectMethod["Object::method"]
    ObjectMethod -->|return Variant| MethodBind
    MethodBind -->|Variant| Script
    ClassDB -.registers.- MethodBind
    ClassDB -.registers.- Property["PropertyInfo"]
    Property -.exposes.- Inspector["Editor inspector"]

MethodBind is generated by templates in core/object/method_bind_common.h plus make_virtuals.py. Almost every engine class has a static void _bind_methods() that registers its scripting surface. The editor inspector reads PropertyInfo and ClassDB::get_property_list to draw fields without per-class UI code.

See Core foundations for the full breakdown.

Scene tree and main loop

The runtime is driven by a MainLoop subclass. In normal operation, that subclass is SceneTree (scene/main/scene_tree.cpp). Each frame, SceneTree:

  1. Calls Window::_process_window_messages and propagates input through Viewport::push_input.
  2. Invokes _physics_process callbacks at a fixed timestep (driven by main/main_timer_sync.cpp).
  3. Invokes _process callbacks at the variable frame rate.
  4. Updates the Tween system, the SceneTreeFTI (fixed-timestep interpolator) for smooth rendering between physics ticks, and timers.
  5. Flushes any deferred calls / message queue (core/object/message_queue.h).
  6. Asks the RenderingServer to render the registered viewports; the server queues commands that the rendering thread executes.

Node (scene/main/node.cpp, ~130 KB) is the largest single source file in the scene layer. It owns parenting, grouping, signals, processing, multiplayer authority, and the path/NodePath resolution that scripts use to address nodes.

See Scene tree and nodes.

Editor architecture

The editor is a Godot project itself: it is built out of Control-derived nodes living in a SceneTree, with a singleton EditorNode (editor/editor_node.cpp, ~377 KB — the largest .cpp in the repo) orchestrating docks, plugins, the inspector, the scene tree dock, the file system dock, and the main editor screens.

Highlights:

  • EditorPlugin is the extension point. Each major editing surface (the 2D editor, 3D editor, script editor, shader editor, asset library, project manager) is implemented as one or more plugins under editor/plugins/.
  • Importers (editor/import/) wrap the engine's resource importers to produce .import metadata for source assets (textures, audio, models). The gltf importer comes from modules/gltf; the fbx importer comes from modules/fbx via FBX-to-glTF conversion.
  • Export templates (editor/export/) define how a project is packaged for each platform. Per-platform export logic lives in platform/<os>/export/.

See Editor architecture.

Build system

SConstruct is the entry point. SCons is invoked with command-line keys (e.g., scons platform=linuxbsd target=editor module_mono_enabled=yes). The build:

  1. Resolves the platform from platform/<name>/detect.py.
  2. Walks each top-level subdir's SCsub to enumerate sources.
  3. Generates code at build time: shader glue (gles3_builders.py, glsl_builders.py), virtual method binding glue (make_virtuals.py), localization data, encryption keys, and the script class lists.
  4. Optionally enables single-compilation-unit mode (scu_builders.py) to speed up builds by concatenating files.

The engine produces one executable. There is no shared library split — modules are compiled in. Disabling a module is done via module_<name>_enabled=no (or via modules_enabled.gen.h once SCons has picked the active set).

Cross-cutting features

Some capabilities span multiple layers and don't fit a single subsystem page. They are documented as features:

  • Scripting — GDScript (modules/gdscript), C# (modules/mono), and the GDExtension C ABI in core/extension/.
  • Resource I/OResourceLoader/ResourceSaver plus per-format loaders in core/io/ and scene/resources/.
  • Multiplayermodules/multiplayer implements RPC, scene replication, and high-level peer abstractions over ENet/WebSocket/WebRTC.
  • XRmodules/openxr, modules/mobile_vr, modules/webxr plug into XRServer.

Where data lives at rest

At runtime, the most important singletons (registered through Engine::get_singleton) are:

Singleton File Role
Engine core/config/engine.cpp Frame counters, target FPS, time scale, build info
OS core/os/os.cpp + per-platform os_*.cpp OS abstraction (file system, clipboard, processes, environment)
ProjectSettings core/config/project_settings.cpp Reads/writes project.godot, exposes setting overrides per feature tag
Input core/input/input.cpp Aggregates InputEvents across DisplayServer, joypads, and remap
RenderingServer servers/rendering_server.cpp Public rendering API
PhysicsServer3D, PhysicsServer2D servers/physics_* Physics public API
AudioServer servers/audio_server.cpp Audio mixing graph
DisplayServer servers/display_server.cpp Window + input from OS
NavigationServer3D, NavigationServer2D servers/navigation_server_* Navigation meshes/agents
TextServerManager servers/text_server.cpp Active TextServer + secondary servers
XRServer servers/xr_server.cpp XR origin/cameras/trackers

These are created in Main::setup/Main::setup2 and torn down in Main::cleanup.

Threading model

  • Main thread runs the scene tree, scripting, and most engine logic.
  • Rendering thread (when the project setting rendering/driver/threads/thread_model is Multi-Threaded) is the only thread allowed to talk to the GPU; all other threads enqueue commands via the RenderingServerWrapMT shim.
  • Server threads for physics and audio mix on dedicated threads where applicable.
  • Worker thread pool (core/object/worker_thread_pool.cpp) handles shorter-lived parallel tasks: resource loading, baking, navigation, lightmapping. Tasks can be submitted as groups for fork-join parallelism.

The MessageQueue (core/object/message_queue.cpp) is how nodes call methods on each other across thread boundaries via call_deferred, and how set_deferred defers property writes until the end of the frame.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Architecture – Godot wiki | Factory