【Unity】エディタ拡張で全プレハブからRigidbodyを削除する機能を作ってみた【C#】
はじめに
Unity4からUnity2018にアップデートする過程で100個以上あるPrefabからRigidbodyを外さなければなかったので作った。
ToolsからRemove Conponents From Prefabを選べば使えます。
Rigidbodyを書き換えれば他のコンポーネントにも対応できます。
ソース
using System.IO; using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEngine; class RemoveConponentsFromAllPrefab : MonoBehaviour { private static IEnumerator m_iEnumerator = null; [MenuItem("Tools/Remove Conponents From All Prefab")] static private void StartRemove() { var prefabs = GetPrefabs(); foreach (var p in prefabs) { // StartCoroutineがnon staticで使えないため、MoveNext()を使用 m_iEnumerator = RemoveConponentsFromPrefab(p); m_iEnumerator.MoveNext(); } } static private List<GameObject> GetPrefabs() { Debug.Log("Prefabの取得"); string directoryPath = "Assets"; List<GameObject> assets = new List<GameObject>(); // Asset以下の全ファイルを取得 string[] filePathes = Directory.GetFiles(directoryPath, "*", SearchOption.AllDirectories); foreach (var filePath in filePathes) { // Prefabファイルのみ処理を行う if (filePath.Contains(".prefab") && !filePath.Contains(".meta")) { GameObject asset = AssetDatabase.LoadAssetAtPath<GameObject>(filePath); Debug.Log("Loaded " + filePath); if (asset != null) { assets.Add(asset); } } } return assets; } static private IEnumerator RemoveConponentsFromPrefab(GameObject prefab) { // 非アクティブなオブジェクトのコンポーネントを取得するため引数にtrue var components = prefab.GetComponentsInChildren<Rigidbody>(true); if (components.Length > 0) { Debug.Log("Destroy " +components[0].name+ " in " +prefab.name); foreach (var c in components) { // Destroyでは即時反映されないためDestroyImmediateを使用 DestroyImmediate(c, true); } var go = Instantiate(prefab); //待機処理 while (go == null) { yield return null; } go = PrefabUtility.ConnectGameObjectToPrefab(go, prefab); Debug.Log("Replace " + prefab.name + " with " + go.name); PrefabUtility.ReplacePrefab(go, prefab, ReplacePrefabOptions.ConnectToPrefab); Debug.Log("Destroy " +go.name); DestroyImmediate(go, true); } } }
あとがき
StartCorutine()ではなくMoveNext()を使った方法やPrefabUtility等、学ぶ事が多かった。
もう少し使いやすさを上げてRigitbody以外にも対応させたい。
Unity2018.2では問題ないが、Unity2018.3ではPrefabUtilityが旧形式と警告されているので後々対応したい。
参考
StartCoroutine(MonoBehaviour)を使わずにコルーチンを実行する【Unity】【エディタ拡張】
http://kan-kikuchi.hatenablog.com/entry/Coroutine_Editor
【Unity】【エディタ拡張】スクリプトからPrefabを操作する(Unity2018.2まで版)
http://light11.hatenadiary.com/entry/2018/12/19/220554