MRが楽しい

MRやVRについて学習したことを書き残す

複数選択できるEnum値のEnumFlagsFieldでスクリプトから一部のフラグを有効/無効を切り替える

本日はUnityの小ネタ枠です。
複数選択できるEnum値のEnumFlagsFieldでスクリプトから一部のフラグを有効/無効を切り替える方法についてです。

EditorGUILayout.EnumFlagsField

EnumFlagsFieldを使うと、列挙型の全ての値に対する選択が可能なメニューが作成できます。
選択肢には"Nothing"(全てのビットが0)と、"Everything"(全てのビットが1)が常にメニューの最上段に表示されます。
本メソッドは sbyte、short、int、byte、ushort、uint 列挙型のみをサポートします。
docs.unity3d.com

スクリプトからEditorGUILayout.EnumFlagsFieldの一部のフラグを有効/無効を切り替える場合、以下の通り記述します。

// Aフラグを選択状態にする
flags |= FlagsEnum.A;
// Aフラグを非選択状態にする
flags &= ~FlagsEnum.A;

サンプルスクリプト

今回は以下の前回記事で作成したスクリプトを基にサンプルスクリプトを作成しました。
bluebirdofoz.hatenablog.com

以下の通り一部のフラグを有効/無効を切り替えるコンテンツメニューを追加しました。
・EnumFlagsFieldInspector.cs

using System;
using UnityEngine;

public class EnumFlagsFieldInspector : MonoBehaviour
{
    // 各ビットが列挙値インデックスを表す選択ビットマスクを使用して複数の列挙値を選択します
    [Flags]
    enum ExampleFlagsEnum
    {
        None = 0, // Nothingの選択肢をカスタム名にする
        A = 1 << 0,
        B = 1 << 1,
        AB = A | B, // 2つのフラグの組み合わせ選択肢
        C = 1 << 2,
        All = ~0, // Everythingの選択肢をカスタム名にする
    }
    
    /// <summary>
    /// フラグ
    /// </summary>
    private ExampleFlagsEnum flags;

    /// <summary>
    /// Aフラグを選択状態にする
    /// </summary>
    [ContextMenu("SetAFlag")]
    void SetAFlag()
    {
        // Aフラグを選択状態にする
        flags |= ExampleFlagsEnum.A;
    }
    
    /// <summary>
    /// Aフラグを非選択状態にする
    /// </summary>
    [ContextMenu("UnsetAFlag")]
    void UnsetAFlag()
    {
        // Aフラグを非選択状態にする
        flags &= ~ExampleFlagsEnum.A;
    }

    /// <summary>
    /// 現在のフラグをログ表示する
    /// </summary>
    [ContextMenu("Show Current Flags")]
    void ShowCurrentFlags()
    {
        Debug.Log("Show Current Flags");
        Debug.Log("Flags: " + flags);
        // 各値が設定されているかどうかを確認する
        if ((flags & ExampleFlagsEnum.A) != 0) Debug.Log("A is set");
        if ((flags & ExampleFlagsEnum.B) != 0) Debug.Log("B is set");
        if ((flags & ExampleFlagsEnum.C) != 0) Debug.Log("C is set");
    }
    
#if UNITY_EDITOR
    /// <summary>
    /// エディター拡張
    /// </summary>
    [UnityEditor.CustomEditor(typeof(EnumFlagsFieldInspector))]
    public class EditorButtonManager : UnityEditor.Editor
    {
        /// <summary>
        /// インスペクターのGUIを上書きする
        /// </summary>
        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();
            
            EnumFlagsFieldInspector instance = target as EnumFlagsFieldInspector;

            // 列挙型の全ての値に対する選択が可能なフラグフィールドを追加する
            instance.flags = (ExampleFlagsEnum)UnityEditor.EditorGUILayout.EnumFlagsField(instance.flags);
        }
    }
#endif
}

スクリプトから対象のフラグのみ選択したり、選択を外したりできています。