【Unity】スクリプトからPrefab内のGameObjectを削除・移動する方法

UnityでスクリプトからPrefab内のGameObjectを移動したり削除したりする方法です。
Unity2018.3からPrefabワークフローが変更されたのに伴い方法が変わったので紹介します。

Unity2018.3.12

誤ったパターン

まず、普通にPrefabをインスタンス化してその子のGameObjectを削除してみます。

var instance = PrefabUtility.InstantiatePrefab(prefabObject) as GameObject;
GameObject.DestroyImmediate(instance.transform.GetChild(0).gameObject);
PrefabUtility.SaveAsPrefabAsset(instance, prefabAssetPath);

これを実行すると以下のようなエラーが出ます。

InvalidOperationException: Destroying a GameObject inside a Prefab instance is not allowed.

ここで一度、シーン上にこのPrefabを置いて子GameObjectを削除しようとしてみます。
すると以下のようなエラーダイアログが出て、Prefabモードで編集するように促されます。

f:id:halya_11:20190505220924p:plain

前述のエラーはすなわちこれと同じ操作をスクリプトで行っているために発生しているというわけです。

正しいパターン

スクリプトからPrefab内のGameObjectを削除したり移動したりするには以下のように書きます。

var instance = PrefabUtility.LoadPrefabContents(prefabAssetPath);
GameObject.DestroyImmediate(instance.transform.GetChild(0).gameObject);
PrefabUtility.SaveAsPrefabAsset(instance, prefabAssetPath);
PrefabUtility.UnloadPrefabContents(instance);

PrefabUtility.LoadPrefabContents()を使っているのがポイントです。
これは要するにPrefabモードに入れたのと同様の操作になります。

docs.unity3d.com

またマニュアルにもありますが、Prefabの編集が終わったらPrefabUtility.UnloadPrefabContents()を呼んで解放する必要があるので注意が必要です。

関連

light11.hatenadiary.com

light11.hatenadiary.com

参考

docs.unity3d.com