事の経緯。
空のゲームオブジェクトなども含まれた複雑な親子構造のFBXを読み込んで
meshrendererコンポーネントのもつプロパティ(cast Shadowsの設定など)をまとめて編集(multi-edit)したい。というお話。
で、普通にHierarchyからShiftおしながらまとめて選択すると、だいたいこうなります。
書いてある通りなんですが、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という親を選択しています。
4.ツールの、Selectボタンを押します。すると、以下のように、選択以下にあるオブジェクトからMeshRendererをもつオブジェクトだけを選択してくれます。
そして、Inspectorをご覧ください。
はい。幸せになりましたね。
Cast Shadowsとか、ReceiveShadowsとか、まとめて編集しちゃいましょう。
おまけ
ちなみに再起関数のところで、
if (ob.GetComponent<MeshRenderer>() != null)
ってやってるので、"MeshRenderer"のところを見つけたいコンポーネントクラス名に書き換えれば、
(たとえばSkinned Mesh Renderer とか!)
もっと幸せが訪れると思いますよ
こういう機能、Unity標準でないんですかね