美文网首页
Unity 编辑器扩展十 多选枚举

Unity 编辑器扩展十 多选枚举

作者: 合肥黑 | 来源:发表于2021-12-12 08:42 被阅读0次

参考
Unity实现多选枚举
unity 多选枚举
【Unity】在Inspector上显示自定义的位掩码枚举(Flags)
Unity 实现枚举多选

这个功能在实际开发中,其实很少用到。但大家在平常的使用中,其实经常遇到。摄像机Camera的Clear Flags 和Culling Mask属性都是典型的例子。它的作用在这里体现出来,当你的属性有很多值,并且这些值还可以多选时,使用枚举多选就非常方便了。


image.png
一、示例
1.Scripts/EnumFlags.cs 做个自定义标签
using UnityEngine;
public class EnumFlags : PropertyAttribute
{
}
2.Scripts/EnumTenToTwo.cs 实际测试用的脚本,使用了EnumFlags标签
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum BookCount
{
    One = 1,
    Two = 2,
    Three = 4,
    Four = 8,
    Five = 16,
    Six = 32,
    Seven = 64,
    Eight = 128,
    Nine = 256,
    Ten = 512,
    Eleven = 1024
}
public class EnumTenToTwo : MonoBehaviour
{
    [EnumFlags]
    public BookCount bookCount;
    public static EnumTenToTwo instance;
    void Awake()
    {
        instance = this;
    }
    // Start is called before the first frame update
    void Start()
    {
        SwitchState(bookCount);
    }

    // Update is called once per frame
    void Update()
    {

    }
    public void Number()
    {
    }
    private void SwitchState(BookCount type)
    {
        if ((BookCount.One & type) == BookCount.One)     //&判断type是否存在one这个枚举,与one做判断,
        {

            Debug.Log("我进入One环节");
        }
        if ((BookCount.Two & type) == BookCount.Two)
        {

            Debug.Log("我进入Two环节");
        }
        if ((BookCount.Three & type) == BookCount.Three)
        {

            Debug.Log("我进入There环节");
        }
        if ((BookCount.Four & type) == BookCount.Four)
        {

            Debug.Log("我进入Four环节");
        }

        if ((BookCount.Five & type) == BookCount.Five)
        {

            Debug.Log("我进入Five环节");
        }

        if ((BookCount.Six & type) == BookCount.Six)
        {

            Debug.Log("我进入Six环节");
        }

        if ((BookCount.Seven & type) == BookCount.Seven)
        {

            Debug.Log("我进入Seven环节");
        }

        if ((BookCount.Eight & type) == BookCount.Eight)
        {

            Debug.Log("我进入Eight环节");
        }

        if ((BookCount.Nine & type) == BookCount.Nine)
        {

            Debug.Log("我进入Nine环节");
        }

        if ((BookCount.Ten & type) == BookCount.Ten)
        {

            Debug.Log("我进入Ten环节");
        }
        if ((BookCount.Eleven & type) == BookCount.Eleven)
        {

            Debug.Log("我进入Eleven环节");
        }
    }
}

3.Editor/EnumFlagsAttributeDrawer.cs
using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(EnumFlags))]
public class EnumFlagsAttributeDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        property.intValue = EditorGUI.MaskField(position, label, property.intValue
        , property.enumNames);
    }
}
最终效果
二、MaskField

https://docs.unity.cn/cn/current/ScriptReference/EditorGUI.MaskField.html

  • public static int MaskField (Rect position, GUIContent label, int mask, string[] displayedOptions, GUIStyle style= EditorStyles.popup);
  • public static int MaskField (Rect position, string label, int mask, string[] displayedOptions, GUIStyle style= EditorStyles.popup);
  • public static int MaskField (Rect position, int mask, string[] displayedOptions, GUIStyle style= EditorStyles.popup);

参数

  • position 屏幕上用于此控件的矩形。
  • label 字段的标签。
  • mask 要显示的当前掩码。
  • displayedOption 包含每个标志的标签的字符串数组。
  • style 可选 GUIStyle。
  • displayedOptions 包含每个标志的标签的字符串数组。

创建一个适用于掩码的字段。注意:与菜单中的每个选项相关联的标志的掩码值将为从 1 开始的连续 2 次幂(即 1、2、4、8、16,以此类推)。

image.png

这里可以对照上面示例中的代码,比如从 1 开始的连续 2 次幂

public enum BookCount
{
    One = 1,
    Two = 2,
    Three = 4,
    Four = 8,
    Five = 16,
    Six = 32,
    Seven = 64,
    Eight = 128,
    Nine = 256,
    Ten = 512,
    Eleven = 1024
}
三、示例
1.Scripts/EnumFlags.cs 做个自定义标签

using UnityEngine;
public class EnumFlags : PropertyAttribute
{
}

2.MyWdsCompoment.cs
using UnityEngine;
using System.Collections;


public enum LayerMaskEnum
{
    Layer1,
    Layer2,
    Layer3,
    Layer4,
    Layer5,
    Layer6,
    Layer7,
    Layer8,
    Layer9,
    Layer10
}

public class MyWdsCompoment : MonoBehaviour
{

    [EnumFlags]
    public LayerMaskEnum layer;
    [ContextMenu("输出Layer值")]
    public void DebugPrint()
    {
        Debug.Log("layer=" + (int)layer);
        Debug.Log(IsSelectEventType(LayerMaskEnum.Layer10));
    }
    //判断是否选择了该枚举值
    public bool IsSelectEventType(LayerMaskEnum _eventType)
    {
        // 将枚举值转换为int 类型, 1 左移 
        int index = 1 << (int)_eventType;
        // 获取所有选中的枚举值
        int eventTypeResult = (int)layer;
        // 按位 与
        if ((eventTypeResult & index) == index)
        {
            return true;
        }
        return false;
    }
}
3.EnumFlagsAttributeDrawer1.cs
using UnityEngine;
using System.Collections;
using UnityEditor;

[CustomPropertyDrawer(typeof(EnumFlags))]
public class EnumFlagsAttributeDrawer1 : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        /*
         * 绘制多值枚举选择框,0 全部不选, -1 全部选中, 其他是枚举之和
         * 枚举值 = 当前下标值 ^ 2
         * 默认[0^2 = 1 , 1 ^2 = 2,  4, 16 , .....]
         */
        property.intValue = EditorGUI.MaskField(position, label, property.intValue
                                                , property.enumNames);

    }
}
image.png

当我们选中layer值后,比如


image.png

输出Layer值,发现是10,也就是Layer2对应2,Layer4对应8。不过代码中LayerMaskEnum的值,并没有按照1,2,4,8这种顺序去枚举定义,难道MaskField方法自动纠正了??

相关文章

网友评论

      本文标题:Unity 编辑器扩展十 多选枚举

      本文链接:https://www.haomeiwen.com/subject/umtrtrtx.html