Core Concepts
Teaching an old robot new tricks!
Inverted Architecture
Traditional Godot applications have Godot control the process lifecycle:
Godot Process → SceneTree → Your Scripts2dog inverts this:
Your .NET Process → twodog.Engine → Godot (as library)Your .NET process controls startup, frames, and shutdown. Godot becomes a rendering, physics, and audio library that your application drives.
libgodot Embedding
2dog uses libgodot, a shared-library build of Godot Engine. It runs inside your .NET process, supports direct P/Invoke calls to native APIs, and retains full access to GodotSharp managed bindings.
The native library (libgodot.dll, libgodot.so, or libgodot.dylib) ships in the 2dog.win-x64, 2dog.linux-x64, or 2dog.osx-arm64 NuGet package. 2dog.engine references the appropriate packages automatically.
Build Variants
Generated hosts map .NET configurations to Godot variants with TwoDogVariant. Other projects must configure this mapping explicitly.
Template Builds (Runtime-Only)
Template Debug (template_debug) includes assertions and additional error checking, but no editor features. Use it for development.
Template Release (template_release) is optimized for production, without debug symbols or editor features.
Editor Build (Development Tools)
Editor (editor) enables TOOLS_ENABLED, the resource-import pipeline, and editor APIs such as EditorInterface, EditorPlugin, and ImportPlugin. It is larger and slower than template builds.
Choosing a Build Variant
Build Configurations is the complete guide to choosing and configuring variants. Resource import selects the editor variant automatically; see Resource Import.
# Scaffolded projects use these mappings:
dotnet build -c Debug # template_debug
dotnet build -c Release # template_release
dotnet build -c Editor # editor with TOOLS_ENABLEDGodotSharp API Access
After startup, the full GodotSharp API is available:
using var engine = new Engine("app", "./project");
using var godot = engine.Start();
// Access the scene tree
SceneTree tree = engine.Tree;
// Load and instantiate scenes
var scene = GD.Load<PackedScene>("res://my_scene.tscn");
var instance = scene.Instantiate();
tree.Root.AddChild(instance);
// Use any Godot API
var viewport = tree.Root.GetViewport();
var physics = PhysicsServer3D.Singleton;The Main Loop
Unlike traditional Godot, the host explicitly pumps the main loop:
while (!godot.Iteration())
{
// Godot processes physics, rendering, input, and your frame logic here.
if (someCondition)
break; // Exit when you decide
}Iteration() returns true when Godot wants to quit, such as when the window closes.
Single Instance Limitation
Only one Godot instance can run per assembly load context at a time. Sequential restart is supported. See Single Godot Instance for examples and the experimental isolated-hosting path.
Resource Paths
Godot resolves res:// paths relative to the project directory passed to Engine:
// Project at ./my_project
new Engine("app", "./my_project");
// res://scenes/main.tscn → ./my_project/scenes/main.tscn
var scene = GD.Load<PackedScene>("res://scenes/main.tscn");