【问题标题】:EditorGuiLayout.MaskField issue with large enums大型枚举的 EditorGuiLayout.MaskField 问题
【发布时间】:2019-09-12 23:30:19
【问题描述】:

我正在开发一种输入系统,该系统允许用户在不同输入设备和操作系统之间转换输入映射,并可能定义自己的映射。

我正在尝试为编辑器窗口创建一个 MaskField,用户可以在其中从 RuntimePlatforms 列表中进行选择,但选择单个值会导致选择多个值。

主要用于调试,我将其设置为生成它使用的等效枚举 RuntimePlatformFlags,而不是 RuntimePlatform:

[System.Flags]
public enum RuntimePlatformFlags: long
{
    OSXEditor=(0<<0),
    OSXPlayer=(0<<1),
    WindowsPlayer=(0<<2),
    OSXWebPlayer=(0<<3),
    OSXDashboardPlayer=(0<<4),
    WindowsWebPlayer=(0<<5),
    WindowsEditor=(0<<6),
    IPhonePlayer=(0<<7),
    PS3=(0<<8),
    XBOX360=(0<<9),
    Android=(0<<10),
    NaCl=(0<<11),
    LinuxPlayer=(0<<12),
    FlashPlayer=(0<<13),
    LinuxEditor=(0<<14),
    WebGLPlayer=(0<<15),
    WSAPlayerX86=(0<<16),
    MetroPlayerX86=(0<<17),
    MetroPlayerX64=(0<<18),
    WSAPlayerX64=(0<<19),
    MetroPlayerARM=(0<<20),
    WSAPlayerARM=(0<<21),
    WP8Player=(0<<22),
    BB10Player=(0<<23),
    BlackBerryPlayer=(0<<24),
    TizenPlayer=(0<<25),
    PSP2=(0<<26),
    PS4=(0<<27),
    PSM=(0<<28),
    XboxOne=(0<<29),
    SamsungTVPlayer=(0<<30),
    WiiU=(0<<31),
    tvOS=(0<<32),
    Switch=(0<<33),
    Lumin=(0<<34),
    BJM=(0<<35),
}

In this linked screenshot, only the first 4 options were selected. "Platforms:" 旁边的整数是掩码本身。

我不是一个很大的按位向导,但我的假设是发生这种情况是因为 EditorGUILayout.MaskField 返回一个 32 位 int 值,并且有超过 32 个枚举选项。是否有任何解决方法或其他原因导致此问题?

【问题讨论】:

    标签: unity3d enums bitmask unity-editor


    【解决方案1】:

    我注意到的第一件事是Enum 中的所有值都是相同的,因为您将 0 位向左移动。您可以通过使用此脚本记录您的值来观察这一点。

    // Shifts 0 bits to the left, printing "0" 36 times.
    for(int i = 0; i < 36; i++){
        Debug.Log(System.Convert.ToString((0 << i), 2));
    }
    
    // Shifts 1 bits to the left, printing values up to 2^35.
    for(int i = 0; i < 36; i++){
        Debug.Log(System.Convert.ToString((1 << i), 2));
    }
    

    long 继承的原因不能单独工作,是因为位移。查看this example我发现了这个问题:

    UInt32 x = ....;
    UInt32 y = ....;
    UInt64 result = (x << 32) + y;
    

    程序员打算通过将“x”移动 32 位并添加最高有效部分和最低有效部分来从两个 32 位值形成一个 64 位值。但是,由于在进行移位操作的那一刻,'x'是一个32位的值,所以移位32位就相当于移位了0位,会导致结果不正确。


    因此,您还应该转换移位位。像这样:

    public enum RuntimePlatformFlags : long {
        OSXEditor = (1 << 0),
        OSXPlayer = (1 << 1),
        WindowsPlayer = (1 << 2),
        OSXWebPlayer = (1 << 3),
    
        // With literals.
        tvOS = (1L << 32),
        Switch = (1L << 33),
    
        // Or with casts.
        Lumin = ((long)1 << 34),
        BJM = ((long)1 << 35),
    }
    

    【讨论】:

    • 另外仍然值 &gt; 32 可能是一个问题,但我也不是专家 ^^ 您可以尝试使用 long,如 in this answer 所述
    • 你完全正确。由于控制台中的消息折叠,我忽略了前 4 个值被打印了多少次。修复。谢谢。
    • 是的,现在它还解释了为什么在 OP 的屏幕截图中选择了最后 4 个项目!因为它们的值与前 4 个值相同,只是移动了32==0bist。
    • 非常感谢大家,问题解决了!也完全错过了枚举中的那个问题。以下是现在处理掩码的方式:c# int x = (int)(OSMask[i]); int y = (int)(OSMask[i]&gt;&gt;32); GUILayout.Label("Platforms: "); x = EditorGUILayout.MaskField(" (p.1)" + x.ToString(),x, OS32); y = EditorGUILayout.MaskField(" (p.2)" + y.ToString(),y, OS64); OSMask[i] = (((long)y &lt;&lt; 32) + (long)x); 存在一些边缘问题,多个下拉菜单卡顿,但它有效!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-24
    • 2013-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多