Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

How would I convert an array of bools into a byte and vice versa? C#

Discussion in 'Scripting' started by Sayuri_Artsy, Sep 25, 2018.

  1. Sayuri_Artsy

    Sayuri_Artsy

    Joined:
    Aug 12, 2018
    Posts:
    9
    Hello is there a way to express 8 booleans as a byte. I wanted to have a system when the game would keep track of the players input (wasd and the arrow keys) and figure out what combination of the buttons are pressed as a byte.

    My idea was to make a replay system that would record the players input as a string of characters representing the bytes and then save it as txt file. Then later the game could open up that txt and recreate the player's inputs.
     
  2. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,204
    Crash course in flags: to set the values for a byte, you use binary operators. So you could have something like:

    Code (csharp):
    1. byte inputs = 0;
    2. if (Input.GetKeyDown(KeyCode.W))
    3.     inputs |= 1 << 0;
    4. if (Input.GetKeyDown(KeyCode.A))
    5.     inputs |= 1 << 1;
    6. if (Input.GetKeyDown(KeyCode.S))
    7.     inputs |= 1 << 2;
    8. if (Input.GetKeyDown(KeyCode.D))
    9.     inputs |= 1 << 3;
    10.  
    11. //check if D is down:
    12. if ((inputs & 1 << 3) != 0) {
    13.     print("left is down!");
    14. }
    15.  
    If you have this already encoded in a bool[], you just do:

    Code (csharp):
    1. for (int i = 0; i < 8; i ++) {
    2.     if(myBools[i])
    3.         inputs |= 1 << i;
    4. }
    A better way to do the same thing is to use a byte-encoded enum, so you don't have to remember what the values are:

    Code (csharp):
    1. [Flags]
    2. public enum InputFlags : byte {
    3.     Forward     = 1 << 0,
    4.     Left        = 1 << 1,
    5.     Back        = 1 << 2,
    6.     Right       = 1 << 3,
    7.     Forward_alt = 1 << 4,
    8.     Left_alt    = 1 << 5,
    9.     Back_alt    = 1 << 6,
    10.     Right_alt   = 1 << 7,
    11. }
    This turns the above code into:

    Code (csharp):
    1. InputFlags inputs = 0;
    2. if (Input.GetKeyDown(KeyCode.W))
    3.     inputs |= InputFlags.Forward;
    4. if (Input.GetKeyDown(KeyCode.A))
    5.     inputs |= InputFlags.Left;
    6. if (Input.GetKeyDown(KeyCode.S))
    7.     inputs |= InputFlags.Back;
    8. if (Input.GetKeyDown(KeyCode.D))
    9.     inputs |= InputFlags.Right;
    10.  
    11. // if you need it as a byte, you can just cast it:
    12. byte inputBytes = (byte) inputs;

    If you're on the latest Unity version, or have set the modern .NET runtime in the player settings, you could use this syntax for the flags instead, which I find helps keep track of different kings of flags a bit better:

    Code (csharp):
    1. [Flags]
    2. public enum InputFlags : byte {
    3.     Forward     = 0b00000001,
    4.     Left        = 0b00000010,
    5.     Back        = 0b00000100,
    6.     Right       = 0b00001000,
    7.     Forward_alt = 0b00010000,
    8.     Left_alt    = 0b00100000,
    9.     Back_alt    = 0b01000000,
    10.     Right_alt   = 0b10000000,
    11. }
    Final note, There's no actual reason to use a byte for this unless you're packing a bunch of them together for serialization, or as a struct member. Unity also can't automatically serialize an enum that's anything else than int-encoded (which is the default)
     
    lordofduct likes this.
  3. Sayuri_Artsy

    Sayuri_Artsy

    Joined:
    Aug 12, 2018
    Posts:
    9
    Thank you for your detailed responce, very helpful.

    One thing that I can't seem to get to work is this though:
    Code (csharp):
    1. for (int i = 0; i < 8; i ++) {
    2.     if(myBools[i])
    3.         inputs |= 1 << i;
    4. }
    Seems that the 'i' isn't liked, even if I do something like change it from int i to byte i, it gives me this error:
    error CS0266: Cannot implicitly convert type `int' to `byte'. An explicit conversion exists (are you missing a cast?)

    I feel like I understand what the idea of what it's intended to do, but I am stumped as to how to get this bit of it to actually perform properly.
     
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,204
    Yup, my bad.

    For some reason, the << operator always returns an int, and there's no implicit conversion from int to byte, so you have to cast to byte:

    Code (csharp):
    1. inputs |= (byte) (1 << i)
     
  5. Sayuri_Artsy

    Sayuri_Artsy

    Joined:
    Aug 12, 2018
    Posts:
    9
    Thank you that seems to work!