Skip to content

Quick Start

Installation

Core package:

shell
dotnet add package QfStudio.Godette.ReactiveUI

Optional but recommended packages improve the development experience:

shell
dotnet add package GodotSharp.SourceGenerators
dotnet add package ReactiveUI.SourceGenerators

With [SceneTree], annotate a .tscn root script to get:

  • A TscnFilePath static property for type-safe scene loading.
  • Strongly-typed fields for nodes marked unique_name_in_owner -- no GetNode calls needed.
csharp
// With [SceneTree] -- nodes are directly accessible as properties
[SceneTree(root: "_root")]
public partial class MyScene : Control
{
    public override void _Ready()
    {
        BackButton.Pressed += () => GetTree().ChangeSceneToFile(HomeScene.TscnFilePath);
        NameEdit.Text = "hello";
    }
}
csharp
// Without [SceneTree] -- use GetNode with string paths
public partial class MyScene : Control
{
    public override void _Ready()
    {
        GetNode<Button>("BackButton").Pressed += () =>
            GetTree().ChangeSceneToFile("res://Views/HomeScene.tscn");
        GetNode<LineEdit>("NameEdit").Text = "hello";
    }
}
csharp
// With [Reactive]
public partial class MyViewModel : ReactiveObject
{
    [Reactive] public partial string Name { get; set; } = "";
}
csharp
// Without [Reactive] -- manual backing field + RaiseAndSetIfChanged
public class MyViewModel : ReactiveObject
{
    private string _name = "";
    public string Name
    {
        get => _name;
        set => this.RaiseAndSetIfChanged(ref _name, value);
    }
}

Autoload Setup

Create a bootstrapper class to initialize ReactiveUI services and add it as an Autoload in Godot:

csharp
using Godot;
using QfStudio.Godette.ReactiveUI;
using ReactiveUI.Builder;

public partial class RxAppBootstrapper : Godot.Node
{
    private readonly GodotFrameScheduler _processFrameScheduler = new();
    private readonly GodotFrameScheduler _physicsFrameScheduler = new();

    public RxAppBootstrapper()
    {
        RxAppBuilder.CreateReactiveUIBuilder()
            .WithGodot(_processFrameScheduler, _physicsFrameScheduler)
            .WithGodotConverters()
            .WithGodotViewLocator(locator =>
            {
                locator.RegisterViewsFromAssemblyViaReflection(typeof(RxAppBootstrapper).Assembly, verbose: false);
            })
            .BuildApp();
    }

    public override void _Process(double delta) => _processFrameScheduler.NotifyProcess(delta);

    public override void _PhysicsProcess(double delta) => _physicsFrameScheduler.NotifyProcess(delta);
}

Each builder call does the following:

  • .WithGodot(_processFrameScheduler, _physicsFrameScheduler) sets up the Godot platform: it creates the main-thread scheduler (from SynchronizationContext.Current), wires up the process/physics-frame schedulers you pass in, and registers the platform services needed for view activation, property binding, and command binding. It also prepares ReactiveUI's core services, so you do not call WithCoreServices() yourself.
  • .WithGodotConverters() (optional) registers the float↔double binding converters (FloatToDoubleConverter, DoubleToFloatConverter).
  • .WithGodotViewLocator(locator => …) (optional) registers the GodotViewLocator; the callback is where you register your views — here, by reflecting the current assembly.

In Godot Editor, go to Project > Project Settings > Autoload and add this script as an Autoload with a name like RxAppBootstrapper.

NOTE

Without .WithGodotConverters() (which registers FloatToDoubleConverter/DoubleToFloatConverter), bindings between Godot controls that expose double properties (e.g. Range.Value, ColorPicker.Color) and ViewModel float properties will throw ConverterNotFoundException at bind time. The library also ships EnumToStringConverter<TEnum>, StringToEnumConverter<TEnum>, and Variant-to/from-primitive converters -- register whichever ones you need via .WithConverter(...) in the builder above.