reckfellENGINE

Переходы между уровнями

Автозагрузка, смена сцены, ожидание завершения и повторные запросы.

На этой странице

Уровни и автозагрузка

Нужны два сохранённых документа, например asset://Levels/Level01.rscene и asset://Levels/Level02.rscene. Каждый уровень должен содержать собственную камеру и освещение. Назначьте первый главным документом проекта.

Создайте Scripts/LevelRouter.cs. В Project Settings → Globals → Autoload добавьте этот скрипт с именем LevelRouter. Автозагрузка создаёт объект вне текущей сцены: он не удалится при переходе на другой уровень.

LevelRouter.cs

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

public partial class LevelRouter : Entity
{
    public bool IsChanging { get; private set; }

    public async Task<Error> OpenLevel(string path)
    {
        if (IsChanging)
            return Error.Busy;
        if (!IsInsideTree())
            return Error.Unconfigured;
        if (!ResourceLoader.Exists(path, "PackedEntity"))
            return Error.FileNotFound;

        IsChanging = true;
        EntityTree tree = GetTree();
        try
        {
            Error error = tree.ChangeSceneToFile(path);
            if (error != Error.Ok)
                return error;

            await ToSignal(tree, EntityTree.SignalName.SceneChanged);
            return Error.Ok;
        }
        finally
        {
            IsChanging = false;
        }
    }
}

Все переходы проекта вызывайте через этот объект. Пока один переход не завершён, повторный возвращает Busy. finally снимает блокировку и при успешной смене, и при возвращённой ошибке загрузки.

Кнопка перехода

В первом уровне добавьте CanvasLayer, внутри него Control с размещением Full Rect, затем дочерний Button. Для кнопки задайте Text: Следующий уровень, Position: (24, 24), Size: (240, 48); привязки оставьте к верхнему левому углу. Эта структура размещает кнопку поверх 3D-мира.

Прикрепите к кнопке OpenLevelButton.cs. После сборки назначьте Level Path: asset://Levels/Level02.rscene.

C#
using Reckfell;

public partial class OpenLevelButton : Button
{
    [Export] public string LevelPath { get; set; } = "asset://Levels/Level02.rscene";

    public override void _Ready()
    {
        Pressed += Open;
    }

    private async void Open()
    {
        var router = GetEntityOrNull<LevelRouter>("/root/LevelRouter");
        if (router == null)
        {
            ReckfellApi.PushError("Add LevelRouter to Autoload.");
            return;
        }

        Error error = await router.OpenLevel(LevelPath);
        if (error != Error.Ok && error != Error.Busy)
            ReckfellApi.PushError($"Level change failed: {error}");
    }
}

Нажмите F5 и кнопку: первый уровень заменится вторым. Код после await не обращается к кнопке — она принадлежала старому уровню и к этому моменту уже удалена.

Что происходит при смене

МоментСостояние дерева
ChangeSceneToFile вернул OkСтарая сцена уже исключена из дерева; CurrentScene временно равна null
Конец кадраСтарое дерево удаляется, новое добавляется и выполняет _Ready()
Сигнал SceneChangedНовый CurrentScene доступен; OpenLevel() завершается

Не получайте новое дерево сразу после ChangeSceneToFile: дождитесь SceneChanged или настройте объекты в их _Ready(). Ссылки на объекты старого уровня становятся недействительными. Сам LevelRouter остаётся в /root/LevelRouter.

Данные между уровнями храните в отдельной автозагрузке. Для восстановления после закрытия игры нужна запись на диск; автозагрузка сохраняет состояние только в рамках текущего запуска.

Ошибки и ограничения

СимптомПроверка
Add LevelRouter to AutoloadИмя автозагрузки должно быть ровно LevelRouter
FileNotFoundПроверьте путь asset://, регистр и наличие сохранённого документа
CantOpen / CantCreateФайл не загружается как PackedEntity или не создаёт экземпляр; смотрите первую ошибку Output
Новый уровень чёрныйПроверьте его камеру, Current, свет и положение объектов
После перехода возникла ошибка доступаКод использует объект уже удалённого уровня

ChangeSceneToFile загружает ресурс синхронно; на крупных уровнях возможна пауза. Замена сцены не реализует подгрузку частей открытого мира. Для перезапуска текущего документа есть EntityTree.ReloadCurrentScene() с тем же отложенным завершением смены.

Справочник: EntityTree, ResourceLoader, Button.

Документация Reckfell EngineНаверх ↑
БЫСТРЫЙ ПЕРЕХОДНачало работыEntity и иерархияC# & .NET 10Сцены и префабы
Руководства и полный API Reckfell K
reckfellENGINE
RECKFELL ACCOUNT

Вход в аккаунт

Войдите в аккаунт Reckfell.

Один аккаунт для всей платформы Reckfell.