Edited at

MasterMemoryとAirtableでいい感じにマスタを高速に読む


事の発端

きゅぶんずさんがいい感じの記事を書いてるのを見て、Airtableに興味を持ち、いろいろ調べていたらMasterMemoryなるものが出たので、全部一緒に料理してやんよ見たいな感じでUnityでいい感じに使おうと思った記録です。


とりあえず参考までに

きゅぶんずさんの記事

https://qiita.com/kyubuns/items/dc47cf7c9af38f13c9ee

Airtable

https://airtable.com/

Airtableの.NETクライアント

https://github.com/ngocnicholas/airtable.net

↑がJson.NET使ってたので、Utf8Json用に私が作ったもの

https://github.com/yKimisaki/AirtableClient

Utf8Json

https://github.com/neuecc/Utf8Json

起動のたびにAirtableにアクセスすると遅いので、手元にそのデータをバイナリでキャッシュしておく。

そのキャッシュを作ったり、バイナリからテーブルにしてくれる良い物がMasterTable。

https://github.com/Cysharp/MasterMemory


作戦

image.png

↑のようなテーブルを


MasterCache.cs

var appleMaster = MasterCache.TestMaster.FindByID(1);


みたいな形でUnity上から使えるようにする。


TestMasterクラスの作成

自動生成したいけど、いろいろ面倒くさい経験しかないので頑張って書きます。


TestMaster.cs

[MessagePackObject(true)]

[MemoryTable(nameof(MainGameMaster))]
public class TestMaster
{
[PrimaryKey]
public int ID { get; set; }

public string Name { get; set; }

public int Price { get; set; }
}


注意点としては、PrimaryKey属性がフィールドじゃなくプロパティにしか付けられないので{ get; set; }なりが必須、またUnity用のmpc.exe(MessagePackのリゾルバ生成)はTestMasterのリゾルバは生成してもTestMaster[]、つまりカスタムクラスの配列は自動で生成してくれないので、作っておかないと怒られます。以下で生成されるMasterMemoryResolverを登録しましょう!!!


UnityEditorで必要なものをいい感じに生成する

https://gist.github.com/yKimisaki/9ecc52c87cd7e926423a506bab519de1

image.png

みたいなのを作ってメニューからMessagePackのリゾルバやらAssetBundleやらをそれっぽく生成できるようにしておきます。

できたらMasterMemoryのTablesを生成します。

普通にMasterMemory.Generator.exe自分でたたいてくれてもいいです。


AirTableやバイナリからMasterMemoryに読み込む

https://gist.github.com/yKimisaki/5a3bc7317e4193c38651b8f8ebff1771

みたいな感じで、複数の経路、具体的にはキャッシュのバイナリか、Airtableから直接MasterCacheみたいなメモリ上に展開するクラスに登録できる状態を作っておきましょう。


Airtableからバイナリを作成

あとは、だいぶ前のBuilder.csあたりに

[MenuItem("Build/MasterMemory/Binaries")]

public static void BuildBinaries()
{
var binary = ScriptableObject.CreateInstance<BinaryObject>();

Task.Run(async () =>
{
binary.Value = await new AirtableMasterLoader().LoadAsync();
}).Wait();

AssetDatabase.CreateAsset(binary, ClientMasterLoader.BinaryAssetPath);
AssetDatabase.Refresh();

Debug.Log($"Build completed. Binary is created on {ClientMasterLoader.BinaryAssetPath}");
}

を追加して実行すると、指定の場所にバイナリを内包したScriptableObjectが生成されます。

image.png


仕上げ

あとはそのバイナリをAssetBundleにしておきましょう。

await MasterCache.RegisterAsync(new ClientMasterLoader());

で、読み込んであげれば、


MasterCache.cs

var appleMaster = MasterCache.TestMaster.FindByID(1);


これが達成できます。


まとめ

雑くてスミマセンが、アプリの起動時間=ログインのしやすさ関わってくる部分だと思っているので、できるだけマスタなどはクライアントにキャッシュしておくことをお勧めします。

で、更新があれば都度AssetBundleなどを経由してDLしてもらうのが、いいと思います。