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 --> ModulesThe 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:
- 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. - A driver/backend in
drivers/(or a server-internal renderer inservers/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/_callvirtual hooks, anObjectID, and the script instance pointer. Almost everything that lives in the editor or a scene derives fromObject.ClassDB(core/object/class_db.h) — a registry that maps class names → constructors, methods, properties, signals, and inheritance. Built up byClassDB::bind_method/ClassDB::add_propertycalls 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:
- Calls
Window::_process_window_messagesand propagates input throughViewport::push_input. - Invokes
_physics_processcallbacks at a fixed timestep (driven bymain/main_timer_sync.cpp). - Invokes
_processcallbacks at the variable frame rate. - Updates the
Tweensystem, theSceneTreeFTI(fixed-timestep interpolator) for smooth rendering between physics ticks, and timers. - Flushes any deferred calls / message queue (
core/object/message_queue.h). - Asks the
RenderingServerto 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:
EditorPluginis 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 undereditor/plugins/.- Importers (
editor/import/) wrap the engine's resource importers to produce.importmetadata for source assets (textures, audio, models). Thegltfimporter comes frommodules/gltf; thefbximporter comes frommodules/fbxvia FBX-to-glTF conversion. - Export templates (
editor/export/) define how a project is packaged for each platform. Per-platform export logic lives inplatform/<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:
- Resolves the platform from
platform/<name>/detect.py. - Walks each top-level subdir's
SCsubto enumerate sources. - 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. - 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 incore/extension/. - Resource I/O —
ResourceLoader/ResourceSaverplus per-format loaders incore/io/andscene/resources/. - Multiplayer —
modules/multiplayerimplements RPC, scene replication, and high-level peer abstractions over ENet/WebSocket/WebRTC. - XR —
modules/openxr,modules/mobile_vr,modules/webxrplug intoXRServer.
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_modelisMulti-Threaded) is the only thread allowed to talk to the GPU; all other threads enqueue commands via theRenderingServerWrapMTshim. - 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.