概要
Unity で Photon を使ったゲームを作る際、Vector3 や Quaternion を手間なくビットパッキングできるクラスが欲しくなったので作りました。
不具合や改善点がありましたら、コメントしていただけると幸いです。
コード
クラス紹介
BitPacking.Vec3ToLong
Vec3ToLong はVector3をlongに非可逆圧縮・展開できるクラスです。他に Vec3ToInt, Vec2ToInt, Vec2ToShort を用意しています。
// 最小単位, 中央座標, ループ, X座標に使うビット数, Y座標に使うビット数、Z座標に使うビット数を指定できる
// (符号付きの値を利用する際は、値をマイナスにする)
var posPacker = new BitPacking.Vec3ToLong(0.01f, Vector3.zero, false, -22, -20, -22);
// 圧縮
long data = posPacker.Build(transform.position);
// 展開
transform.position = posPacker.Expand(data);
ループを無効にした場合、オーバーフローを抑制します(マップの端より先に移動できなくなります)。
ループを有効にした場合、オーバーフローを許容します(マップの右端まで行くとマップの左端にワープする挙動になります)。
BitPackingQuaternion
BitPackingQuaternion は、QuaternionのEulerAnglesをintやlongに非可逆圧縮・展開できる拡張メソッド等を定義したクラスです。
方向の情報のみを圧縮・展開できる拡張メソッドも用意しています。
//EulerAnglesをlongに圧縮する拡張メソッド。角度は 0.0005f 刻みになる
long data1 = transform.rotation.PackingToLong();
transform.rotation = data1.ExpandToQuaternion();
//EulerAnglesをintに圧縮する拡張メソッド。角度は 0.5f 刻みになる
int data2 = transform.rotation.PackingToInt();
transform.rotation = data2.ExpandToQuaternion();
// EulerAnglesの一つをshortに圧縮する拡張メソッド。角度は 0.01f 刻みになる
short data3 = transform.rotation.eulerAngles.y.AnglePackingToShort();
transform.rotation = data3.ExpandToQuaternion(Vector3.up);
/* 方向の情報のみを圧縮・展開できる拡張メソッド */
//EulerAnglesのX,Yをintに圧縮する拡張メソッド。角度は 0.01f 刻みになる
int data4 = transform.forward.DirectionPackingToInt();
transform.forward = data4.ExpandToDirection();
//EulerAnglesのX,Yをlongに圧縮する拡張メソッド。変換で僅かな誤差が生まれるものの高精度
long data5 = transform.forward.DirectionPackingToLong();
transform.forward = data5.ExpandToDirection();
BitPackingJoyStick
BitPackingJoyStick は、JoyStick等で扱われるVector2をushortにビットパッキングできる拡張メソッドを定義したクラスです。
ushort data = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")).JoyStickPackingToUshort();
Debug.Log(data.ExpandToJoyStick());
BitPackingColor
BitPackingColor は、Color, Color32をintにビットパッキングできる拡張メソッドを定義したクラスです。
int data = Color.yellow.PackingToInt();
Debug.Log(data.ExpandToColor());
BitPacking
BitPacking クラスには、long, int, short, byte に複数の値を組み込める関数を用意しています。
// 各値をパッキングする際、必要になるビット数を指定する配列を用意する
// (符号付きの値を利用する際は、値をマイナスにする)
private static readonly int[] PlayerInfoBits = { 2, 20, -10 };
// int data に3つの値をパッキング
int data = BitPacking.BuildInt(PlayerInfoBits, 3, 65535, -512);
// パッキングした値を array に展開
int[] array = BitPacking.Expand(PlayerInfoBits, data);
32ビット以上の値をパッキングする際はBuildLong(int[] bits, params long[] values)
とExpandToLongs(int[] bits, long packedData)
関数を利用してください。
必要になるバイト数は2^n
で求まりますが、BitPacking.MinValue(int bit)
とBitPacking.MaxValue(int bit)
関数で求める事もできます。またオーバーフローさせたくない場合はBitPacking.Clamp(long value, int bit)
関数で抑制できます。