はじめに
AssetDatabaseはアセットの作成・削除・移動・コピーなどの操作をすることができます。特に大量のアセットに大して操作を行ったりすると、なかなか処理が終わらずにパフォーマンス上の問題がでてきたりします。
docs.unity3d.com
そこでAssetDatabase.StartAssetEditing・AssetDatabase.StopAssetEditingを用いることで、複数のアセット操作を一度の処理で行うように指示することができます。
また今回はそれらをより安全に活用できるようにしたAssetEditingScopeについて紹介したいと思います。
StartAssetEditingとStopAssetEditingについて
StartAssetEditing()を呼び出すと、一時的にAssetDataabaseの操作が行われなくなります。そしてStopAssetEditingを呼び出すことでStartAssetEditing〜StopAssetEditingの間に行った変更をバッチ処理します。デフォルトでは各変更を順番に処理して毎回アセットの完全な更新処理を実行するのに対し、一連の操作を最後に一度だけ処理を行うようにすることで処理時間を大きく削減できるというわけです。
try { AssetDatabase.StartAssetEditing(); AssetDatabase.CopyAsset("Assets/SourceFolder/MyTexture.png", "Assets/DestinationFolder/MyTexture_copy.png"); AssetDatabase.MoveAsset("Assets/SourceFolder/MyMaterial.mat", "Assets/DestinationFolder/MyMaterial_moved.mat"); } finally { AssetDatabase.StopAssetEditing(); }
またネストされている場合には、内部にカウンターを持っているのでStartAssetEditing()を実行した回数だけStopAssetEditing()を呼ぶ必要があります。
AssetDatabase.StartAssetEditing(); // Counter = 1 //... アセット操作... AssetDatabase.StartAssetEditing(); // Counter = 2 //... アセット操作... AssetDatabase.StopAssetEditing(); // Counter = 1 (まだインポートは再開されない) //... アセット操作... AssetDatabase.StopAssetEditing(); // Counter = 0 (ここでインポートが再開される)
ちなみにStopAssetEditingをStartAssetEditing以上に呼び出してしまうと、以下のようなエラーがでてきます。
Assertion failed on expression: 'gRefreshReentrancyCount > 0' StopAssetEditing invoked without a call to StartAssetEditing. Please make sure that for every call to StopAssetEditing there is at least one call to StartAssetEditing
AssetEditingScopeについて
IDisposableを実装して、usingを用いることでStartAssetEditing・StopAssetEditingを確実に行えるようにしたAssetEditingScopeがUnity 2023.1.0f1より登場しました。
github.com
2023.1.0f1
Added: Added AssetDatabase.AssetEditingScope().
Unity Release Notes (Alpha) - Search
using (var editingScope = new AssetDatabase.AssetEditingScope()) { AssetDatabase.CopyAsset("Assets/CopyAsset.txt", "Assets/Text/CopyAsset.txt"); AssetDatabase.MoveAsset("Assets/MoveAsset.txt", "Assets/Text/MoveAsset.txt"); }
AssetEditingScope - Unity スクリプトリファレンス
安全性とコードの明瞭性の観点から可能な限りAssetDatabase.AssetEditingScopeを使用して、StartAssetEditing/StopAssetEditingを直接使用する場合は、try...finallyを必ず利用するようにすると良いでしょう。