Unity3D:刷新资源数据库

推荐:将NSDT场景编辑器加入你的3D工具链
3D工具集:NSDT简石数字孪生

刷新资源数据库

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 中调用了以下任一项:
  • ForceReserializeAssets
  • AssetImporter.SaveAndImport
  • 导致出现额外“刷新”排队情况的任何 AssetDatabase API,例如 MoveAsset、CreateAsset 和 ImportAsset
  • 如果所导入文件的时间戳在导入时发生改变,会使该文件排队等待重新导入
  • 导入器在导入过程中创建了文件(例如,FBX 模型可以通过从模型提取纹理来重新启动“刷新”)。

查找磁盘中的更改

当 Unity 在磁盘上查找更改时,它会扫描项目中的 and 文件夹,以检查自上次扫描以来是否添加、修改或删除了任何文件。它将任何更改收集到一个列表中,以便在下一步中处理。AssetsPackages

更新源资源数据库

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

依赖项跟踪

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

静态依赖项

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

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

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

Unity 通常会在导入过程中发现资源的动态依赖关系。这是因为这些依赖项是由源资产的内容定义的。例如,着色器可能引用另一个着色器,而预制件可能依赖于其他预制件。

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

Unity 将资源的这些动态依赖项存储在资源导入上下文中。

导入和编译代码相关文件

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

重新加载域

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

导入与代码无关的资源

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

有两种类型的进口商:

  • 本机导入器:Unity 的内置导入器。
  • 脚本化导入器:扩展 Unity 导入功能的自定义导入程序。这些是用 C# 编写的。

Unity 首先处理所有本机导入程序,然后在单独的阶段处理所有脚本导入程序。

当导入器导入资源文件时,Unity 会生成一个资源导入上下文。AssetImportContext 报告资产的静态依赖关系。

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

预处理资源导入器调用:

后处理资源导入器调用:

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

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

  • 如果资源导入失败
  • 如果在刷新的导入阶段修改了资源。例如,如果列表中的文件被修改,因此其修改日期与上次刷新的日期不符。如果在 Editor 获得焦点时开始从版本控制系统中提取文件,则会发生这种情况。
  • 如果资源在导入期间创建了其他资源。例如:导入 FBX 时,可以从 FBX 中提取纹理并将其置于项目中,这意味着 Unity 必须导入这些纹理(及其生成的任何 Artifact)。
  • 如果在某次预处理/或后处理回调期间或者在 OnPostProcessAllAssets 内强制重新导入某个文件,例如,使用 AssetDatabase.ForceReserializeAssetsAssetImport.SaveAndReimport。注意,如果执行此操作,必须小心,不要引起无限的重新导入循环。
  • 如果在编译脚本后发生程序集重新加载。如果在刷新过程中生成 C# 文件,必须先编译这个新文件,以便 Unity 重新启动刷新。
  • 如果将资源另存为“仅文本”,但是必须将此资源序列化为二进制文件,这时会发生重新启动。(例如,必须将包含地形的场景序列化为二进制文件,因为如果在文本文件中将地形数据视为一系列字符,则此数据将很难处理。)

热重载

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

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

注意:Unity 首先导入由(内置 DefaultImporter)[内置导入器] 导入的资源,然后导入脚本资源,因此它不会为默认资源调用任何脚本定义的 PostProcessAllAssets。

刷新结束

完成所有这些步骤后,即完成。使用相关信息更新工件数据库,并在磁盘上生成必要的导入结果文件。Refresh()

此文由3D建模学习工作室整理翻译,转载请注明出处!

上一篇:Unity3D:资源数据库 (mvrlink.com)

下一篇:Unity3D:自定义资产数据库工作流 (mvrlink.com)

NSDT场景编辑器 | NSDT 数字孪生 | GLTF在线编辑器 | 3D模型在线转换 | UnrealSynth虚幻合成数据生成器 | 3D模型自动纹理化工具
2023 power by nsdt©鄂ICP备2023000829号