Unity:缓存下载后的SceneInstance无法激活的技术问题
问题分析与解决
核心问题
你的缓存逻辑仅跟踪了场景是否加载过,未处理场景被卸载或场景已处于激活状态的情况:
- 当用
LoadSceneMode.Single加载其他场景时,主菜单场景会被自动卸载,但_isLoaded标记仍为true,返回的_cachedScene已失效 - 若主菜单场景已经激活,调用
ActivateAsync不会触发任何操作,因为场景本身就是激活状态
修复方案
方案1:添加缓存有效性检查
修改MainMenuProvider,在返回缓存前验证场景是否仍有效:
class MainMenuProvider { private static SceneInstance _cachedScene; private static bool _isLoaded; public async Task<SceneInstance> Load() { // 检查缓存场景是否已失效(未加载或无效) if (_isLoaded && (!_cachedScene.Scene.IsValid() || !_cachedScene.Scene.isLoaded)) { _isLoaded = false; } if (!_isLoaded) { var mainMenuLoadHandle = Addressables.LoadSceneAsync("Assets/Bundles/UI/Scenes/MainMenu.unity", LoadSceneMode.Single, false); await mainMenuLoadHandle.Task; _cachedScene = mainMenuLoadHandle.Result; _isLoaded = true; } return _cachedScene; } }
方案2:激活前检查场景状态
调用ActivateAsync前先判断场景是否未激活,避免无效调用:
var sceneInstance = await mainMenuProvider.Load(); if (!sceneInstance.Scene.isActive) { await sceneInstance.ActivateAsync(); }
方案3:实例化管理+场景卸载监听
静态缓存易导致状态不一致,改为实例化类并监听场景卸载事件:
class MainMenuProvider { private SceneInstance? _cachedScene; private bool _isLoaded; public MainMenuProvider() { SceneManager.sceneUnloaded += OnSceneUnloaded; } private void OnSceneUnloaded(Scene scene) { if (_cachedScene.HasValue && _cachedScene.Value.Scene == scene) { _cachedScene = null; _isLoaded = false; } } public async Task<SceneInstance> Load() { if (!_isLoaded || !_cachedScene.HasValue || !_cachedScene.Value.Scene.IsValid()) { var mainMenuLoadHandle = Addressables.LoadSceneAsync("Assets/Bundles/UI/Scenes/MainMenu.unity", LoadSceneMode.Single, false); await mainMenuLoadHandle.Task; _cachedScene = mainMenuLoadHandle.Result; _isLoaded = true; } return _cachedScene.Value; } }
额外注意事项
- 用
SceneInstance.Scene.IsValid()和Scene.isLoaded可准确判断场景实际状态 - 若需频繁切换场景,建议用
LoadSceneMode.Additive加载主菜单,避免被Single模式卸载,同时手动管理激活状态
内容的提问来源于stack exchange,提问作者Виктор Титов
相关产品推荐
相关产品推荐

