-4

Unity3d PlayerPrefs only allow saving certain types - string, float, and int32. Since int is composed of 32 bits, it should be able to store 32 flags or a bool[] of length 32.

So far, I've thought about setting the int based on a binary number of 32 digits, where each digit represents a flag. I'm having trouble doing this with consideration of negative numbers.

Is there a way to access each individual bit of the int without recursive math to store and use them as flags?

JPtheK9
  • 199

3 Answers3

3

Yes, there is a Flags attribute that lets you use enums as flags for an int, and the type has methods to help identify if a flag is set and the such.

Telastyn
  • 110,259
1

Expanding on @Telastyn's answer, you can declare your flags as an enum with the Flags attribute instead of using an array of booleans:

[Flags]
public enum Options : uint {
    Empty = 0,
    FancyClouds = 1,
    EnhancedGrassTextures = 2,
    HiDefNoses = 4,
    NoPantsMode = 8,
    // etc. values are increasing powers of 2 up to 2^31
}

You can fiddle with the flags using bitwise operators:

Options flags = Options.HiDefNoses | Options.FancyClouds;
flags &= ~Options.HiDefNoses;               // remove an option
if ((flags & Options.HiDefNoses) != 0) {    // test an option
if (flags.HasFlag(Options.HiDefNoses)) {    // same thing, nicer(?) syntax

And the enum value can be (explicitly) cast to and from Int32:

int i = (int)flags;
Options o = (Options)i;     // round-tripped to int and back
0

Here is what I came up with:

The Flags attribute way consisted of several tricky pitfalls. For example, bit shifts on signed ints are arithmetic so the sign bit can't be easily used. Also, reconstructing the array of flags from a bitmask can get really mess, as blorgbeard mentioned.

Instead, I used the System.BitArray class which which is easily accessible with indexes. BitArray allows for easy serialization and deserialization to and from an int. BitArray offers a CopyTo() method to copy its bits to a byte array which can then be converted to an int with BitConverter.ToInt32(). To reconstruct the BitArray, a constructor can be used that takes a byte array generated from BitConverter.GetBytes().

I.e.

//Serializing 32 flags into int
BitArray bitArray = new BitArray (32);
byte[] byteBuffer = new byte[4];
bitArray.Copyto (byteBuffer, 0);
int SerializedFlags = BitConverter.ToInt32 (byteBuffer, 0);

//Reconstructing 32 flags from int
byteBuffer = BitConverter.GetBytes(SerializedFlags);
bitArray = new BitArray (byteBuffer);
JPtheK9
  • 199