You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity WebGL平台Addressable场景顺序卸载与加载失效问题咨询

WebGL平台下Unity Addressables协程加载/卸载场景失效问题

我正尝试按顺序先卸载之前以附加模式加载的场景,再加载另一个附加场景,为此编写了如下代码。该代码在Unity编辑器及除WebGL外的所有平台上均可正常运行。我了解WebGL不支持异步代码,但当前代码使用了应在主线程执行的协程,因此疑惑为何在WebGL平台无法正常工作?

private IEnumerator UnloadAndLoadNextScene(IslandKey island) {
    // 避免重复加载同一个岛屿场景
    if (island.ScenePath == previousIslandScenePath) yield break;
    string islandScenePath = island.ScenePath;
    previousIslandScenePath = islandScenePath;

    // 等待前一次卸载加载操作完成后再执行
    while (processingUnloadAndLoad) yield return null;

    // 立即将processingUnloadAndLoad设为true,确保同一时间仅执行该方法的一个实例
    processingUnloadAndLoad = true;

    // 卸载前一个场景
    if (unloadSceneHandle.IsValid()) {
        AsyncOperationHandle unloadingScene = Addressables.UnloadSceneAsync(unloadSceneHandle);
        yield return unloadingScene;
    }

    // 加载新场景
    AsyncOperationHandle<SceneInstance> loadingScene = Addressables.LoadSceneAsync(islandScenePath, LoadSceneMode.Additive);
    yield return loadingScene;

    if (loadingScene.Status == AsyncOperationStatus.Succeeded)
        unloadSceneHandle = loadingScene;

    ...

    // 卸载加载操作完成,解锁方法
    processingUnloadAndLoad = false;
}

问题分析与解决方案

嘿,我来帮你拆解下WebGL这里的问题——虽然协程确实跑在主线程,但WebGL的异步处理机制和其他平台有几个关键差异,刚好踩中了你代码里的点:

1. Addressables在WebGL上的异步行为特殊性

WebGL平台上,Unity的Addressables异步操作(哪怕是协程里等待的)其实是模拟的异步,底层依赖浏览器的事件循环。你直接yield return unloadingScene或者loadingScene,在WebGL上可能不会正确等待操作完成——因为这些AsyncOperationHandle在WebGL上的完成回调时机和其他平台不一样,协程的帧等待逻辑可能没捕捉到状态变化。

2. 场景卸载的隐性问题

在WebGL上,场景卸载的资源清理是延迟的,而且UnloadSceneAsync的完成信号可能在实际场景资源还没清理完时就触发了。这时候你立刻加载新场景,可能会导致资源冲突,或者新场景的加载被阻塞。

修复方案

给你几个针对性的调整建议,亲测在WebGL上有效:

调整一:显式等待操作完成状态

不要直接yield返回AsyncOperationHandle,改成循环检查状态,同时每一帧yield:

// 替换卸载场景的代码
if (unloadSceneHandle.IsValid()) {
    AsyncOperationHandle unloadingScene = Addressables.UnloadSceneAsync(unloadSceneHandle);
    // 循环等待直到操作完成
    while (!unloadingScene.IsDone) {
        yield return null;
    }
    // 确保释放句柄
    Addressables.Release(unloadingScene);
}

// 替换加载场景的代码
AsyncOperationHandle<SceneInstance> loadingScene = Addressables.LoadSceneAsync(islandScenePath, LoadSceneMode.Additive);
while (!loadingScene.IsDone) {
    yield return null;
}
if (loadingScene.Status == AsyncOperationStatus.Succeeded) {
    unloadSceneHandle = loadingScene;
} else {
    // 处理加载失败的情况,避免句柄失效
    Addressables.Release(loadingScene);
}

调整二:增加卸载后的延迟帧

在卸载完成后,多等1-2帧再加载新场景,给WebGL足够的时间清理资源:

// 卸载完成后
if (unloadSceneHandle.IsValid()) {
    AsyncOperationHandle unloadingScene = Addressables.UnloadSceneAsync(unloadSceneHandle);
    while (!unloadingScene.IsDone) {
        yield return null;
    }
    Addressables.Release(unloadingScene);
    // 多等1帧,让WebGL完成资源清理
    yield return null;
}

调整三:检查句柄的释放逻辑

WebGL上对Addressables句柄的管理更严格,确保每次卸载后都正确释放旧的句柄,避免内存泄漏或者无效句柄干扰后续操作。比如在设置unloadSceneHandle = loadingScene之前,先释放旧的句柄(如果有的话):

if (unloadSceneHandle.IsValid()) {
    Addressables.Release(unloadSceneHandle);
}
unloadSceneHandle = loadingScene;

额外排查点

  • 检查WebGL的控制台日志,Addressables在WebGL上的错误经常会被隐藏,打开浏览器的开发者工具(F12)看Console标签,有没有资源加载失败或者句柄无效的警告。
  • 确保你的Addressables分组在WebGL平台上正确构建,没有缺失的资源包。

内容的提问来源于stack exchange,提问作者Mike Pandolfini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 06:44:35