【Unity】【エディタ拡張】コンポーネントに設定したHideFlagsがPrefab化したときに消える問題

コンポーネントに設定したHideFlagsがPrefab化したときに消えてしまう問題とその対処方法です。

Unity2018.3.9

問題点

コンポーネントにHideFlagsを設定するとインスペクタで表示されないようにしたりできます。 (UnityEngine.Objectの持つプロパティなのでコンポーネント以外にも使えます)

docs.unity3d.com

いま、これを使ってコンポーネントをインスペクタから表示されないようにしたとします。
そしてそのコンポーネントがアタッチされているGameObjectをPrefab化します。

すると設定したはずのHideFlagsが外れ、コンポーネントが表示されてしまいます。
バグではなく意図があっての仕様な気がしますが、これでは困ることもあるので対応してみます。

解決方法

解決方法としてはMonoBehaviourのOnValidate()でhideFlagsを設定するのがよさそうです。

using UnityEngine;

public class Example : MonoBehaviour
{
    private void OnValidate()
    {
        hideFlags |= HideFlags.HideInInspector;
    }
}

OnValidate()は結構頻繁に呼ばれますが、エディタでしか呼ばれないので問題ないです。

ちなみにこれは下記のサイトで紹介されていた方法です。
ただHideFlagsはPrefab化するときにUnity側でも変更しているため、
上記の例ではフラグを上書きではなく追加にしました。

caitsithware.com

ダメだった方法

Prefab生成・更新時のコールバックは下記のように取れるのでここで処理することもできます。

using UnityEditor;
using UnityEngine;

[InitializeOnLoad]
public class OnPrefabInstanceUpdated
{
    static OnPrefabInstanceUpdated()
    {
        PrefabUtility.prefabInstanceUpdated += OnPrefabInstanceUpdate;
    }

    private static void OnPrefabInstanceUpdate(GameObject instance)
    {
        // Prefabのインスタンスのコンポーネント
        var instanceComponents = instance.GetComponentsInChildren<MonoBehaviour>();

        foreach (var instanceComponent in instanceComponents) {
            // Prefabのコンポーネント
            var prefabComponent = PrefabUtility.GetCorrespondingObjectFromOriginalSource(instanceComponent);

            // この時点でinstanceComponentのhideFlagsはNoneに変更されてしまっているので下記のコードは意味ない
            prefabComponent.hideFlags = instanceComponent.hideFlags;

            // こうしても結果的に反映されなかった
            if (instanceComponent.GetType() == typeof(Example) || instanceComponent.GetType().IsSubclassOf(typeof(Example))) {
                prefabComponent.hideFlags |= HideFlags.HideInInspector;
            }
        }
    }
}

ただしコメントに書いている通り、この方法ではうまくいきませんでした。

参考

caitsithware.com