Unity Edtitorでコンポーネントを一括操作

#初めに
ヒエラルキーのコンポーネントを一括で操作したい
いつも通り、まずはgoogle先生にそれっぽい事の検索から

##ありました。

https://qiita.com/OKsaiyowa/items/4380893a2a9653cf41e3

とても良いプログラムです。
ですが、今回やりたかったことは、削除だけでなく
各コンポーネントのチェックボックスを外したり、付けたりしたいので
ちょっと改造が必要がありました。

###ソースを元に色々アレンジ

元のソースはゲームオブジェクトにスクリプトつけて、実行するタイプだったのですが、
メニューから起動できるようにして、削除するだけでなく各コンポーネントのチェックボックスを付けたり
外したりできるようにしました。

```c#

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

public class OperationComponentInChild : EditorWindow
{
    public enum Operation
    {
        Enabled,
        Disabled,
        Delete,
    };
    private GameObject _objGameObj = null;
    private Operation _operation = Operation.Enabled;

    private List<string> _componentName = new List<string>();
    private int _componentIndex = 0;

    [MenuItem("tool/OperationComponentInChild")]
    static private void Show()
    {
        GetWindow<OperationComponentInChild>();
    }

    /// <summary>
    /// コンポーネントを探す
    /// </summary>
    private void SearchComponent()
    {
        _componentIndex = 0;
        _componentName.Clear();
        _componentName.Add("ALL");
        var components = _objGameObj.GetComponentsInChildren<UnityEngine.Component>();
        foreach (var component in components)
        {
            if (component == null)
                continue;
            if (component.GetType() != typeof(Transform))
            {
                _componentName.Add(component.GetType().Name);
            }
        }
    }

    private void OnGUI()
    {
        // 自身のSerializedObjectを取得
        var so = new SerializedObject(this);
        EditorGUI.BeginChangeCheck();

        _objGameObj = EditorGUILayout.ObjectField("RootGameObj", _objGameObj, typeof(GameObject), true) as GameObject;

        if (EditorGUI.EndChangeCheck() && _objGameObj)
        {
            SearchComponent();
        }

        if (_objGameObj)
        {
            EditorGUILayout.Space();
            _operation = (Operation)EditorGUILayout.EnumPopup("Operation", _operation);

            EditorGUILayout.Space();
            _componentIndex = EditorGUILayout.Popup("操作したいコンポーネント", _componentIndex, _componentName.ToArray());
			
            EditorGUILayout.Space();
            if (GUILayout.Button("Operation Set"))
            {
                var executionFlag = true;
                if (_operation == Operation.Delete)
                {
                    if (!EditorUtility.DisplayDialog("確認", "コンポーネントを削除していいですか？", "Yes", "No"))
                    {
                        executionFlag = false;
                    }
                }

                if (executionFlag)
                {
                    GetComAndDes();
                }
            }
        }

        so.Update();
        so.ApplyModifiedProperties();

    }

    /// <summary>
    /// コンポーネントを取得して該当コンポーネントを操作
    /// </summary>
    private void GetComAndDes()
    {
        var components = _objGameObj.GetComponentsInChildren<UnityEngine.Component>();
        foreach (var component in components)
        {
            if (component == null)
                continue;
            //
            if (component.GetType().Name == _componentName[_componentIndex] || _componentIndex == 0)
            {
                if (component.GetType() != typeof(Transform))
                {
                    Debug.Log($"{_operation.ToString()} Operation name {component.gameObject.name} component {component.GetType().Name} ");
                    switch (_operation)
                    {
                            // true
                        case Operation.Enabled:
                            SetComponentObj(component, true);
                            break;
                            //　false
                        case Operation.Disabled:
                            SetComponentObj(component, false);
                            break;
                        //削除
                        case Operation.Delete:
                            DestroyImmediate(component);
                            break;
                    }
                    EditorUtility.SetDirty(component.gameObject);
                }
            }
        }
    }

    /// <summary>
    /// オブジェクトの操作
    /// </summary>
    /// <param name="comp"></param>
    /// <param name="flag"></param>
    private void SetComponentObj(Component comp, bool flag )
    {
        var be = (comp is Behaviour ? (Behaviour)comp : null);
        var re = (comp is Renderer ? (Renderer)comp : null);
        var coll = (comp is Collider ? (Collider)comp : null);

        if (be != null)
        {
            be.enabled = flag;
        }
        else if (re != null)
        {
            re.enabled = flag;
        }
        else if (coll != null)
        {
            coll.enabled = flag;
        }
        else
        {
            Debug.Log($"none : {comp.GetType()}");
        }
    }
}

```

こんな画面に
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37068/b24ae650-a7f6-6672-e848-febc1da0adef.png)

Selectで選んだり
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37068/2c3cc693-b8d1-9ca5-f6ab-465a97041962.png)

参考にしたものは、文字列を入れて文字列比較で、見つけて削除してましたけど。
初めに、コンポーネントを調べているので、選択で選べるようにしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37068/020a10eb-6f9b-5a01-e444-4828ad3109ba.png)


一応削除する時は確認も出ます。
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37068/66da4d3d-3e66-e55a-b2a7-cc2e923ca6bc.png)


####色々苦労したところ
チェックボックスだけを外すのにがてこずった。。

```c#
        var components = _objGameObj.GetComponentsInChildren<UnityEngine.Component>();
```

でComponentには、チェックボックスを外すenabledフラグを外す変数がない。。
各コンポーネントはComponentクラスを継承したクラスがそれぞれ用意している

https://docs.unity3d.com/jp/current/ScriptReference/Behaviour.html

https://docs.unity3d.com/jp/current/ScriptReference/MeshRenderer.html

https://docs.unity3d.com/ja/current/ScriptReference/Collider.html


```c#
       var be = (comp is Behaviour ? (Behaviour)comp : null);
       var re = (comp is Renderer ? (Renderer)comp : null);
       var coll = (comp is Collider ? (Collider)comp : null);
 ```
コンポーネントが含まれているかチェックして含まれているならキャストして
それぞれのコンポーネントクラスのenabled変数を操作するようにしました。


#####最後に
もっといい方法ないのかな。。
キャストして操作するのちょっと手間と言うか一気に出来たらいいのですが。。。
どなたか教えてください。。。