缩短 Unity 中资源导入时间

发布: (2025年12月31日 GMT+8 02:41)
10 min read
原文: Dev.to

Source: Dev.to

Source:

导入活动概览

每当我们向项目添加新资源时,Unity 必须通过其导入器对其进行处理。在大多数情况下,Unity 不能直接使用原始格式的源文件。相反,它会读取 Assets 文件夹中的资源,并将它们的内部表示存储在 Library 文件夹中,以一种引擎能够理解的格式。

所有游戏开发者都经历过这样一种情况:看似无关的操作触发了大量其他资源的重新导入,或者打开一个新项目耗时非常长。幸运的是,Unity 提供了许多诊断工具,帮助我们了解实际发生了什么,从而缩短重新导入的时间,腾出更多时间专注于游戏本身。

检查 Import Activity 窗口

Import Activity 窗口可以让你看到最近的导入列表,以及用于了解触发导入的原因、持续时间等的诊断信息。可通过 Window > Analysis > Import Activity 打开它。

Import Activity window

  • 右侧面板 – 显示导入时间最长的资源以及依赖关系最多的资源的快速概览。优先处理这些资源可以降低整体导入时间,并加快迭代周期。
  • 左侧面板 – 列出所有已(重新)导入的资源。选中条目后会显示更多信息,包括:
    • 其依赖关系列表。
    • 导入触发的原因(例如首次导入、缺失库工件、定制或动态依赖变化、Unity 版本升级、构建目标更改等)。

Import Activity details

该窗口还会指向 Library 文件夹中生成的工件。单个源资源可能会生成多个文件(例如,一个 .fbx 模型可能会产生单独的材质文件和动画文件)。这些文件会显示在 Produced Files/Artifacts 面板中。

你也可以在 Project 视图中右键单击资源,选择 “View in Import Activity window”,直接跳转到其最近的导入事件。

注意: 重新导入也可能是由于资源依赖关系的变化——静态(例如资源名称或构建目标更改)或动态(资源相互引用)导致的。自 Unity 6.4 起,依赖解析逻辑已被大幅重构,从而减少了依赖数量并加快了导入速度。相关讨论请参见此处

搜索索引导入器

有时 Import Activity 窗口会显示类似 “ASIEI03” 的原因。这些是 Search Index Entry 导入器,用于支持 Unity Search。

  • 它们通常非常快速,对导入时间几乎没有影响。
  • 如果需要,你可以禁用它们(Unity 6.3 及以上):Preferences > Search > Indexing → 切换 Index on Editor Startup

Search Indexing preferences

检查编辑器日志

每当资源被导入时,Unity 会将诊断信息写入 Editor logs。这些信息与 Import Activity 窗口中看到的内容相同,只是以纯文本形式呈现。

示例日志条目

[Worker7] Start importing Assets/Textures/hero.png using Guid(ae35ctf46db9fd442b94a73df0ec0f44) Importer(2089858483,0ecaa5967403d0e2aa24f35e1b516d23)
Done ondemand importing asset: 'Assets/Textures/hero.png' (artifact id: '4fead12a87251aa702d2e109bfb6181b')
Done importing asset: 'Assets/Textures/hero.png' (target hash: 'b6a')

Source: (保持原样)

bac4492f6da0253684d7b2f48c6e3') in 0.076 seconds

确定资产为何被标记为已更改

当资产被修改——无论是外部修改、在编辑器内部修改,还是通过自定义编辑器脚本修改——它都会被标记为 dirty,这意味着 Unity 需要重新导入它以获取最新的表示。

Import Activity 窗口会给出重新导入的高级原因,但有时你需要更详细的信息。启用 ObjectSetDirty 诊断标志后,Unity 会在日志中打印导致资产变脏的调用堆栈。

如何启用

  1. 打开 Preferences > Diagnostics > Core
  2. 勾选 ObjectSetDirty
  3. 重启编辑器以使更改生效。

ObjectSetDirty preference

现在,当资产被标记为 dirty 时,编辑器日志中将包含指向导致该更改的确切代码路径的堆栈跟踪。这对于追踪脚本或第三方工具引起的意外重新导入非常有价值。

Source:

脏计数日志

当启用 Dirty Count 标志时,Unity 会在每次对象的脏计数发生变化时输出日志。日志条目按顺序包含:

  1. 脏计数的变化(IncrementClear
  2. 实例 ID
  3. 对象名称
  4. 对象类型

示例 – Increment

Increment Dirty(3) : [-3808] Sphere (GameObject)

示例 – Clear(通常在重新导入后)

Clear Dirty(0) : [942] UIMask (Sprite)

提示:Stack Trace Logging 设置为 Full(针对 All logs),这样就能看到完整的堆栈跟踪,了解是什么将对象标记为脏。

Stacktrace Logging Level

解释日志条目

Increment Dirty(1) : [17448] HeroPrefab (GameObject)

#0 PlatformStacktrace::GetStacktrace(int)
#1 DebugStringToFile(DebugStringToFileData const&)
#2 Object::IncrementPersistentDirtyIndex()
#3 Object::SetDirty()
#4 GameObject::SetLayer(int)
#5 (Mono JIT Code) (wrapper managed-to-native) UnityEngine.GameObject:set_layer_Injected (intptr,int)
#6 (Mono JIT Code) UnityEngine.GameObject:set_layer (int)
#7 (Mono JIT Code) [SceneModeUtility.cs:311] UnityEditor.SceneModeUtility:SetLayer (System.ReadOnlySpan`1,string)

从堆栈跟踪可以看出,资产被标记为脏是因为它的 layer 被更改了。

您可以在此处了解更多关于此诊断标志的信息。

Source:

AssetDatabase API 操作批处理

许多编辑器 API 调用(例如 AssetDatabase.CopyAssetAssetDatabase.DeleteAsset)在每行代码后都会触发 数据库刷新,在处理大量资源时可能代价高昂。

批量编辑

AssetDatabase.StartAssetEditing()AssetDatabase.StopAssetEditing() 之间包裹你的资源修改代码,以暂停自动刷新,并在结束时只执行一次刷新。

try
{
    AssetDatabase.StartAssetEditing();

    AssetDatabase.MoveAsset("Assets/hero.png", "Assets/Textures/hero.png");
    AssetDatabase.DeleteAsset("Assets/Old/placeholder.png");
}
finally
{
    AssetDatabase.StopAssetEditing();
}

注意: Unity 为这些调用维护了一个内部计数器。务必为每个 StartAssetEditing 匹配相应的 StopAssetEditing;否则 AssetDatabase 可能会保持禁用状态,导致无响应。

并行导入

Unity 2022 开始,您可以为受支持的资源类型启用并行导入,从而显著加快导入过程。

  1. 打开 Project Settings → Editor → Asset Pipeline
  2. 勾选 Parallel Import

Parallel Import Setting

资源类型并行导入
纹理
模型
音频
其他❌(顺序导入)

启用后,Unity 会将工作负载分配到多个线程。您可以在同一设置面板中可选地指定工作线程的数量及其待机行为。Unity 会尝试遵守这些数值,但实际的工作线程数量可能会根据系统资源而有所不同。

禁用资产自动刷新

默认情况下,Unity 会在编辑器重新获得焦点时自动刷新资产数据库,重新导入已更改的资产并检测新增或删除的文件。

关闭自动刷新

  1. 打开 Preferences → Asset Pipeline
  2. Auto Refresh 设置为 Disabled

已禁用自动刷新

关闭自动刷新后,需要手动刷新资产数据库:

  • 菜单: Assets → Refresh
  • API: AssetDatabase.Refresh()

IDE 集成

许多 IDE(例如 Rider)会自动触发刷新。要阻止此行为:

  • Rider: Languages & Frameworks → Unity Engine → General → Automatically refresh assets in Unity(禁用)。

Rider Unity 刷新设置

导入时压缩纹理

每当你创建新项目或添加新的纹理资源时,Unity 会在导入过程中自动压缩这些纹理。这可确保运行时的内存使用和性能达到最佳状态。

禁用自动压缩

  1. 打开 Preferences → Asset Pipeline → Compress Textures on Import
  2. 将该选项 off(关闭)。

Editor texture import settings

  • 效果: 缩短导入时间。Unity 在编辑器中工作时会保持纹理未压缩。
  • 构建影响: 纹理仅在创建构建时才会压缩,这可能会延长构建过程。
  • 适用场景: 如果你从不进行本地构建(例如,只使用 CI/CD 流水线),则更长的构建时间可能并不重要。

在打开编辑器之前禁用

要加快 初始项目导入,直接编辑用户设置文件:

UserSettings/EditorUserSettings.asset

设置以下属性:

m_CompressAssetsOnImport: 0

这会阻止首次导入时的纹理压缩,使编辑器启动更快。

Back to Blog

相关文章

阅读更多 »