Open4

MemoryPackで○○をシリアライズする

EuglenachEuglenach

Texture2D

とりあえずPNGでエンコードする
生のバイナリならシリアライズ/デシリアライズは速いが、ファイルサイズはでかくなる
臨機応変に変えたい場合はクラスをそれぞれ継承してフォーマッターを作ると良きかな

EuglenachEuglenach

Ulid

Ulid は unmanagedな構造体なので何もしなくてもシリアライズできる

UlidSerializeTest.cs
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のメモリレイアウトは以下の通り

Ulid.cs
// 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には驚きのコメントが付いている。これはいつか変わるかも...?

Ulid.cs
namespace System // wa-o, System Namespace!?
{
EuglenachEuglenach

ObservableCollections関連

CysharpさんのObservableCollectionsのあれこれに対応する
https://github.com/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>());