GFramework/docs/zh-CN/game/scene-management.md
GeWuYou 317eddca9b docs(sidebar): 更新侧边栏导航结构并移除API参考页面
- 调整Core模块导航链接结构,从overview页面改为根路径
- 重构Core模块侧边栏,将原有的6个主要类别扩展为15个详细分类
- 精简Game模块侧边栏,保留场景管理和游戏设置两个主要功能
- 更新Godot集成模块侧边栏,新增协程、信号、存储等功能分类
- 修改源码生成器模块命名,将枚举扩展重命名为枚举生成器
- 新增抽象接口侧边栏,包含Core和Game抽象接口文档
- 调整教程模块顺序,新增入门教程和Godot集成教程分类
- 移除独立的API参考导航项,将其整合到相应模块中
- 修正生成器API文档链接路径错误问题
2026-02-11 12:52:14 +08:00

10 KiB
Raw Blame History

场景管理

GFramework.Game 模块提供的场景管理功能,实现游戏场景的加载、切换和状态管理

概述

GFramework.Game 提供了统一的场景管理系统,支持场景的异步加载、切换动画、状态保持等功能。通过场景管理,您可以优雅地处理游戏中的各种场景转换,如主菜单、游戏界面、设置菜单等。

核心特性

  • 异步加载:支持后台异步加载场景,避免卡顿
  • 场景切换动画:内置淡入淡出等切换效果
  • 状态保持:场景切换时保持必要的游戏状态
  • 场景栈:支持场景叠加(如弹出菜单)
  • 资源管理:自动管理场景资源的加载和卸载

基本用法

定义场景

using GFramework.Game.scene;

public class GameScene : GameSceneBase
{
    protected override void OnLoad()
    {
        // 场景加载时的初始化
    }

    protected override void OnUnload()
    {
        // 场景卸载时的清理
    }

    public override void OnEnter()
    {
        // 进入场景
    }

    public override void OnExit()
    {
        // 退出场景
    }
}

场景管理器

using GFramework.Game.scene;

[ContextAware]
public partial class SceneManager : Node
{
    private ISceneManager _sceneManager;

    public override void _Ready()
    {
        _sceneManager = Context.GetSystem<ISceneManager>();
        
        // 初始化场景管理器
        _sceneManager.Initialize();
    }

    public async Task SwitchToGameScene()
    {
        await _sceneManager.SwitchSceneAsync<GameScene>();
    }
}

场景加载

同步加载

适用于小场景的快速切换:

public void LoadMainMenu()
{
    _sceneManager.SwitchScene<MainMenuScene>();
}

异步加载

大场景建议使用异步加载:

public async Task LoadGameLevel(string levelName)
{
    // 显示加载界面
    loadingUI.Show();
    
    try
    {
        // 异步加载场景
        await _sceneManager.SwitchSceneAsync<GameLevelScene>(scene =>
        {
            // 可以在这里传递场景参数
            var gameScene = scene as GameLevelScene;
            gameScene.LevelName = levelName;
        });
        
        GD.Print("场景加载完成");
    }
    catch (Exception ex)
    {
        GD.PrintErr($"场景加载失败: {ex.Message}");
        loadingUI.ShowError();
    }
    finally
    {
        loadingUI.Hide();
    }
}

加载进度

监听加载进度:

public async Task LoadSceneWithProgress<TScene>() where TScene : IScene
{
    loadingUI.Show();
    
    var progress = new Progress<float>(value =>
    {
        loadingUI.UpdateProgress(value * 100);
    });
    
    await _sceneManager.SwitchSceneAsync<TScene>(progress: progress);
    
    loadingUI.Hide();
}

场景切换动画

内置切换效果

public async Task SwitchWithFade()
{
    // 使用淡入淡出效果
    await _sceneManager.SwitchSceneAsync<GameScene>(
        transition: new FadeTransition(
            duration: 0.5f,
            fadeColor: Colors.Black
        )
    );
}

public async Task SlideTransition()
{
    // 使用滑动效果
    await _sceneManager.SwitchSceneAsync<GameScene>(
        transition: new SlideTransition(
            direction: Vector2.Left,
            duration: 0.3f
        )
    );
}

自定义切换动画

public class CustomTransition : ISceneTransition
{
    public float Duration { get; } = 1.0f;

    public async Task PlayAsync(Node fromScene, Node toScene)
    {
        // 自定义动画逻辑
        var tween = CreateTween();
        
        // 旧场景缩小消失
        tween.TweenProperty(fromScene, "scale", Vector2.Zero, Duration / 2)
            .SetTrans(Tween.TransitionType.BackIn);
        
        await ToSignal(tween, Tween.SignalName.Finished);
        
        fromScene.Visible = false;
        toScene.Visible = true;
        toScene.Scale = Vector2.Zero;
        
        // 新场景放大出现
        tween = CreateTween();
        tween.TweenProperty(toScene, "scale", Vector2.One, Duration / 2)
            .SetTrans(Tween.TransitionType.BackOut);
        
        await ToSignal(tween, Tween.SignalName.Finished);
    }
}

场景栈

推送场景

将新场景推入栈中:

public void PushPauseMenu()
{
    _sceneManager.PushScene<PauseMenuScene>();
}

弹出场景

弹出栈顶场景:

public void PopScene()
{
    _sceneManager.PopScene();
}

示例:带返回的导航

public async Task NavigateToSettings()
{
    // 保存当前场景引用
    var previousScene = _sceneManager.CurrentScene;
    
    // 推入设置场景
    await _sceneManager.PushSceneAsync<SettingsScene>();
    
    // 设置场景有返回按钮
    await _sceneManager.PushSceneAsync<ConfirmDialog>(
        data: new ConfirmData
        {
            Message = "是否保存设置?",
            OnConfirm = () => _sceneManager.PopScene(), // 不保存,直接返回
            OnCancel = () =>
            {
                // 保存设置后返回
                SaveSettings();
                _sceneManager.PopScene();
            }
        }
    );
}

场景状态管理

保存状态

public class GameScene : GameSceneBase
{
    private GameState _state;

    protected override void OnLoad()
    {
        // 从存档加载状态
        _state = LoadGameState();
    }

    protected override void OnUnload()
    {
        // 保存状态
        SaveGameState(_state);
    }

    public override void OnExit()
    {
        // 清理工作
        Cleanup();
    }
}

跨场景数据传递

// 传递数据到新场景
await _sceneManager.SwitchSceneAsync<GameScene>(data: new GameData
{
    Level = 5,
    Difficulty = Difficulty.Hard,
    ContinueToken = saveToken
});

// 在目标场景中接收数据
public class GameScene : GameSceneBase
{
    public override void OnEnter(object data)
    {
        var gameData = data as GameData;
        InitializeLevel(gameData.Level, gameData.Difficulty);
    }
}

预加载策略

预加载资源

public void PreloadCommonResources()
{
    _sceneManager.PreloadScene<MainMenuScene>();
    _sceneManager.PreloadScene<GameLevelScene>(count: 3);
}

预加载配置

var config = new ScenePreloadConfig
{
    PreloadCount = 5,
    Priority = ResourceLoader.CacheMode.Cache,
    Timeout = 30.0f
};

_sceneManager.ConfigurePreload(config);

资源管理

自动卸载

// 配置自动卸载策略
var unloadConfig = new SceneUnloadConfig
{
    UnloadDelay = 30.0f,      // 30秒后卸载
    KeepReferences = true,    // 保持引用
    ForceUnloadOnMemoryPressure = true  // 内存紧张时强制卸载
};

_sceneManager.ConfigureUnload(unloadConfig);

手动卸载

// 卸载指定场景
_sceneManager.UnloadScene<MainMenuScene>();

// 卸载所有场景
_sceneManager.UnloadAllScenes();

最佳实践

1. 场景设计原则

// 推荐:每个场景职责单一
public class MainMenuScene : GameSceneBase { /* 主菜单 */ }
public class SettingsScene : GameSceneBase { /* 设置菜单 */ }
public class GameHUDScene : GameSceneBase { /* 游戏HUD */ }

// 避免:场景职责过多
public class MegaScene : GameSceneBase 
{ 
    /* 包含菜单、设置、HUD、存档管理... 不要这样设计 */
}

2. 场景切换优化

// 推荐:使用异步加载
public async Task LoadGame()
{
    loadingUI.Show("正在加载游戏...");
    await _sceneManager.SwitchSceneAsync<GameScene>();
}

// 避免:同步加载大场景
public void LoadGame()
{
    // 这会导致游戏卡顿
    _sceneManager.SwitchScene<GameScene>();
}

3. 内存管理

public class GameScene : GameSceneBase
{
    private Texture2D[] _largeTextures;

    protected override void OnLoad()
    {
        // 加载资源
        _largeTextures = LoadLargeTextures();
    }

    protected override void OnUnload()
    {
        // 及时释放大资源
        foreach (var texture in _largeTextures)
        {
            texture.Dispose();
        }
        _largeTextures = null;
    }
}

4. 错误处理

public async Task SafeLoadScene<TScene>() where TScene : IScene
{
    try
    {
        await _sceneManager.SwitchSceneAsync<TScene>();
    }
    catch (SceneNotFoundException)
    {
        Logger.Error($"场景 {typeof(TScene)} 未找到");
        // 回退到默认场景
        await _sceneManager.SwitchSceneAsync<FallbackScene>();
    }
    catch (ResourceLoadException ex)
    {
        Logger.Error($"资源加载失败: {ex.Message}");
        await ShowRetryDialog();
    }
}

与其他模块集成

与 Game 模块集成

public class GameLevelScene : GameSceneBase
{
    private GameManager _gameManager;

    public override void OnEnter()
    {
        // 初始化游戏管理器
        _gameManager = Context.GetSystem<GameManager>();
        _gameManager.StartGame();
    }

    public override void OnExit()
    {
        _gameManager.EndGame();
    }
}

与存档系统集成

public class GameScene : GameSceneBase
{
    private ISaveSystem _saveSystem;

    protected override void OnLoad()
    {
        _saveSystem = Context.GetUtility<ISaveSystem>();
        
        // 检查是否有自动存档
        if (_saveSystem.HasAutoSave())
        {
            var dialog = Context.GetSystem<IDialogSystem>();
            await dialog.ShowAsync("发现自动存档,是否继续?",
                onConfirm: () => LoadAutoSave(),
                onCancel: () => StartNewGame()
            );
        }
    }

    private void LoadAutoSave()
    {
        var saveData = _saveSystem.LoadAutoSave();
        RestoreGameState(saveData);
    }

    public override void OnExit()
    {
        // 自动保存
        _saveSystem.SaveAutoSave(CreateSaveData());
    }
}

相关文档