Unity卸载场景时出现Assertion failed on expression报错如何解决
报错信息
Assertion failed on expression: 'offsetIndex != -1' Assertion failed on expression: 'offsetIndex != -1'UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&
复现条件
- 调用
SceneManager.UnloadSceneAsync接口卸载场景后,同帧立刻执行新场景加载逻辑 - 场景加载、卸载的实际功能运行完全正常,但控制台持续抛出上述断言报错,其中带
UnityEngine.GUIUtility:ProcessEvent堆栈的报错累计触发15次 - 所用场景加载脚本的逻辑,与Unity官方示例项目open-project-1中的SceneLoader实现基本一致
报错根因
该报错是Unity编辑器环境下原生IMGUI系统的时序Bug,不属于业务逻辑错误:
- 调用
UnloadSceneAsync异步卸载场景时,Unity会在当前帧末尾清理被卸载场景关联的所有IMGUI绘制回调,包括场景内MonoBehaviour的OnGUI方法、挂载的编辑器拓展GUI回调 - 若同帧直接触发新场景加载,GUI事件调度器会提前持有已被标记为待卸载的回调引用,等回调被清理后再查找对应GUI元素的偏移索引就会返回-1,触发断言
- 该断言仅在编辑器环境下触发,真机打包后不会出现,也不会造成任何实际功能异常;open-project-1中的SceneLoader实现本身没有逻辑错误,只是其异步场景衔接的默认时序刚好命中了这个编辑器已知问题
修复方案
- 方案1(无代码改动):确认业务流程运行正常的前提下,可直接在Unity控制台的日志过滤规则中,屏蔽匹配
offsetIndex != -1的断言日志即可,该报错不会影响最终打包产物的运行表现 - 方案2(时序规避,彻底消除报错):不要在调用
UnloadSceneAsync的同帧触发新场景加载,等待卸载异步操作完成后延迟1帧再执行加载逻辑,参考实现:
// 原易触发报错的逻辑 // SceneManager.UnloadSceneAsync(targetUnloadScene); // SceneManager.LoadSceneAsync(targetLoadScene); // 修改后规避时序问题的逻辑 AsyncOperation unloadOp = SceneManager.UnloadSceneAsync(targetUnloadScene); unloadOp.completed += _ => { StartCoroutine(LoadSceneDelayOneFrame(targetLoadScene)); }; IEnumerator LoadSceneDelayOneFrame(string sceneName) { // 等待1帧跳过GUI回调清理的敏感时序 yield return null; SceneManager.LoadSceneAsync(sceneName); }
- 方案3(编辑器工具场景适配):如果是自定义编辑器拓展工具触发的该报错,可在场景卸载、加载的衔接帧主动清空
GUIUtility.hotControl、GUIUtility.keyboardControl的缓存状态,避免GUI索引查找失效。
内容的提问来源于stack exchange,提问作者Austin
相关产品推荐
相关产品推荐

