アセットがUnityエディタ外で変更されたことを検知する方法についてまとめました。
Unity2020.1.17f1
やりたいことと方針
YAMLを直接編集したり、バージョン管理ツールを使用するなどしてアセットをUnityエディタの外側で変更することがあります。
本記事ではこのような操作がアセットになされたことを検知するための方法についてまとめます。
実装の方針として、まず外部で変更されたアセットにはUnityエディタにフォーカスが戻ってきたときにインポート処理が走ります。
したがってAssetPostProcessor
で当該アセットがインポートされたことを検知します。
なおAssetPostProcessor
については以下の記事にまとめていますので、必要に応じて参照してください。
ただし、インポート処理は外部でアセットが変更された時以外のインポート時(Reimportしたときなど)にも走ってしまいます。
エディタ外で変更された時のみ処理するためには、Unityエディタがバックグラウンドから復帰したことを検知する必要があります。
この方法については以下の記事にまとめています。
実装
前節の方針で実装したものが以下になります。
using UnityEditor; using UnityEditorInternal; using UnityEngine; public sealed class Example : AssetPostprocessor { private static bool _isUnityEditorFocused; private static bool _needReloading; public static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) { foreach (var importedAsset in importedAssets) { // TODO: 対象のアセットを絞り込む var isTarget = importedAsset.Contains("target"); if (!isTarget) { continue; } // Unity外から戻ってきた場合には、delayCallまでの間に_needReloadingにtrueが代入される _needReloading = false; EditorApplication.delayCall += OnAssetImported; return; } } [InitializeOnLoadMethod] private static void InitializeOnLoad() { EditorApplication.update += Update; } private static void Update() { if (!_isUnityEditorFocused && InternalEditorUtility.isApplicationActive) { _isUnityEditorFocused = InternalEditorUtility.isApplicationActive; OnApplicationFocused(); } else if (_isUnityEditorFocused && !InternalEditorUtility.isApplicationActive) { _isUnityEditorFocused = InternalEditorUtility.isApplicationActive; } } private static void OnApplicationFocused() { _needReloading = true; } private static void OnAssetImported() { // この時点で_needReloadingがtrueなら、アセットに変更が加わった、かつUnity外からフォーカスが戻ってきたと判断できる if (!_needReloading) return; Debug.Log("Unity外でアセットが変更されたことを検知しました"); } }
これをEditorフォルダに配置すると、名前にtarget
が含まれるアセットがUnityエディタ外で変更されたことを検知できることが確認できます。
(名前などの条件は適宜変更してください