Packagesフォルダのreadonlyなprefabのvariantを作る
はじめに
Unityでprefab variantを作るときは元のprefabと同じフォルダにしか作れないせいかPackagesフォルダにあるreadonlyなprefabからvariantを作れません。
prefabの右クリックメニューを開いても以下のように作成
が無効になっています。
そのため他のフォルダにprefab variantを作るエディタ拡張を作りました。
ソース
以下のソースをEditor
フォルダに入れるとメニューが追加されてウインドウを開けます。
メニュー
ウインドウ
使い方
-
Source Prefab
にprefabを設定するとボタンが表示されます。 -
Create Variant
ボタンを押してファイル保存ダイアログで保存ボタンを押すとprefab variantが作られます。
技術的な解説
エディタ拡張を作るにあたって調べた事、はまった事を解説します。
シーン更新を抑制
- AssetDatabase.StartAssetEditing
- AssetDatabase.StopAssetEditing
- PrefabUtility.InstantiatePrefab
- DestroyImmediate
PrefabUtility.InstantiatePrefab
を呼ぶとアクティブなシーンにインスタンス化されたprefabが追加されてしまうのですが、AssetDatabase.StartAssetEditing
でアセットインポート抑制中にDestroyImmediate
も合わせて呼ぶ事でシーンの更新を防ぎます。
また、try-finallyでAssetDatabase.StopAssetEditing
を呼んで解除忘れを防ぎます。
Prefab Variant作成
PrefabUtility.SaveAsPrefabAssetAndConnect
の第1引数はインスタンス化されたGameObjectなので一旦PrefabUtility.InstantiatePrefab
でインスタンス化します。
また、保存中はAssetDatabase.StartAssetEditing
でアセットインポートが抑制されているのでAssetDatabase.StopAssetEditing
の後にAssetDatabase.LoadMainAssetAtPath
でアセットをロードします。
PrefabアセットのGameObject取得
PrefabUtility.GetCorrespondingObjectFromSourcePrefabUtility.GetCorrespondingObjectFromOriginalSource
PrefabUtility.GetCorrespondingObjectFromSource
でPackagesフォルダのprefabを取得しても何故かnullが返ってくるためPrefabUtility.GetCorrespondingObjectFromOriginalSource
も合わせて使っています。
PrefabUtility.IsPartOfPrefabAsset
でEditorGUILayout.ObjectField
の返り値がPrefabアセットである事を確認しています。
PrefabUtility.GetCorrespondingObjectFromSource
はPrefab Variantの親Prefabを返し、PrefabUtility.GetCorrespondingObjectFromOriginalSource
は多重Prefab Variantの大元のPrefabを返すものでした。
参考サイト
Discussion