Unity 在以下情况下刷新资源数据库
一些其他 AssetDatabase API 会触发 Refresh(),但仅针对您指定的资源。例如CreateAsset() 和ImportAsset()。
Unity 在资源数据库刷新期间执行以下步骤
Unity 在资源数据库刷新期间执行上一节中描述的步骤。本节更详细地描述了此过程。这些步骤在循环内发生,某些步骤可能会导致刷新过程重新启动(例如,如果导入资源创建了 Unity 也需要导入的其他资源)。
Unity 在以下条件下重新启动资源数据库刷新循环
当 Unity 查找磁盘上的更改时,它会扫描项目中的Assets
和Packages
文件夹,以检查自上次扫描以来是否有任何文件添加、修改或删除。它将所有更改收集到一个列表中,以便在下一步中处理。
一旦 Unity 收集了文件列表,它就会获取已添加或修改的文件的文件哈希值。然后,它使用这些文件的 GUID 更新资源数据库,并删除它检测为已删除的文件的条目。
资源数据库跟踪两种类型的资源依赖项:静态依赖项和动态依赖项。如果任何资源的依赖项发生更改,Unity 将触发该资源的重新导入。
静态依赖项是导入程序依赖的值、设置或属性。静态依赖项在导入资源之前是已知的,并且不受导入过程中导入程序行为的影响。如果资源的静态依赖项发生更改,Unity 将重新导入该资源。
一些常见的静态依赖项包括
Unity 通常在导入过程中发现资源的动态依赖项。这是因为这些依赖项由源资源的内容定义。例如,一个着色器在 GPU 上运行的程序。 更多信息
参见 词汇表可能会引用另一个着色器,而一个预制件一种资产类型,允许您存储一个包含组件和属性的完整游戏对象。预制件充当模板,您可以从中在场景中创建新的对象实例。 更多信息
参见 词汇表可能会依赖于其他预制件。
导入程序还可以根据源资源的内容有条件地使用全局状态,在这种情况下,它也成为动态依赖项。此类示例包括目标平台、项目的颜色空间、图形 API、脚本运行时版本或纹理压缩一种存储数据的方法,可以减少其所需的存储空间。请参阅 纹理压缩、动画压缩、音频压缩、构建压缩。
参见 词汇表状态。
Unity 将资源的这些动态依赖项存储在资源导入上下文中。
在已更改或添加的文件列表中,Unity 收集与代码相关的文件,并将其发送到脚本编译管道。编译器从项目中的脚本文件和程序集定义文件生成程序集。有关此步骤的更多信息,请参阅有关脚本编译程序集定义文件的文档。
如果 Unity 检测到任何脚本更改,它将重新加载 C# 域。这样做是因为可能会创建新的脚本导入程序,并且它们的逻辑可能会影响刷新队列中资源的导入结果。此步骤重新启动 Refresh() 以确保任何新的脚本导入程序生效。
一旦 Unity 导入所有与代码相关的资源并重新加载域,它就会继续处理剩余的资源。每个资源的导入程序都会处理该类型的资源,并根据文件名扩展名识别它应该导入的文件类型。例如,TextureImporter 负责导入 .jpg、.png 和 .psd 文件等。
有两种类型的导入程序
Unity 首先处理所有原生导入程序,然后在单独的阶段处理所有脚本导入程序。
当导入程序导入资源文件时,Unity 会生成一个AssetImportContext。AssetImportContext 报告资源的静态依赖项。
此外,在导入步骤中,会发生许多回调。
预处理资源导入程序调用
OnPreprocessAsset
OnPreprocessAnimation
OnPreprocessAudio
OnPreprocessModel
OnPreprocessSpeedTree
OnPreprocessTexture
后处理资源导入程序调用
OnAssignMaterialModel
OnPostprocessAnimation
OnPostprocessAssetbundleNameChanged
OnPostprocessAudio
OnPostprocessCubemap
OnPostprocessGameObjectWithAnimatedUserProperties
OnPostprocessGameObjectWithUserProperties
OnPostprocessMaterial
OnPostprocessMeshHierarchy
OnPostprocessModel
OnPostprocessSpeedTree
OnPostprocessSprites
OnPostprocessTexture
最后一个后处理回调是在所有导入完成后触发的OnPostprocessAllAssets
。
可能会发生许多会导致资源文件夹上刷新过程重新启动的事情,其中一些包括
如果资源导入失败
如果资源在刷新的导入阶段被修改。例如,如果列表中的文件被修改,因此其修改日期与上次刷新时的日期不同。如果编辑器有焦点时,您开始从版本控制用于管理文件更改的系统。您可以将 Unity 与大多数常见的版本控制工具结合使用,包括 Perforce、Git、Mercurial 和 PlasticSCM。 更多信息
参见 词汇表系统中提取文件,则可能会发生这种情况。
如果资源在导入过程中创建了其他资源。例如:导入 FBX 时,可以从 FBX 中提取纹理并放置到项目中,这意味着 Unity 必须导入纹理(以及它们生成的任何构件)。
如果在某个预/后处理回调或 OnPostProcessAllAssets 内部强制重新导入文件,例如,使用AssetDatabase.ForceReserializeAssets
或AssetImport.SaveAndReimport
。请注意,如果您这样做,必须小心不要导致无限的重新导入循环。
如果在编译脚本允许您创建自己的组件、触发游戏事件、随时间推移修改组件属性并以任何您喜欢的方式响应用户输入的代码片段。 更多信息
参见 词汇表后发生程序集重新加载。如果在刷新过程中生成 C# 文件,则必须编译该新文件,因此 Unity 将重新启动刷新。
如果将资源保存为“仅文本”,但资源必须序列化为二进制文件,则会发生重新启动。(例如,包含地形的场景必须序列化为二进制文件,因为如果将地形数据视为文本文件中的字符数组,则它将难以处理。)
热重载是指 Unity 在编辑器打开时导入并应用对脚本和资源的任何更改的过程。这可能发生在编辑器处于播放模式或编辑模式时。您无需重新启动应用程序或编辑器即可使更改生效。
当您更改并保存脚本时,Unity 会热重载项目的所有脚本数据。它首先存储所有已加载脚本中所有可序列化变量的值,重新加载脚本,然后恢复这些值。在热重载期间,存储在不可序列化变量中的所有数据都会丢失。
这会影响所有编辑器窗口和项目中的所有 MonoBehaviour。与其他序列化情况不同,Unity 在重新加载时默认序列化私有字段,即使它们没有SerializeField 属性。
注意:Unity 首先导入由内置 DefaultImporter导入的资源,然后导入脚本资源,因此它不会为默认资源调用任何脚本定义的 PostProcessAllAssets。
一旦所有这些步骤完成,Refresh()
就完成了。构件数据库将使用相关信息更新,并在磁盘上生成必要的导入结果文件。