【Unity拡張】コンポーネントのON/OFFチェックボックスをヒエラルキー上に表示するエディター拡張を作ってみた

# はじめに
コンポーネントのON/OFFチェックボックスをヒエラルキー上に出すエディター拡張を作ってみました。

![hierarchy_toggle.gif](https://qiita-image-store.s3.amazonaws.com/0/44288/da658826-1239-fcd5-b3fc-d5eb1ecc0043.gif)
MaskコンポーネントのON/OFFをヒエラルキーから変更する例

# つくったきっかけ
オブジェクトについているコンポーネントのON/OFFを変えたいとき、
「オブジェクトをクリック -> Inspectorウィンドウ上でコンポーネントを探してチェックボックスをクリック」
という手順を踏む必要があって、若干めんどくさい。 

「ヒエラルキー上からコンポーネントを直接ON/OFFできれば少しは楽できるのではないだろうか？」
と思ったので作ってみました。

#環境
Unityのバージョン : 5.6.1f1
OS : Windows 10

# ソースコード
Unityプロジェクト内にEditorフォルダを作成し、以下のスクリプトをEditorフォルダの中へ入れてください.

```HierarchyComponentToggler.cs
namespace HierarchyComponentToggler
{
    using System.Linq;
    using UnityEngine;
    using UnityEditor;
    using UnityEditor.SceneManagement;

    /// <summary>
    /// HierachyにコンポーネントActiveチェックボックスを表示するEditorWindow
    /// </summary>
    public class HierarchyComponentToggler : EditorWindow
    {
        private const int WIDTH = 18;
        [SerializeField] private string componentName = "";
        static private string _componentName = "";

        [MenuItem("Tools/Hierarchy Component Toggler")]
        static void Open()
        {
            GetWindow<HierarchyComponentToggler>();
        }

        void OnDestroy()
        {
            _componentName = ""; // リセット
        }

        private void OnGUI()
        {
            EditorGUILayout.LabelField("指定したコンポーネントのActiveチェックボックスをHierarchyに表示します");
            EditorGUI.BeginChangeCheck();
            _componentName = this.componentName;
            this.componentName = EditorGUILayout.TextField(_componentName);
            if (EditorGUI.EndChangeCheck())
            {
                EditorApplication.delayCall += () =>
                {
                    EditorApplication.RepaintHierarchyWindow();
                };
            }
        }

        [InitializeOnLoadMethod]
        private static void Initialize()
        {
            EditorApplication.hierarchyWindowItemOnGUI += HierarchyWindowItemOnGUI;
        }

        private static void HierarchyWindowItemOnGUI(int instanceID, Rect selectionRect)
        {
            if (!IsOpen()) { return; }

            var go = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
            if (go == null) { return; }

            var component = go.GetComponent(_componentName);
            if (component == null) { return; }

            EditorGUI.BeginChangeCheck();
            var enabledProperty = component.GetType().GetProperties().FirstOrDefault(p => p.Name == "enabled");
            if (enabledProperty == null) { return; }

            var rect = selectionRect;
            rect.x = rect.xMax - WIDTH;
            rect.width = WIDTH;
            bool enabled = EditorGUI.Toggle(rect, (bool)enabledProperty.GetValue(component, null)); // ON/OFFアクティブボックスを表示
            if (EditorGUI.EndChangeCheck())
            {
                enabledProperty.SetValue(component, enabled, null);
                EditorSceneManager.MarkSceneDirty(go.scene); // シーン変更フラグ ON
            }
        }

        private static bool IsOpen()
        {
            var windows = Resources.FindObjectsOfTypeAll<HierarchyComponentToggler>();
            return windows != null && windows.Length > 0;
        }
    }
}
```
Undo処理は入れていません。

#使い方
メニューの Tools / Hierarchy Componente Toggler をクリックしてください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/a1c35a1c-f3c1-0f11-8118-37728cd204d5.png)
<br>
クリックするとウィンドウが開くので、あとはON/OFFさせたいコンポーネント名を入力するだけです
![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/c7919a17-1435-41a2-16ae-895c3e7824a6.png)

(おわり)