Slide 1

Slide 1 text

ʲ೥຤ͩΑʳUnity ͓ɾͱɾͳͷLTେձ 2024 2024/12/28 @yucchiy_ MasterMemory v3 最速確認会

Slide 2

Slide 2 text

• MasterMemoryについてのおさらい • MasterMemoryについて • MessagePackとの関係やコード生成について • MasterMemory v3の変更点の紹介 • Source Generator対応について • MasterMemory v3の利用方法の紹介 • 導入方法から簡単な使い方について このLTで話したいこと

Slide 3

Slide 3 text

自己紹介 向井 祐一郎 • 株式会社 サイバーエージェント / 株式会社アプリ ボ ット • Lead Developer Experience • システム系の基盤開発・プロジェクトの開発支援 SNS・個人活動など • @yucchiy_(X) • Unity Weekly • https://blog.yucchiy.com/tags/unity-weekly/ • UniTips(社内有志で技術書典に執筆)

Slide 4

Slide 4 text

MasterMemory のおさらい

Slide 5

Slide 5 text

• マスター デ ータの管理に主眼を置いたインメモリ デ ータベース • 省メモリ・高速なデータベースロード・高速な検索の3点に重点を置く • 弊社導入事例: Unity/C# ゲ ーム開発における、クライアントでのマスターデータの扱い方 • https://blog.applibot.co.jp/2024/01/19/unity-master-data/ • デ ータベースのフォーマットは MessagePack • データを読み込んで、メモリ上にデータベースを構築する • 書き出されたデータの読み込みでMessagePackのデータの解析に、 MessagePackのシリアライ ザ が必要になる MasterMemory とは https://github.com/Cysharp/MasterMemory

Slide 6

Slide 6 text

[MemoryTable("person"), MessagePackObject(true)] public record Person { [PrimaryKey] public int PersonId { get; set; } [SecondaryKey(0), NonUnique] [SecondaryKey(1, keyOrder: 1), NonUnique] public int Age { get; set; } [SecondaryKey(2), NonUnique] [SecondaryKey(1, keyOrder: 0), NonUnique] public Gender Gender { get; set; } public string Name { get; set; } } デ ータの定義 属性を用いて各カラムの “扱い” を定義

Slide 7

Slide 7 text

var db = new MemoryDatabase( File.ReadAllBytes( Path.Combine(Application.dataPath, "StreamingAssets", "database.bytes") ) ); Person person = db.PersonTable.FindByPersonId(3); RangeView persons = db.PersonTable.FindByGender(Gender.Male); デ ータベースの検索 データベースの読み込み (byte[] を引数に初期化) PrimaryKeyで検索 SecondaryKeyで範囲検索

Slide 8

Slide 8 text

internal sealed class PersonFormatter : MessagePack.Formatters.IMessagePackFormatter { public void Serialize( ref MessagePack.MessagePackWriter writer, Samples.Person value, MessagePack.MessagePackSerializerOptions options) { var formatterResolver = options.Resolver; writer.WriteMapHeader(4); writer.WriteRaw(GetSpan_PersonId()); // … } public Samples.Person Deserialize( ref MessagePack.MessagePackReader reader, MessagePack.MessagePackSerializerOptions options) { // … } } 独自型のシリアライ ズ のために、内部でフォーマッタが必要になる MessagePackのフォーマッタ [MemoryTable(“person”), MessagePackObject(true)] public record Person { [PrimaryKey] public int PersonId { get; init; } [SecondaryKey(0), NonUnique] [SecondaryKey(1, keyOrder: 1), NonUnique] public int Age { get; init; } [SecondaryKey(2), NonUnique] [SecondaryKey(1, keyOrder: 0), NonUnique] public Gender Gender { get; init; } public string Name { get; init; } }

Slide 9

Slide 9 text

MessagePackCompiler(mpc) • IL2CPP下のUnityではフォーマッタの事前生成が必要(AOT Code Generation) • mpcを用いて実行前にコード生成しておく // Simple Sample: dotnet mpc -i "..\src\Sandbox.Shared.csproj" -o "MessagePackGenerated.cs" // Use force map simulate DynamicContractlessObjectResolver dotnet mpc -i "..\src\Sandbox.Shared.csproj" -o "MessagePackGenerated.cs" -m dotnet tool install --global MessagePack.Generator

Slide 10

Slide 10 text

定義された デ ータを操作するためのロジックを生成するツール MasterMemory.Generator [MemoryTable("person"), MessagePackObject(true)] public record Person { [PrimaryKey] public int PersonId { get; set; } [SecondaryKey(0), NonUnique] [SecondaryKey(1, keyOrder: 1), NonUnique] public int Age { get; set; } [SecondaryKey(2), NonUnique] [SecondaryKey(1, keyOrder: 0), NonUnique] public Gender Gender { get; set; } public string Name { get; set; } } Person person = db.PersonTable.FindByPersonId(3); RangeView persons = db.PersonTable.FindByGender(Gender.Male); MasterMemory.Generator.exe -i “C:\UnitySample” -o “C:\UnitySample\Generated" -n "UnitySample"

Slide 11

Slide 11 text

MasterMemory v3の変更点

Slide 12

Slide 12 text

前提: MessagePack v3の ア ップ デ ートについて • v3(v3.0.3)にて、フォーマッタの事前生成がSource Generator化された • プロジェクトコードのコンパイル時にフォーマッタが自動生成される • 上記の対応に伴い、mpcが不要になった https://github.com/MessagePack-CSharp/MessagePack-CSharp/releases/tag/v3.0.3

Slide 13

Slide 13 text

• MessagePack v3が取り込まれた • これによりMessagePackのSource Generator対応が取り込まれた • あわせて、MasterMemory.GeneratorがSource Generator化された • MasterMemoryのコード生成に関する実装が、すべてSource Generator化された MasterMemory v3の ア ップ デ ート https://neue.cc/2024/12/20_mastermemory_v3.html

Slide 14

Slide 14 text

MasterMemory v3の導入方法

Slide 15

Slide 15 text

NuGet For Unityで「MasterMemory」をインストールする( だ け!) インストール

Slide 16

Slide 16 text

“Override References” をONにし、”Assembly References”にDLLを設定 asmdef を切る場合の設定

Slide 17

Slide 17 text

各アセン ブ リごとに「MasterMemoryGeneratorOptions」を設定する デ ータベースの設定 using MasterMemory; [assembly: MasterMemoryGeneratorOptions( Namespace = "Samples", IsReturnNullIfKeyNotFound = false, PrefixClassName = "Hoge" )] namespace System.Runtime.CompilerServices { internal sealed class IsExternalInit { } } v2以前ではコマンドラインのオプションで指定していた箇所 Initプロパティを利用したい場合は定義

Slide 18

Slide 18 text

MasterMemory v3の使い方

Slide 19

Slide 19 text

[MemoryTable("person"), MessagePackObject(true)] public record Person { [PrimaryKey] public int PersonId { get; init; } [SecondaryKey(0), NonUnique] [SecondaryKey(1, keyOrder: 1), NonUnique] public int Age { get; init; } [SecondaryKey(2), NonUnique] [SecondaryKey(1, keyOrder: 0), NonUnique] public Gender Gender { get; init; } public string Name { get; init; } } v2以前と比べ、利用方法に変更はない デ ータの定義

Slide 20

Slide 20 text

var builder = new DatabaseBuilder(); builder.Append(new Person[] { new() { PersonId = 1, Age = 20, Gender = Gender.Male, Name = "John" }, new() { PersonId = 2, Age = 22, Gender = Gender.Female, Name = "Jane" }, new() { PersonId = 3, Age = 24, Gender = Gender.Male, Name = "Jack" }, }); File.WriteAllBytes( Path.Combine(Application.dataPath, "StreamingAssets", "database.bytes"), builder.Build() ); v2以前と比べ、利用方法に変更はない デ ータベースの書き出し ゲ ームごとに管理されている マスターデータを読み込んで データベースファイルとして書き出す

Slide 21

Slide 21 text

var db = new MemoryDatabase( File.ReadAllBytes( Path.Combine(Application.dataPath, "StreamingAssets", "database.bytes") ) ); Person person = db.PersonTable.FindByPersonId(3); RangeView persons = db.PersonTable.FindByGender(Gender.Male); v2以前と比べ、利用方法に変更はない デ ータベースの検索

Slide 22

Slide 22 text

Unity 6で再現する、Unity側のバ グ とのこと 余談: コンパイル時のエラー https://x.com/neuecc/status/1870994368020296171

Slide 23

Slide 23 text

• MasterMemory v3の、Source Generator対応に焦点を当てて紹介しました • Source Generator対応により、導入からコード生成の手間が大幅に省けた • これによって開発体験が大きく向上した • MasterMemory v2からv3について利用方法の大きな変更はない • 下回り(Source Generator対応)がメインになる • 移行コストは低そう(Unityバージョンの要求は高いので、運用タイトルからの移行はチョット高い) まとめ → MasterMemory v3、積極的に使っていきたい