Version: 2023.2
资源数据库
Customizing the Asset Database workflow

刷新资源数据库

Unity 在以下情况下会刷新资源数据库:

  • Unity Editor 重新获得焦点时(如果已在 Preferences 窗口中启用 Auto-Refresh
  • 从菜单中选择 Assets > Refresh
  • 从 C# 调用 AssetDatabase.Refresh

其他一些 AssetDatabase API 会触发 Refresh(),但是仅针对您指定的资源。例如,CreateAsset()ImportAsset()

Unity 在资源数据库刷新期间执行以下步骤:

  1. 查找资源文件的更改,然后更新源资源数据库
  2. 导入并编译与代码相关的文件,例如 .dll、.asmdef、.asmref、.rsp 和 .cs 文件。
  3. 然后,如果未从脚本调用 Refresh,重新加载该域。
  4. 对导入的代码相关文件的所有资源进行后期处理
  5. 然后导入与代码无关的资源,并对所有剩余的导入资源进行后期处理
  6. 随后对资源进行热重载

资源数据库详细刷新过程

Unity 在资源数据库刷新期间执行以上部分中描述的步骤。本部分将进一步详细描述这一过程。这些步骤在一个循环中执行,某些步骤可能导致刷新过程重新启动(例如,导入资源时会创建其他资源,Unity 也需要导入这些资源)。

Unity 在以下情况下会重新启动资源数据库刷新循环:

  • 如果导入资源后,导入器用过的文件在磁盘中发生改变。
  • 如果在 OnPostProcessAllAssets 中调用了以下任一项:
  • 如果所导入文件的时间戳在导入时发生改变,会使该文件排队等待重新导入
  • 导入器在导入过程中创建了文件(例如,FBX 模型可以通过从模型提取纹理来重新启动“刷新”)。

查找磁盘中的更改

When Unity looks for changes on disk, it scans the Assets and Packages folders in your Project to check if any files have been added, modified, or deleted since the last scan. It gathers any changes into a list to process in the next step.

更新源资源数据库

Unity 收集文件列表后,将为添加或修改的文件获取文件哈希。然后会使用这些文件的 GUID 来更新资源数据库,并会删除被检测到“已删除”的文件的条目。

依赖项跟踪

资源数据库跟踪两类资源依赖项:静态依赖项动态依赖项。如果资源的任何依赖项改变,Unity 都会触发该资源的重新导入。

静态依赖项

静态依赖项是导入器所依赖的值、设置或属性。静态依赖项在导入资源之前为已知状态,并且在导入过程中不受导入器行为的影响。如果资源的静态依赖项改变,Unity 将重新导入该资源。

一些常见静态依赖项如下:

  • 资源的名称
  • 资源关联的导入器的 ID
  • 导入器的版本
  • 当前选择的构建目标平台
动态依赖项

Unity typically discovers the dynamic dependencies of an asset during the import process. This is because these dependencies are defined by the content of the source asset. For example, a Shader might reference another Shader, and a Prefab might depend on other Prefabs.

导入器还可以根据源资源的内容,有条件地使用全局状态,在这种情况下也将成为动态依赖项。这种情况的示例包括目标平台、项目的颜色空间、图形 API、脚本运行时版本或纹理压缩状态。

Unity stores these dynamic dependencies of an asset in an Asset Import Context.

导入和编译代码相关文件

在一系列已更改或已添加的文件中,Unity 收集与代码相关的文件,并将其发送到脚本编译管线。编译器从项目中的脚本文件和程序集定义文件生成程序集。有关此步骤的更多信息,请参阅脚本编译程序集定义文件的相关文档。

重新加载域

如果 Unity 检测到任何脚本更改,则会重新加载 C# 域。这样做的原因是可能已创建新的脚本化导入器 (Scripted Importer),它们的逻辑可能会影响“刷新”队列中的资源导入结果。此步骤会重新启动 Refresh() 以确保所有新的脚本化导入器生效。

导入与代码无关的资源

Unity 导入所有与代码相关的资源并重新加载域后,将继续导入其余资源。每个资源的导入器都会处理该类型的资源,并根据文件扩展名来识别应导入的文件类型。例如,TextureImporter 负责导入 .jpg、.png 和 .psd 文件等。

There are two types of importers:

Unity processes all native importers first, and then all scripted importers in a separate phase.

When an importer imports an asset file, Unity generates an AssetImportContext. The AssetImportContext reports the Static Dependencies of an asset.

另外,在导入步骤中,会发生多次回调。

预处理资源导入器调用:

后处理资源导入器调用:

所有导入完成后触发的最后一个后处理回调是 OnPostprocessAllAssets

过程中可能会发生许多事件,这些事件将对 Asset 文件夹重新启动刷新过程,其中一些事件包括:

  • 如果资源导入失败

  • 如果在刷新的导入阶段修改了资源。例如,如果列表中的文件被修改,因此其修改日期与上次刷新的日期不符。如果在 Editor 获得焦点时开始从版本控制系统中提取文件,则会发生这种情况。

  • 如果资源在导入期间创建了其他资源。例如:导入 FBX 时,可以从 FBX 中提取纹理并将其置于项目中,这意味着 Unity 必须导入这些纹理(及其生成的任何 Artifact)。

  • 如果在某次预处理/或后处理回调期间或者在 OnPostProcessAllAssets 内强制重新导入某个文件,例如,使用 AssetDatabase.ForceReserializeAssetsAssetImport.SaveAndReimport。注意,如果执行此操作,必须小心,不要引起无限的重新导入循环。

  • 如果在编译脚本后发生程序集重新加载。如果在刷新过程中生成 C# 文件,必须先编译这个新文件,以便 Unity 重新启动刷新。

  • 如果将资源另存为“仅文本”,但是必须将此资源序列化为二进制文件,这时会发生重新启动。(例如,必须将包含地形的场景序列化为二进制文件,因为如果在文本文件中将地形数据视为一系列字符,则此数据将很难处理。)

热重载

热重载是指在 Editor 开启的状态下由 Unity 导入脚本和资源并应用所有更改的过程。无论 Editor 是否处于运行模式 (Play Mode),都可能发生此情况。无需重新启动应用程序和 Editor 即可使更改生效。

更改并保存脚本时,Unity 会热重载项目的所有脚本数据。它首先将所有可序列化变量的值存储在所有加载的脚本中,重新加载脚本,然后恢复这些值。在热重载期间,存储在不可序列化变量中的所有数据都将丢失。

Note: Unity imports assets imported by the (built-in DefaultImporter)[BuiltInImporters] first, and then script assets, so it does not call any script-defined PostProcessAllAssets for default assets.

刷新结束

Once all these steps have completed, the Refresh() is complete. The Artifact Database is updated with the relevant information, and the necessary import result files are generated on disk.

资源数据库
Customizing the Asset Database workflow