reckfellENGINE

EntityTree: change and reload a level

CurrentScene, deferred replacement and SceneChanged; a complete button handler without accessing a freed level.

On this page

When a level has actually changed

GetTree() is available to an Entity in the active tree. EntityTree.Root is the main Viewport; CurrentScene is the current level root below it. Other Root children, such as autoloads, may coexist. Assigning CurrentScene alone neither attaches nor frees objects.

ChangeSceneToFile returns the starting operation's Error. On success the old root detaches immediately and CurrentScene is temporarily null; old-root deletion and new-root attachment finish later. SceneChanged is emitted after the new level enters and completes _Ready. Awaiting one ProcessFrame does not substitute for that signal contract.

A transition button

Prepare Assets/BadgeStyle.rdata, Actors/Badge.rprefab and Levels/FormatShowcase.rscene from the format example. Add both C# files below. In a separate level create a Button, give it visible text, attach LevelSwitchButton, build and run with F6. Pressing it replaces the level with FormatShowcase and its two instances.

LevelTransitions.cs
C#
using System;
using System.Threading.Tasks;
using Reckfell;

public static class LevelTransitions
{
    private static bool _pending;

    public static async Task<Error> ChangeAsync(EntityTree tree, string path)
    {
        if (_pending) return Error.Busy;
        if (!path.StartsWith("asset://", StringComparison.Ordinal) ||
            !path.EndsWith(".rscene", StringComparison.OrdinalIgnoreCase)) return Error.InvalidParameter;
        if (!ResourceLoader.Exists(path, "PackedEntity")) return Error.FileNotFound;
        _pending = true;
        try
        {
            Error error = tree.ChangeSceneToFile(path);
            if (error != Error.Ok) return error;
            await tree.ToSignal(tree, EntityTree.SignalName.SceneChanged);
            return Error.Ok;
        }
        finally
        {
            _pending = false;
        }
    }
}
LevelSwitchButton.cs
C#
using System;
using Reckfell;

public partial class LevelSwitchButton : Button
{
    [Export(PropertyHint.File, "*.rscene")]
    public string NextLevelPath { get; set; } = "asset://Levels/FormatShowcase.rscene";

    public override void _EnterTree() => Pressed += OnPressed;
    public override void _ExitTree() => Pressed -= OnPressed;

    private async void OnPressed()
    {
        try
        {
            Error error = await LevelTransitions.ChangeAsync(GetTree(), NextLevelPath);
            if (error != Error.Ok) ReckfellApi.PrintErr("Level change: " + error);
        }
        catch (Exception error)
        {
            ReckfellApi.PrintErr(error.ToString());
        }
    }
}

Call the helper on the main thread and route all transitions needing its overlap guard through it. Requiring .rscene is helper policy: the native API also accepts a .rprefab containing PackedEntity. A path's existence does not prove valid content, so the Error check after ChangeSceneToFile remains necessary.

After await the handler does not access the button; it may have been freed with the old level. To update UI afterward, find it in the new CurrentScene or use a controller Entity living outside the replaced root.

The helper does not implement a loading screen, background streaming or cancellation. Do not concurrently replace levels through another controller or manually free the pending new root: that breaks its SceneChanged wait.

Reload and manual management

ReloadCurrentScene loads CurrentScene.SourceAssetPath again. It restores file state rather than restarting with currently modified fields. A level created through new Entity and ChangeSceneToEntity may have no source file: retain the PackedEntity/path separately if it needs restarting.

ChangeSceneToEntity accepts a root not yet inside the active tree. Adding it through Root.AddChild and merely assigning CurrentScene does not automatically delete the previous root.

UnloadCurrentScene frees the current root immediately. Do not keep accessing its objects afterward. Use coordinated replacement for ordinary transitions, and retain long-lived data outside the replaced tree.

Diagnose a failed transition

ResultNext action
Helper InvalidParameterCheck asset:// and .rscene; resolve a UID to a valid path first
FileNotFoundCheck the level file and project/export inclusion
BusyWait for the previous transition to finish
Native load failureInspect resource diagnostics; refusal before replacement retains the old level
Temporarily null CurrentSceneWait for SceneChanged rather than accessing old references

The fixture verifies the actual transition gap, new-root readiness, old-root deletion, overlap refusal, reload and an already-created Entity target. This does not establish export or streaming readiness.

Reckfell Engine documentationBack to top ↑
QUICK LINKSGetting startedEntity hierarchyC# & .NET 10Scenes and prefabs
Reckfell guides and full API K
reckfellENGINE
RECKFELL ACCOUNT

Sign in

Sign in to your Reckfell account.

One account for the entire Reckfell platform.