twodog.Engine
Configures, starts, and owns one embedded Godot instance.
public class Engine : IDisposable, IAsyncDisposablePackage: 2dog.engine
Namespace: twodog
Constructor
public Engine(string project, string? path = null, params string[] args)| Parameter | Description |
|---|---|
project | Label passed as Godot's first argument; this is not a content path |
path | Directory containing project.godot; omit it for automatic content resolution |
args | Additional Godot command-line arguments, passed unchanged |
When path is omitted or null, desktop hosts call ResolveContent(). Browser hosts leave the path unset so Godot loads the web pack. Pass a path only for a nonstandard content location. Relative paths are resolved from the process working directory.
Properties
Tree
public SceneTree Tree { get; }Returns the active scene tree. Access it only after Start() succeeds.
NativePath
public string? NativePath { get; init; }Loads an exact desktop libgodot file instead of selecting a packaged variant. Leave this unset in normal hosts. It is not supported in the browser.
ProjectAssemblyDir
public string? ProjectAssemblyDir { get; init; }Sets the preferred directory for the game's C# assembly. The default is AppContext.BaseDirectory; custom isolated hosts may need a different path.
LoadedNativePath
public static string? LoadedNativePath { get; }Returns the full path of the loaded desktop libgodot, when known.
Completion
public Task Completion { get; }Completes when this Engine reaches a terminal state. If Start() succeeded, that means the owned native instance has been destroyed and synchronous Exited handlers have returned. Asynchronous work started by those handlers is not awaited. Shutdown restores the host synchronization context before notifying Exited, so subsequent host awaits do not depend on Godot's stopped frame loop.
Exited
public event Action? Exited;Fires once after a successfully started instance is destroyed. Completion also completes for an Engine disposed before it starts, but Exited does not fire.
Methods
Start
public GodotInstance Start()Starts Godot and the project's run/main_scene, then returns a borrowed GodotInstance compatibility handle. Engine owns the instance; do not dispose the handle. Starting another instance before completion throws InvalidOperationException.
Iteration
public bool Iteration()Processes one main-loop frame. Returns true when Godot requests exit. Dispose the engine after the pump stops. Calling Iteration() recursively, or while Run() owns the pump, throws InvalidOperationException.
RequestQuit
public void RequestQuit()Requests a graceful quit. Repeated requests are harmless.
Run
public void Run(Action? perFrame = null)Runs the main loop after Start().
- On desktop, it blocks until Godot requests exit.
perFrameruns after each completed frame that did not request exit. - In the browser, it registers the Emscripten main loop and returns immediately.
Dispose
public void Dispose()Stops and destroys the owned instance synchronously on desktop. In a browser, Dispose() requests shutdown and returns before teardown; use DisposeAsync() or await Completion.
DisposeAsync
public ValueTask DisposeAsync()Requests shutdown and waits for teardown. Prefer this in browser hosts.
Lifecycle calls and Godot object access belong on the thread that called Start(). Calls from another thread are rejected; dispatch them to the host's engine thread. Disposal from a game callback is deferred until the native frame returns. Do not synchronously wait for Completion inside that callback.
WebExitRuntimeOnQuit
public static bool WebExitRuntimeOnQuit { get; set; }Defaults to false in a browser: quitting destroys Godot and keeps .NET alive so any host can start another engine. Standalone pages may set it to true to terminate the entire WebAssembly runtime on quit. Blazor keeps it false. Browser restarts require a fresh canvas and host configuration before Start(); GodotView handles those browser resources automatically.
ResolveContent
public static string? ResolveContent()Returns null when a .pck named after the executable sits beside it, letting Godot load that pack. Otherwise, returns ResolveProjectDir(). The desktop constructor calls this automatically when path is omitted.
ResolveProjectDir
public static string ResolveProjectDir()Returns the absolute GodotProjectDir embedded in loaded assembly metadata. It throws InvalidOperationException when no loaded assembly provides that metadata.
RegisterWebPluginsInitializer
public static void RegisterWebPluginsInitializer(IntPtr initializer)Registers the game assembly's generated plugin initializer in a browser host. The web host's Program.cs calls this before Start() with the pointer from TwoDogWebBoot.PluginsInitializer() (the bootstrap file in the web host folder, compiled into the game assembly); normal application code does not need anything beyond that template line. Desktop calls throw PlatformNotSupportedException.
Example
using Godot;
using Engine = twodog.Engine;
internal static class Program
{
[STAThread]
private static void Main(string[] args)
{
using var engine = new Engine("MyGame", args: args);
engine.Start();
while (!engine.Iteration())
{
// One frame has completed.
}
}
}args accepts ordinary Godot command-line arguments – --headless, --verbose, --rendering-driver opengl3, --audio-driver Dummy, and the rest – and passes them to the engine unchanged.
See Generic Host for the full desktop-host pattern.