Skip to main content

Bit Count From Range

The bit count of Integer based fields can be set using BitCountFromRangeAttribute It will use the given range to calculate the required bit count. This works in a similar way to BitCount

The min value is subtracted from the value before it is written and added back after it is read. This will shift all written values into the positive range for writing so that the sign bit is not lost.

This will truncate the bits so that only the small bits are sent. There is no range checking for values using BitCount, so the value that is too big or too small will not be unpacked correctly.

Bit Count is calculated using bitCount = 1 + Floor(Log2(max - min)), so min = -100, max = 100 results in bit count = 8

Values are written using Write(value - min, bitCount) and read using value = Read(bitCount) + min

Use cases

  • A Value with a minimum and maximum value

Supported Types

  • Byte
  • Short
  • UShort
  • Int
  • Uint
  • Long
  • ULong
  • Enum

Example 1

A modifier that can add to a character value to increase or decrease it

public class MyNetworkBehaviour : NetworkBehaviour 
{
[SyncVar, BitCountFromRange(-100, 100)]
public int modifier;
}

Range = 200 so bit count is 8, causing the real range to be -100 to 155

modifier = 57 will serialize to 1001_1101

modifier = -57 will serialize to 0010_1011

modifier = -110 (out of range) will serialize to 1111_0110

modifier = 130 will serialize to 1110_0110, even tho 130 is out of range there is enough range because bit count rounds up.

modifier = 170 (out of range) will serialize to 0000_1110

Example 2

A Direction enum to say which way a model is facing

public enum MyDirection
{
Backwards = -1,
None = 0,
Forwards = 1,
}
public class MyNetworkBehaviour : NetworkBehaviour
{
[SyncVar, BitCount(-1, 1)]
public MyDirection direction;
}

Range = 3 so bit count is 2, causing the real range to be -1 to 2

direction = -1 will serialize to 00

direction = 1 will serialize to 10

Generated Code

Source:

[SyncVar, BitCountFromRange(-100, 100)]
public int myValue;

Generated:

public override bool SerializeSyncVars(NetworkWriter writer, bool initialState)
{
ulong syncVarDirtyBits = base.SyncVarDirtyBits;
bool result = base.SerializeSyncVars(writer, initialize);

if (initialState)
{
writer.Write((ulong)(this.myValue - (-100)), 8);
return true;
}

writer.Write(syncVarDirtyBits, 1);
if ((syncVarDirtyBits & 1UL) != 0UL)
{
writer.Write((ulong)(this.myValue - (-100)), 8);
result = true;
}

return result;
}

public override void DeserializeSyncVars(NetworkReader reader, bool initialState)
{
base.DeserializeSyncVars(reader, initialState);

if (initialState)
{
this.myValue = reader.Read(8) + (-100);
return;
}

ulong dirtyMask = reader.Read(1);
if ((dirtyMask & 1UL) != 0UL)
{
this.myValue = reader.Read(8) + (-100);
}
}

last updated for Mirage v101.8.0