Version: 2019.4
资源数据库
AssetDatabase 批处理

刷新资源数据库

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 模型可以通过从模型提取纹理来重新启动“刷新”)。

查找磁盘中的更改

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

更新源资源数据库

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

依赖项跟踪

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

静态依赖项

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

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

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

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

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

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

导入和编译代码相关文件

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

重新加载域

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

导入与代码无关的资源

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

导入器分为两组:原生导入器 (Native Importer)脚本化导入器 (Scripted Importer)

原生导入器

原生导入器内置于 Unity 中,并为 Unity 的大多数基本资源类型(例如 3D 模型、纹理和音频文件)提供导入功能。

导入器 文件格式
AssemblyDefinitionImporter asmdef
AssemblyDefinitionReferenceImporter asmref
AudioImporter ogg、aif、aiff、flac、wav、mp3、mod、it、s3m、xm
ComputeShaderImporter compute
DefaultImporter rsp、unity
FBXImporter fbx、mb、ma、max、jas、dae、dxf、obj、c4d、blend、lxo
IHVImageFormatImporter astc、dds、ktx、pvr
LocalizationImporter po
Mesh3DSImporter 3ds
NativeFormatImporter anim、animset、asset、blendtree、buildreport、colors、controller、cubemap、curves、curvesNormalized、flare、fontsettings、giparams、gradients、guiskin、ht、mask、mat、mesh、mixer、overrideController、particleCurves、particleCurvesSigned、particleDoubleCurves、particleDoubleCurvesSigned、physicMaterial、physicsMaterial2D、playable、preset、renderTexture、shadervariants、spriteatlas、state、statemachine、texture2D、transition、webCamTexture、brush、terrainlayer、signal
PackageManifestImporter json
PluginImporter dll、winmd、so、jar、java、kt、aar、suprx、prx、rpl、cpp、cc、c、h、jslib、jspre、bc、a、m、mm、swift、xib、bundle、dylib、config
PrefabImporter prefab
RayTracingShaderImporter raytrace
ShaderImporter cginc、cg、glslinc、hlsl、shader
SketchUpImporter skp
SpeedTreeImporter spm、st
SubstanceImporter .sbsar
TextScriptImporter txt、html、htm、xml、json、csv、yaml、bytes、fnt、manifest、md、js、boo、rsp
TextureImporter jpg、jpeg、tif、tiff、tga、gif、png、psd、bmp、iff、pict、pic、pct、exr、hdr
TrueTypeFontImporter ttf、dfont、otf、ttc
VideoClipImporter avi、asf、wmv、mov、dv、mp4、m4v、mpg、mpeg、ogv、vp8、webm
VisualEffectImporter vfx、vfxoperator、vfxblock

脚本化导入器

您可以定义自己的导入器,从而添加新文件类型的导入功能,或覆盖现有文件类型的导入器。这些导入器被称为脚本化导入器。

注意:除了自定义导入器,Unity 自身的一些导入器也被算作脚本化导入器,并且 Unity 会在此阶段(而不是原生导入器阶段)处理它们。

Unity 随附的脚本化导入器为:

  • StyleSheetImporter(用于 .uss 文件)
  • UIElementsViewImporter(用于 .uxml 文件)

导入器导入资源文件时,会生成 AssetImportContext

AssetImportContext 用于报告资源的静态依赖项。

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

预处理资源导入器调用:

后处理资源导入器调用:

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

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

  • 如果资源导入失败

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

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

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

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

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

热重载

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

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

注意:默认资源先于脚本资源导入,因此不会为默认资源调用任何由脚本定义的 PostProcessAllAssets 回调。

刷新结束

一旦完成所有这些步骤,就完成了 Refresh() 并使用相关信息更新了 Artifact 数据库,还会在磁盘中生成必要的导入结果文件。

资源数据库
AssetDatabase 批处理