MemoryPackで○○をシリアライズする
ReactiveProperty, ReactiveCollection, ReactiveDictionary
Texture2D
とりあえずPNGでエンコードする
生のバイナリならシリアライズ/デシリアライズは速いが、ファイルサイズはでかくなる
臨機応変に変えたい場合はクラスをそれぞれ継承してフォーマッターを作ると良きかな
Ulid
Ulid は unmanagedな構造体なので何もしなくてもシリアライズできる
var orig = Ulid.NewUlid();
var bin = MemoryPackSerializer.Serialize(orig);
var des = MemoryPackSerializer.Deserialize<Ulid>(bin);
Assert.That(orig == des, Is.True);
ただし、MemoryPackはunmanaged構造体の変更を許容できないので、もしUlidのメモリレイアウトが変更されたら変更前のバイナリからデシリアライズできなくなる。(まあ無いと思うけど...)
ver1.3.2
現在のUildのメモリレイアウトは以下の通り
// Timestamp(64bits)
[FieldOffset(0)] readonly byte timestamp0;
[FieldOffset(1)] readonly byte timestamp1;
[FieldOffset(2)] readonly byte timestamp2;
[FieldOffset(3)] readonly byte timestamp3;
[FieldOffset(4)] readonly byte timestamp4;
[FieldOffset(5)] readonly byte timestamp5;
// Randomness(80bits)
[FieldOffset(6)] readonly byte randomness0;
[FieldOffset(7)] readonly byte randomness1;
[FieldOffset(8)] readonly byte randomness2;
[FieldOffset(9)] readonly byte randomness3;
[FieldOffset(10)] readonly byte randomness4;
[FieldOffset(11)] readonly byte randomness5;
[FieldOffset(12)] readonly byte randomness6;
[FieldOffset(13)] readonly byte randomness7;
[FieldOffset(14)] readonly byte randomness8;
[FieldOffset(15)] readonly byte randomness9;
余談
UlidはSystem
名前空間上に定義されており、Ulid.csには驚きのコメントが付いている。これはいつか変わるかも...?
namespace System // wa-o, System Namespace!?
{
ObservableCollections関連
CysharpさんのObservableCollectionsのあれこれに対応する
IL2CPPの場合ジェネリック型は型引数が違う場合もそれぞれ列挙しなければいけないのでその形式に準拠するObservableList
MemoryPackFormatterProvider
に登録するだけ
MemoryPackFormatterProvider.RegisterCollection<ObservableList<int>, int>();
MemoryPackFormatterProvider.RegisterCollection<ObservableList<string>, string>();
ObservableDictionary
MemoryPackFormatterProvider
に登録するだけ
MemoryPackFormatterProvider.RegisterDictionary<ObservableDictionary<int, string>, int, string>();
MemoryPackFormatterProvider.RegisterDictionary<ObservableDictionary<string, string>, string, string>();
ObservableHashSet
シリアライズ時にUnsafe.As
を用いたハックを使っているので心配であれば配列にしてToArrayするのが良いと思う。ObservableHashSetの一番最初にHasSet<T>が宣言されていれば問題ないが、仕様変更等で今後メモリレイアウトが変われば挙動がおかしくなるので注意。
MemoryPackFormatterProvider
に登録
MemoryPackFormatterProvider.Register(new ObservableHashSetFormatter<int>());
MemoryPackFormatterProvider.Register(new ObservableHashSetFormatter<string>());
ObservableQueue
シリアライズ時にUnsafe.As
を用いたハックを使っているので心配であれば配列にしてToArrayするのが良いと思う。ObservableQueueの一番最初にQueue<T>が宣言されていれば問題ないが、仕様変更等で今後メモリレイアウトが変われば挙動がおかしくなるので注意。
MemoryPackFormatterProvider
に登録
MemoryPackFormatterProvider.Register(new ObservableQueueFormatter<int>());
MemoryPackFormatterProvider.Register(new ObservableQueueFormatter<string>());
ObservableStack
シリアライズ時にUnsafe.As
を用いたハックを使っているので心配であれば配列にしてToArrayするのが良いと思う。ObservableStackの一番最初にStack<T>が宣言されていれば問題ないが、仕様変更等で今後メモリレイアウトが変われば挙動がおかしくなるので注意。
MemoryPackFormatterProvider
に登録
MemoryPackFormatterProvider.Register(new ObservableStackFormatter<int>());
MemoryPackFormatterProvider.Register(new ObservableStackFormatter<string>());
ObservableRingBuffer
MemoryPackFormatterProvider
に登録するだけ
MemoryPackFormatterProvider.RegisterCollection<ObservableRingBuffer<int>, int>();
MemoryPackFormatterProvider.RegisterCollection<ObservableRingBuffer<string>, string>();
ObservableFixedSizeRingBuffer
コンストラクタの引数にCapacityを必ず渡す必要があり、MemoryPackFormatterProvider.RegisterCollection
をそのまま使えない。自前で定義する必要がある。
MemoryPackFormatterProvider
に登録
MemoryPackFormatterProvider.Register(new ObservableFixedSizeRingBufferFormatter<int>());
MemoryPackFormatterProvider.Register(new ObservableFixedSizeRingBufferFormatter<string>());