Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Bug EnumFlagsField enum equals -1 when everything is selected

Discussion in 'Scripting' started by BasicallyGames, Oct 20, 2021.

  1. BasicallyGames

    BasicallyGames

    Joined:
    Aug 31, 2018
    Posts:
    91
    I am currently using Unity 2020.3.20f1. I'm having an issue where an enum I've created, which can store multiple values, and is set using an EnumFlagsField, returns -1 when all items are selected, instead of the maximum value like it used to in earlier versions of Unity.

    Here is the enum:
    Code (CSharp):
    1. public enum ManualEditorDirection { None = 0, North = 1 << 0, East = 1 << 1, South = 1 << 2, West = 1 << 3}
    I used to have no issues using this. I would set the values in the inspector and it would always return a value between 0 and 15. Now however, when all values are selected, it returns -1. I've made a hacky workaround (Setting the value to 15 if it is less than 0) for now, but this definitely doesn't seem correct.

    To recreate the issue, create a new project, create a class with the enum above, create an editor script for that class that allows you to set it using the EnumFlagsField, and then use a Debug.Log to send "(int)enumName" to the console. You'll see that for any combination of values it will return the correct total, but if you select them all it will be -1.
     
    Last edited: Oct 20, 2021
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,517
    -1 is actually two's complement for all bits set in a given integer field:

    https://en.wikipedia.org/wiki/Two's_complement

    Now you only have four bits in that enum, and AFAIK enums are supposed to be System.Int32s, but it seems it might be sign-extending out??

    This might be a result of a change in .NET level, or a bug in the C#.

    Might even just be a Unity editor thing, if that's the source of this data.

    Since you only care about the 4 least significant bits, you can always work around this by logical-anding it with 15, which is all four bits on.
     
    Bunny83 likes this.
  3. johanolofsson

    johanolofsson

    Joined:
    Nov 21, 2018
    Posts:
    94
    I ran into this issue too.

    I'm trying to cache various stuff in arrays where each combination of the enum flags numerically determines the index.

    cachedStuff[(int)enumValue] = ...

    so obv. -1 is not a good result.

    ofc. the solution suggested by Kurt-Dekker is certainly fast enough executionwise (compared to the if) but it is nevertheless annoying to have to patch like that all the time.

    This seems like a bug in the editor where they assume -1 (i.e. all bits) are valid when selecting "Everything".

    Should be pretty easy to sum up the values of all the existing flags.

    Did you ever report a bug on this?
     
  4. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,913
    I know what you're saying, however at no point has a bitmask be limited to just the values that may be defined in the enum. The MaskField deliberately sets the value to -1 (or 0xFFFFFFFF when unsigned) when everything is selected.

    Well, yes, kind of. But you must not sum them up but combine them with a bitwise or.

    Note in the past there was no enum bit field support at all. We had to use the MaskField. However it didn't care, hasn't support for the actual bit value of an item. So it assumes an increasing bit index for each item. I've written a wrapper back then which did support all combinations of the enum values and would handle mixed values as well. Even back then selecting "everything" means it returns -1. However you can add an "ALL" value to your enum at the end to cover that case. My field actually iterates through all values and reconstructs the actual value each time. Back then there was no other way.

    Yes, the behaviour of the EnumFlagsField's everything is a bit strange. It even returns -1 when you turn on your bits one by one. Once all are selected it jumps to -1 ^^. The issue with this is, there are probably some Unity internal UI stuf that may rely on this behaviour, so changing the behaviour would be quite difficult. So it's unlikely that this would happen.
     
    johanolofsson likes this.
  5. johanolofsson

    johanolofsson

    Joined:
    Nov 21, 2018
    Posts:
    94
    Yeah, well regardless of the source being enums or otherwise it would be preferable to not get -1 when selecting Everything.


    Actuallly for flags, which is obv the case here, the result is the same ^^

    Yes I actually have an 'All' option which is the combination of all flags available. I guess a workaround would be if the 'Everything' options could be opted out and that it did not go for -1 when manually selecting all options.
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,517
    .. until someone in the future changes your enum values... for instance today there might be:

    Code (csharp):
    1. PlatformiOS = 0x002,
    2. PlatformiPhone = 0x400,   // special hack for Metal bug in iOS 12

    and then someone decides, "The Metal bug is fixed, we are done with distinguishing those" and changes them both to
    0x002


    Your code that was summing them together would fail in VERY mysterious ways.

    Your code that was logical-OR-ing them together would continue without a hiccup.

    If I had to guess that's just belt-and-suspenders defensive coding in the bitfield selection pulldown code. If I thought about it, I might do it too...
     
    Bunny83 likes this.
  7. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,913
    Exactly :) Or the enum contains "grouping" members. One C# default enum I came across again recently is NumberStyles. Any, Currency, Float, HexNumber, Integer and Number are all compound entries.