Loading

[Unity 杂货铺] 禁用 Domain Reload 提高效率

1 概要

  1. 打开设置Edit → Project Settings → Editor
  2. 勾选打开 Enter Play Mode Options → 取消勾选 Reload Domain
  3. 使用 [RuntimeInitializeOnLoadMethod] 特性,重置静态字段

2 背景

在 Unity 中点击播放 (Play) 按钮运行项目时,或者修改代码保存时,都会开启进度条进行域重新加载:

等待时间从 5 秒至 30 秒不等,卡 Loading 已然成为 Unity 开发者快速迭代之路的梦魇。

关于 域重新加载(domain reloading),可阅读官方文档中相关的四小节内容:https://docs.unity3d.com/6000.3/Documentation/Manual/domain-reloading.html

建议阅读 Unity 英文版本的文档,有中文需求也考虑直接翻译英文版本。

英文文档伴随着 Unity 的升级会有迭代删改,但这些修改似乎并不会重新翻译。即使选择中文文档的最新版本,仍旧可能是落后的翻译版本。

默认情况下,Unity 会在进入 Play 模式时重新加载域以重置应用程序状态,包括所有静态字段,但域重载也是一个耗时的操作。

Unity 编辑器在Project Settings提供了Enter Play Mode Options选项,用以禁用“重新加载域”(Reload Domain) 和“重新加载场景” (Reload Scene) 。

Reload Scene 耗时相对较少,可视情况保留。

而禁用域重载,点击 Play 按钮,此时不再弹出进度条,进入游戏的速度大幅加快。

但后续再点击 Play 按钮进入游戏时,可能会由于静态字段残留,静态事件重复注册等,造成多次回调,导致行为不可预测。所以需要进行手动重置。

3 重置静态字段

其实还是阅读文档即可:

https://docs.unity3d.com/6000.3/Documentation/Manual/domain-reloading.html

编写类似这样的代码,会在加载第一个场景之前被调用:

using UnityEngine;

public static class GlobalReset
{
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
    static void ResetAll()
    {
        GameState.Reset();
        EventManager.Clear();
        ServiceLocator.Clear();
    }
}

另外可使用到的有:EditorApplication.playModeStateChanged[InitializeOnEnterPlayMode]

Github 中 UnityDomainReloadHelper 扩展了 RuntimeInitializeOnLoadMethod,添加了更方便清理的特性:

https://github.com/joshcamas/unity-domain-reload-helper

4 相关的开源库

4.1 com.unity.editoriterationprofiler

https://github.com/Unity-Technologies/com.unity.editoriterationprofiler

官方库,用于测量域重载的耗时。

4.2 UnityManuallyReload

https://github.com/ZeroUltra/UnityManuallyReload

手动编译 Reload 的工具,以及作者在知乎上的文章:

Unity 手动编译 Reload 脚本 减少等待

4.3 UnityDomainReloadHelper

https://github.com/joshcamas/unity-domain-reload-helper

4.4 UnityFastPlay

单脚本,大概是单独添加一个“Play without domain reload”的按钮

https://github.com/JonathanTremblay/UnityFastPlay

5 个人实践

个人会尝试关闭域重载,保持场景重载。对静态变量进行手动重置,相关重置方法限制在编辑器宏之内。

或者参考使用 UnityFastPlay,加一个用于快速迭代的播放按钮。

目前的理解是,由于静态字段的状态保留,可能会导致额外的报错,但应该不会掩盖原本的问题。即不会导致问题在打包之后才暴露出来,所以整体上应该是相对“安全”的。

另外在代码修改编译时,仍然还是会进行重载的。所以整体运行状态应该是时旧时新的。

目前的疑惑是文档中提及:“当您禁用域重新加载时,非序列化字段在编辑模式下保持在播放模式期间分配给它们的值。”还需要观察下这里保持可能造成的影响。

posted @ 2026-09-07 12:19  野生西瓜  阅读(0)  评论(0)    收藏  举报