版本:Unity 6 (6000.0)
语言:English
刷新资源数据库
使用 AssetDatabase 进行批处理

自定义资源数据库工作流

使用 AssetDatabase 类自定义您的资源管道,并创建工具来使用您自己的 脚本一段代码,允许您创建自己的组件、触发游戏事件、随时间推移修改组件属性以及以任何您喜欢的方式响应用户输入。 更多信息
请参阅 术语表
访问、加载、创建和操作资源,以扩展编辑器的工作方式。它是一个编辑器类,因此其功能在独立构建的运行时不可用。

自定义您的资源工作流

AssetDatabase 类具有大量方法,允许您以与 Unity 编辑器本身完全相同的方式访问和对资源执行操作。您可以创建、导入、删除、复制、移动、加载和保存资源,以及搜索资源数据库。

这意味着您可以使用 Unity 的 编辑器脚本编辑器窗口自定义,从简单的调整到强大的工具和自定义创建项目的资源工作流。

有关简单示例,请参阅 AssetDatabase.ForceReserializeAssets 方法的文档。它展示了如何向编辑器添加菜单项,让您更好地控制在将项目升级到 Unity 的新版本时如何升级某些资源包。

有关可用方法的完整列表以及每个方法的文档,请参阅 AssetDatabase 脚本 API 页面。

资源对象

从脚本的角度来看,Unity 认为的“资源”与您在 项目窗口显示 Assets 文件夹内容的窗口(项目选项卡) 更多信息
请参阅 术语表
中看到的略有不同。您放置在项目 Assets 文件夹中的文件是资源的源文件,但它们在概念上与 Unity 编辑器使用的资源对象不同。当 Unity 导入资源文件时,它会处理这些文件并生成导入结果:派生自 UnityEngine.Object 的序列化 C# 对象。从脚本的角度来看,在 Unity 编辑器中进行脚本编写时可以访问的资源是这些导入的结果。

例如,可能以二进制文件(例如 JPEG 或 PNG 图像文件)开始的资源会被转换为类型为 UnityEngine.Object 的专门化版本的 C# 对象。对于 JPEG 或 PNG 文件,它们会被转换为 纹理渲染游戏对象、精灵或 UI 元素时使用的图像。纹理通常应用于网格的表面以使其具有视觉细节。 更多信息
请参阅 术语表
类的序列化实例,该类又继承自 UnityEngine.Object。然后,序列化对象数据会作为工件存储在 Library 文件夹中。因此,当您使用脚本访问纹理资源时,您访问的不是原始 JPEG 或 PNG 文件,而是导入原始图像文件时生成的 C# 纹理对象的序列化版本。Unity 在导入过程中创建的 .meta 文件(存储在原始资源文件旁边)包含资源的导入设置,并包含一个 GUID,允许 Unity 将原始资源文件与资源数据库中的工件连接起来。

When you import an asset, Unity creates a .meta file in the Assets folder, and an artifact file in the Library folder
导入资源时,Unity 会在 Assets 文件夹中创建一个 .meta 文件,并在 Library 文件夹中创建一个工件文件

资源文件和工件文件内部

Unity 本身创建的某些类型的资源文件,例如 .预制件一种资源类型,允许您存储包含组件和属性的完整游戏对象。预制件充当模板,您可以从中在场景中创建新的对象实例。 更多信息
请参阅 术语表
.场景场景包含游戏环境和菜单。可以将每个唯一的场景文件视为一个唯一的关卡。在每个场景中,您放置环境、障碍物和装饰,本质上是以分块的方式设计和构建游戏。 更多信息
请参阅 术语表
.asset.mat,在其源文件中已经包含序列化数据,因此 Unity 生成和缓存的工件文件与源文件非常相似。例如,项目 Assets 文件夹中的 .mat 材质文件的源文件是人类可读的(前提是 资源序列化模式 设置为 强制文本,这是默认设置)。这与从外部来源(如纹理或音频)导入的二进制资源文件形成对比,这些文件通常不可读。

资源文件可以包含多个序列化对象,并且出于使用 AssetDatabase 方法进行脚本编写的目的,每个对象都可以被视为一个“资源”。例如,.prefab 资源文件可以包含一个序列化 游戏对象Unity 场景中的基本对象,可以表示角色、道具、场景、摄像机、路径点等。游戏对象的函数由附加到它的组件定义。 更多信息
请参阅 术语表
,并附加多个组件。这些组件中的每一个也作为对象在资源文件中进行序列化,因此在使用 AssetDatabase 方法访问预制件资源的内容时,资源文件中的组件对象被视为 子资源(在下面更详细地解释)。

导入过程中生成的序列化对象称为 工件,Unity 将它们存储在资源数据库的导入工件缓存中,即项目 Library 文件夹中。它们被视为缓存数据,因为 Unity 可以始终使用导入设置和项目中保存的 项目设置广泛的设置集合,允许您配置物理、音频、网络、图形、输入和项目的许多其他方面的行为。 更多信息
请参阅 术语表
从源资源重新生成它们。

您可以使用 导入活动窗口 检查项目中资源生成的工件,该窗口显示 Unity 生成的特定缓存工件文件,以及其他有用信息,例如导入时间和花费的时间。

每个工件文件名都是一个唯一的哈希值(一个 GUID),没有文件扩展名。Unity 将这些文件分成子文件夹,每个子文件夹的名称与工件文件名的前两个字符匹配。

这些工件文件包含二进制数据,并且不设计为人类可读。虽然了解这些文件包含资源数据库使用的数据很有用,但在使用 Unity 时,您无需直接查看、编辑或使用这些文件。相反,AssetDatabase 类提供了在编辑器中处理资源所需的方法。

主资源和子资源

因为 Unity 可以将多个序列化对象存储在同一资源文件中,所以 Unity 有一个在任何资源文件中 主资源 的概念。当 Unity 创建包含单个资源(如材质)的资源文件时,主资源始终是该单个资源。对于包含多个序列化资源对象的其他类型,主资源始终是添加到文件中的第一个资源,除非使用 SetMainObject 方法另有指定。

如果这些子资源属于特定类型,有时您可以在编辑器的项目窗口中看到子资源。例如,查看项目窗口中包含“太空护卫舰”模型的此 FBX 资源文件,其视图已展开以显示它具有材质和 网格Unity 的主要图形基元。网格构成了 3D 世界的重要组成部分。Unity 支持三角形或四边形多边形网格。Nurbs、Nurms、细分曲面必须转换为多边形。 更多信息
请参阅 术语表
作为子资源。

An FBX asset file in the Project window, showing two sub-assets, a material and mesh
项目窗口中的 FBX 资源文件,显示两个子资源,一个材质和一个网格

资源也可以具有不在项目窗口中显示的子资源类型,例如上面所示的“太空护卫舰”资源文件实际上包含超过项目窗口中显示的两个子资源。如以下脚本所示,当您使用 AssetDatabase 方法访问资源文件时,您可以看到资源的实际数量

using UnityEngine;
using UnityEditor;

public class Example : MonoBehaviour
{
    [MenuItem("AssetDatabase/InspectAssets")]

    private static void InspectAssets()
    {
        Object[] data = AssetDatabase.LoadAllAssetsAtPath("Assets/Space Frigate.fbx");

        Debug.Log(data.Length + " Assets");
        foreach (Object o in data)
        {
            Debug.Log(o);
        }
    }
}

在这种情况下,输出将显示此文件的导入序列化版本包含六个资源

6 Assets
Space Frigate (UnityEngine.GameObject)
space_frigate_0 (UnityEngine.Material)
space_frigate_0 (UnityEngine.Mesh)
Space Frigate (UnityEngine.Transform)
Space Frigate (UnityEngine.MeshRenderer)
Space Frigate (UnityEngine.MeshFilter)

这是因为游戏对象、材质、网格数据本身以及 Unity 在导入过程中自动添加到游戏对象的每个组件(变换、网格过滤器和网格渲染器)都算作一个单独的序列化对象。因此,它们是资源文件的子资源,并且就 Asset Database API 而言,它们都是单独的资源。

资源导入顺序

如果您使用 AssetDatabase 类进行脚本编写,则了解 Unity 导入过程的顺序如何影响您的脚本非常重要,否则您可能会得到意外的结果。顺序如下

  1. 导入脚本资源(.cs、.dll、.asmdef 文件)
  2. 编译
  3. 域重新加载
  4. InitializeOnLoad 回调
  5. 导入所有其他资源

脚本始终在所有其他常规资源之前导入和编译,因为编辑器需要知道项目中是否存在自定义 资源后处理器脚本化导入器。这确保了编辑器在导入其余非脚本资源时使用任何新的或更改的导入器或后处理器。

InitializeOnLoad 回调函数通常用于在项目启动或脚本更改时运行一些代码。如上所述,此回调函数在 Unity 重新加载域后但开始导入资源之前运行。这意味着如果您使用 [InitializeOnLoad] 回调函数访问资源,则您的代码将在当前资源导入周期完成之前执行。特别是

  • 对于首次导入的资源,诸如 AssetDatabase.LoadAssetAtPath、AssetDatabase.FindAssets、Shader在 GPU 上运行的程序。 更多信息
    参见 术语表
    .Find、Resources.Load
    这样的方法将返回 null,因为这些资源尚未导入。

  • 对于至少已导入一次的资源,诸如 AssetDatabase.LoadAssetAtPath、AssetDatabase.FindAssets、Shader.Find、Resources.Load 这样的方法将返回资源的先前(过时)版本(如果该资源在重新加载域之前已修改),因为域重新加载发生在常规资源导入阶段之前。

在编写脚本化导入器、资源预处理器和资源后处理器时,您不应假设其他特定资源已根据任何特定顺序导入。在导入时,Unity 会根据类型将资源分组到队列中,虽然这些类型按照预定义的顺序导入,但同一类型队列中的资源将以任意顺序导入,除非您使用 ScriptedImporter.GatherDependenciesFromSourceFile。使用 GatherDependenciesFromSourceFile 还会在资源之间创建依赖关系,因此,如果一个资源被修改,则依赖它的另一个资源将被重新导入。

刷新资源数据库
使用 AssetDatabase 进行批处理