版本:Unity 6 (6000.0)
语言:英语
自定义资源数据库工作流程
特殊文件夹名称

使用 AssetDatabase 进行批量处理

您可以使用批量处理来减少对代码中的资源进行更改时所需的时间和处理量。

如果您在代码中对多个资源进行了更改(例如,复制或移动资源文件),资源数据库的默认行为是依次处理每个更改,并在继续执行下一行代码之前对资源执行完整的刷新过程。

在下面的示例中,三个资源发生了变化。资源 1 被复制,资源 2 被移动,资源 3 被删除。

AssetDatabase.CopyAsset("Assets/Asset1.txt", "Assets/Text/Asset1.txt");
AssetDatabase.MoveAsset("Assets/Asset2.txt", "Assets/Text/Asset2.txt");
AssetDatabase.DeleteAsset("Assets/Asset3.txt");

在没有批量处理的情况下,Unity 会在继续执行下一行代码之前处理每个更改。这不仅会花费不必要的时间,还会触发许多回调,而如果您使用批量处理,则可以避免这些回调。

相反,您可以指定资源数据库应一次处理一组操作。为此,您需要在进行更改之前告诉资源数据库暂停其正常行为,然后在更改完成后告诉它恢复。

特别是,如果您正在执行以下操作中的多个操作,则应尝试使用批量处理。

  • AssetDatabase.ImportAsset
  • AssetDatabase.MoveAsset
  • AssetDatabase.CopyAsset
  • AddObjectToAsset

处理操作的方法

要指定资源数据库应一次处理一组操作,可以使用以下方法:AssetDatabase.StartAssetEditingAssetDatabase.StopAssetEditing

AssetDatabase.StartAssetEditing

此方法告诉资源数据库您已开始对资源进行编辑。资源数据库进入暂停状态,并且在您调用相应的 **StopAssetEditing** 方法来告诉它您已完成之前,不会处理对您资源的任何进一步更改。

AssetDatabase.StopAssetEditing

完成所有资源更改后,调用此方法告诉资源数据库处理您的更改并恢复其正常行为,即立即自动处理更改。然后,资源数据库会以批处理的方式处理您在 StartAssetEditingStopAssetEditing 之间所做的更改,这比逐个处理它们更快。

对 StartAssetEditing 和 StopAssetEditing 的嵌套调用

如果您多次调用 StartAssetEditing,则必须对 StopAssetEditing 进行相应的调用次数,以使资源数据库恢复其正常行为,即自动处理更改。

这是因为这些函数递增和递减一个计数器,而不是作为简单的开/关开关。调用 StartAssetEditing 会递增计数器,调用 StopAssetEditing 会递减计数器。当计数器达到零时,资源数据库将恢复其正常行为。

Unity 使用计数器而不是简单的开/关布尔值的原因是,如果您的代码执行多个嵌套的“开始”和“停止”对,则内部对不会意外地过早地重新启用资源数据库的正常行为。相反,每个对都递增和递减计数器一次,如果您的代码正确嵌套,则对 StopAssetEditing 的最终外部调用会将计数器设置为零。

注意:您的代码永远不应该使计数器低于零。这样做会生成错误。

示例

以下示例显示了使用这些方法的推荐方式

using UnityEditor;
public class StartStopAssetEditingExample : MonoBehaviour
{
    [MenuItem("APIExamples/StartStopAssetEditing")]
    static void CallAssetDatabaseAPIsBetweenStartStopAssetEditing()
    {
        try
        {
            //Place the Asset Database in a state where
            //importing is suspended for most APIs
            AssetDatabase.StartAssetEditing();
            AssetDatabase.CopyAsset("Assets/Asset1.txt", "Assets/Text/Asset1.txt");
            AssetDatabase.MoveAsset("Assets/Asset2.txt", "Assets/Text/Asset2.txt");
            AssetDatabase.DeleteAsset("Assets/Asset3.txt");
        }
        finally
        {
            //Adding a call to StopAssetEditing inside
            //a "finally" block ensures that the AssetDatabase
            //state will be reset when leaving this function
            AssetDatabase.StopAssetEditing();
        }
    }
}

为资源编辑使用 try…finally

当您调用 AssetDatabase.StartAssetEditing 时,Unity 会将整个编辑器的资源数据库置于暂停状态。因此,如果您没有对 AssetDatabase.StopAssetEditing 进行相应的调用,编辑器在执行任何与资源相关的操作(导入、刷新等)时似乎无响应,并且需要重新启动编辑器才能恢复其正常操作。

如果不使用 tryfinally 块,如果任何修改资源的代码导致错误,可能会阻止 StopAssetEditing 被调用。为了避免这种情况,将调用包装在 tryfinally 块中,并将 StartAssetEditing 和您的资源修改代码放在 try 块中,并将 StopAssetEditing 调用放在 finally 块中。这样可以确保即使您的更改在 try 块中进行时发生了任何异常,也仍然保证会调用 AssetDatabase.StopAssetEditing

自定义资源数据库工作流程
特殊文件夹名称