Unity 在以下情况下会刷新资源数据库:
其他一些 AssetDatabase API 会触发 Refresh(),但是仅针对您指定的资源。例如,CreateAsset() 和 ImportAsset()。
Unity 在资源数据库刷新期间执行以下步骤:
1.查找资源文件的更改,然后更新源资源数据库 2.导入并编译与代码相关的文件,例如 .dll、.asmdef、.asmref、.rsp 和 .cs 文件。 3.然后,如果未从脚本调用 Refresh,重新加载该域。 4.对导入的代码相关文件的所有资源进行后期处理 5.然后导入与代码无关的资源,并对所有剩余的导入资源进行后期处理 6.随后对资源进行热重载
Unity 在资源数据库刷新期间执行以上部分中描述的步骤。本部分将进一步详细描述这一过程。这些步骤在一个循环中执行,某些步骤可能导致刷新过程重新启动(例如,导入资源时会创建其他资源,Unity 也需要导入这些资源)。
Unity 在以下情况下会重新启动资源数据库刷新循环:
Unity 查找磁盘中的更改时会扫描项目中的 Assets 和 Packages 文件夹,从而检查自上次扫描以来是否已添加、修改或删除任何文件。它将所有更改收集到列表中,以供下一步处理。
Unity 收集文件列表后,将为添加或修改的文件获取文件哈希。然后会使用这些文件的 GUID 来更新资源数据库,并会删除被检测到“已删除”的文件的条目。
资源数据库跟踪两类资源依赖项:静态依赖项和动态依赖项。如果资源的任何依赖项改变,Unity 都会触发该资源的重新导入。
静态依赖项是导入器所依赖的值、设置或属性。静态依赖项在导入资源之前为已知状态,并且在导入过程中不受导入器行为的影响。如果资源的静态依赖项改变,Unity 将重新导入该资源。
一些常见静态依赖项如下:
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 随附的脚本化导入器为:
导入器导入资源文件时,会生成 AssetImportContext。
AssetImportContext 用于报告资源的静态依赖项。
另外,在导入步骤中,会发生多次回调。
预处理资源导入器调用:
OnPreprocessAsset
OnPreprocessAnimation
OnPreprocessAudio
OnPreprocessModel
OnPreprocessSpeedTree
OnPreprocessTexture
后处理资源导入器调用:
OnAssignMaterialModel
OnPostprocessAnimation
OnPostprocessAssetbundleNameChanged
OnPostprocessAudio
OnPostprocessCubemap
OnPostprocessGameObjectWithAnimatedUserProperties
OnPostprocessGameObjectWithUserProperties
OnPostprocessMaterial
OnPostprocessMeshHierarchy
OnPostprocessModel
OnPostprocessSpeedTree
OnPostprocessSprites
OnPostprocessTexture
所有导入完成后触发的最后一个后处理回调是 OnPostprocessAllAssets
。
过程中可能会发生许多事件,这些事件将对 Asset 文件夹重新启动刷新过程,其中一些事件包括:
如果资源导入失败
如果在刷新的导入阶段修改了资源。例如,如果列表中的文件被修改,因此其修改日期与上次刷新的日期不符。如果在 Editor 获得焦点时开始从版本控制系统中提取文件,则会发生这种情况。
如果资源在导入期间创建了其他资源。例如:导入 FBX 时,可以从 FBX 中提取纹理并将其置于项目中,这意味着 Unity 必须导入这些纹理(及其生成的任何 Artifact)。
如果在某次预处理/或后处理回调期间或者在 OnPostProcessAllAssets 内强制重新导入某个文件,例如,使用 AssetDatabase.ForceReserializeAssets
或 AssetImport.SaveAndReimport
。注意,如果执行此操作,必须小心,不要引起无限的重新导入循环。
如果在编译脚本后发生程序集重新加载。如果在刷新过程中生成 C# 文件,必须先编译这个新文件,以便 Unity 重新启动刷新。
如果将资源另存为“仅文本”,但是必须将此资源序列化为二进制文件,这时会发生重新启动。(例如,必须将包含地形的场景序列化为二进制文件,因为如果在文本文件中将地形数据视为一系列字符,则此数据将很难处理。)
热重载是指在 Editor 开启的状态下由 Unity 导入脚本和资源并应用所有更改的过程。无论 Editor 是否处于运行模式 (Play Mode),都可能发生此情况。无需重新启动应用程序和 Editor 即可使更改生效。
更改并保存脚本时,Unity 会热重载所有当前加载的脚本数据。它首先将所有可序列化变量存储在所有加载的脚本中,并在加载脚本后恢复这些变量。热重载后,所有不可序列化的数据都会丢失。
注意:默认资源先于脚本资源导入,因此不会为默认资源调用任何由脚本定义的 PostProcessAllAssets 回调。
一旦完成所有这些步骤,就完成了 Refresh() 并使用相关信息更新了 Artifact 数据库,还会在磁盘中生成必要的导入结果文件。