SuiTechLog

Unity,Arduino,RaspberryPiなど、モノづくり系を気ままに書き残すブログ。

Unity Editor拡張 複数のオブジェクトからメッシュレンダラーをもったやつだけ選択したい!


事の経緯。

 空のゲームオブジェクトなども含まれた複雑な親子構造のFBXを読み込んで

meshrendererコンポーネントのもつプロパティ(cast Shadowsの設定など)をまとめて編集(multi-edit)したい。というお話。

 

で、普通にHierarchyからShiftおしながらまとめて選択すると、だいたいこうなります。

f:id:sui332015:20170528162646j:plain

 書いてある通りなんですが、meshrendererコンポーネントを持っていないオブジェクトも選択にまざっているので、multi-editできないよ。とのこと。当然空のゲームオブジェクトだったり、ボーンだったりmeshrenderer持ってないのも選択に混ざっちゃいますよね。

 

 手動で膨大な親子構造からmeshrendererをもつオブジェクトだけを選択するのはアホらしいので、Editorスクリプト作ってみました。そもそもヒューマンエラーがでそうですし。 

 

複数のオブジェクトからメッシュレンダラーをもったやつだけ選択するスクリプト

はい。ようやく本題。スクリプトは以下です。 


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor; // エディタ拡張関連はUnityEditor名前空間に定義されているのでusingしておく。


public class UtilityTool : EditorWindow
{
    // メニューにSuisanTool項目を追加。
    [MenuItem("SuisanTool/Utility Tools")]
    static void Open()
    {
        EditorWindow.GetWindow("Utility Tools");
    }

    //
    //再起関数。子供を取得
    //
    void GetChildren(GameObject obj, ref List allChildren)
    {
        Transform children = obj.GetComponentInChildren();
        //子要素がいなければ終了
        if (children.childCount == 0)
        {
            return;
        }
        //子要素がいるなら、リストに追加して、さらに再起する
        foreach (Transform ob in children)
        {
            if (ob.GetComponent() != null)
            {
                allChildren.Add(ob.gameObject);
            }
            GetChildren(ob.gameObject, ref allChildren);
        }
    }

    //
    //全ての子供を取得する関数
    //
    List GetAllChildren(GameObject in_object)
    {
        List allChildren = new List();
        GetChildren(in_object, ref allChildren);
        return allChildren;
    }

    void OnGUI()
    {
        //
        // MeshRendererをもった子オブジェクトを選択ツール
        //
        EditorGUILayout.LabelField("Select Children which have Mesh renderer");
        if (GUILayout.Button("Select"))
        {
            foreach (GameObject go in Selection.gameObjects)
            {
                List listmesh = GetAllChildren(go);
                Selection.activeGameObject = null;
                Selection.objects = listmesh.ToArray();
            }
        }
    }
}

 

これを、Asset以下にEditorフォルダを作ってそこにUtilityTool.csファイルとしておいてください。

 

使い方

1.Asset以下のEditorフォルダにスクリプトをおいておくと、自動的に上部メニューバーにSuisanToolが追加されます。

 

2.クリックしてUtilityToolを実行すると、ボタンのついたウインドウが立ち上がります。

 

3.以下のように、Hierarchyビューから、実行したいプレハブなどのオブジェクトルートをひとつ選択します。この場合はEngineGroupという親を選択しています。

f:id:sui332015:20170528164058j:plain

 

4.ツールの、Selectボタンを押します。すると、以下のように、選択以下にあるオブジェクトからMeshRendererをもつオブジェクトだけを選択してくれます。

f:id:sui332015:20170528164158j:plain

 

そして、Inspectorをご覧ください。

f:id:sui332015:20170528162641j:plain

 はい。幸せになりましたね。

Cast Shadowsとか、ReceiveShadowsとか、まとめて編集しちゃいましょう。

 

 おまけ

 

 ちなみに再起関数のところで、

if (ob.GetComponent<MeshRenderer>() != null)


ってやってるので、"MeshRenderer"のところを見つけたいコンポーネントクラス名に書き換えれば、

(たとえばSkinned Mesh Renderer とか!)

もっと幸せが訪れると思いますよ

 

こういう機能、Unity標準でないんですかね