Version: 2022.2
言語: 日本語
アセットデータベースワークフローのカスタマイズ
Special folder names

AssetDatabase によるバッチ処理

バッチ処理を使用すると、コードのアセットに変更を加えるときにかかる時間と処理を減らすことができます。

コード内の複数のアセットに変更を加える場合 (例えば、アセットファイルのコピーや移動)、アセットデータベースのデフォルトの動作は各変更を順番に処理し、コードの次の行に進む前にアセットの完全な更新処理を実行します。

以下の例では、3 つのアセットが変更されています。Asset1 がコピーされ、Asset2 が移動され、Asset3 が削除されています。

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 の間に行った変更をバッチ処理します。これは、それらが 1 つずつ処理された場合よりも短時間で済みます。

StartAssetEditing と StopAssetEditing のネストされた呼び出し

StartAssetEditing を複数回呼び出す場合は、対応する数の StopAssetEditing を呼び出して、アセットデータベースに自動的に変更を処理する通常の動作を再開させる必要があります。

なぜなら、これらの関数は単純なオン/オフのスイッチとして機能するのではなく、カウンターを増減させるためです。StartAssetEditing を呼び出すとカウンターを増加させ StopAssetEditing は減少させます。アセットデータベースは、カウンターがゼロになると通常動作を再開します。

Unity が単純なオン/オフのブーリアンではなくカウンターを使用する理由は、コードが複数のネストされた “開始” と “停止” のペアを実行する場合に、内部のペアが誤ってアセットデータベースの通常動作を早期に再開しないようにするためです。代わりに、各ペアが 1 ずつカウンターを増加し減少します。コードが正しくネストされている場合、StopAssetEditing への最後の外部への呼び出しによってカウンターが 0 になります。

ノート: カウンターが 0 未満になるようにコードを記述しないでください。そのようにすると、エラーが発生します。

以下の例は、これらのメソッドの推奨される使用方法を示しています。

using UnityEditor;
public class StartStopAssetEditingExample : MonoBehaviour
{
    [MenuItem("APIExamples/StartStopAssetEditing")]
    static void CallAssetDatabaseAPIsBetweenStartStopAssetEditing()
    {
        try
        {
            //ほとんどのAPIでインポートが一時停止されている状態で
            //アセットデータベースを配置します
            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
        {
            //finally ブロック内にStopAssetEditingを追加すると、
            //この関数が終了するときにAssetDatabaseの状態が
            //確実にリセットされます。
            AssetDatabase.StopAssetEditing();
        }
    }
}

アセット編集に try…finally を使用

AssetDatabase.StartAssetEditing を呼び出すと 、Unity はエディターの AssetDatabase 全体を一時停止の状態にします。したがって、対応する呼び出し StopAssetEditing を AssetDatabase に対して呼び出さない場合、アセット関連の操作 (インポート、更新など) を行うとエディターが応答しなくなり、通常操作に戻すにはエディターの再起動が必要になります。

tryfinally ブロックを使用しない場合、 アセットを変更するコードのいずれかでエラーが発生すると、StopAssetEditing が呼び出されない場合があります。このような状況を避けるために、tryfinally ブロック内に呼び出しをラップします。StartAssetEditing とアセットを変更するコードを try ブロックに、StopAssetEditingfinally ブロックに記述します。これにより、try ブロックで変更を行っている間に例外が発生した場合でも、AssetDatabase.StopAssetEditing が呼び出されることが保証されます。

アセットデータベースワークフローのカスタマイズ
Special folder names