[unity editor]編集したデータを確実に保存する方法

開発効率を上げるため、様々なエディタ拡張機能を作成すると思いますが、以下のような問題を抱えたことはないでしょうか?

[エディタ拡張で]
ScriptableObject を作成・編集したのに、一旦 unity を落として開き直すと消えてしまう
.cs ファイルを作成・編集したのに、ソースコードがコンパイルされない

これらの問題の簡単な解決方法です。

ScriptableObject をツール(エディタ拡張)で作成・編集したら

ScriptableObject に対して EditorUtility.SetDirty() を使います。

// ScriptableObjectのパスは 'Assets/' から始まる相対パス
ScriptableObject obj = AssetDatabase.LoadAssetAtPath(”ScriptableObjectのパス”, typeof(ScriptableObject)) as ScriptableObject;
// 変更を通知
EditorUtility.SetDirty(obj);
AssetDatabase.SaveAssetIfDirty(obj);

.cs をツール(エディタ拡張)で作成したら

こちらの場合は AssetDatabase.ImportAsset() を使います。

// ソースコードのパスは 'Assets/' から始まる相対パス
File.WriteAllText("ソースコードのパス", newtext, Encoding.UTF8);
// ファイルの変更を通知
AssetDatabase.ImportAsset("ソースコードのパス");

ダメ押しで使うおまじない

おそらく全アセットを確認するためか、重いので多用は厳禁です。

AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);

それでもどうにもならない…

たまたまわたしが体験したのは、「同フレームに .cs 書き換えと BuildPipeline.BuildAssetBundles() を実行すると、変更したソースコードのコンパイルをしてくれない」というものでした。
(とてもレアケースだと自覚しています)

// ↓このソースコードのコンパイルが走らない…
File.WriteAllText("ソースコードのパス", newtext, Encoding.UTF8);
AssetDatabase.ImportAsset("ソースコードのパス");
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
BuildPipeline.BuildAssetBundles(~);

実はこれ、File.WriteAllText()BuildPipeline.BuildAssetBundles() の後に移動すると上手くいったりしました。
BuildPipeline.BuildAssetBundles() の中でビルドしてる辺りが問題だったのかなと推測するしかないのですが、こういう理由がよくわからない挙動もあるにはある、と覚えておいてください😢