CodeGeneratorをMacで使えるようにする。MessagePack for C# [Unity]


環境

MacでCodeGeneratorが使えない。。。

Windows -> MessagePack -> CodeGenerator

MacではCodeGeneratorが上記画面から進みません。
それを解決します。

今回の方法は複数人での開発に向きません。
複数人で開発する場合はCodeGeneratorの担当者を一人決める必要があります。他に方法が見つかるか、またはOfficialで修正があればこの記事を書き直します。

基礎知識

AOT Code Generationとは?

MessagePack for C#をIL2CPP上で動作されるには中間コードが必要になります。それを出力するのがAOT Code Generationです。iOS/AndroidアプリをリリースするにはIL2CPPで出力する必要があるので必須となります。

CodeGeneratorとは?

Unity上から「Generate」ボタンをクリックするだけで中間コードを出力してくれる便利機能です。

必要なアプリがインストール済みかチェックする

ターミナルを開き、下記手順で進めます。

1 .NET Core 3 Runtime

dotnet --version

ターミナルに上記を入力しEnterを押すと3.1.102などのバージョンが表示されます。表示されなければ未インストールなのでのインストールしてください。

.NET Core 3 Runtimのダウンロード

2 MessagePackCompiler(mpc)

dotnet tool list -g

messagePack.generatorが未インストールであればターミナルで下記を実行しインストールしてください。messagePack.generatorの文言が表示されなければ未インストールです。

dotnet tool install --global messagePack.generator

必要なアプリのパスを取得

1 .NET Core 3 Runtime

type dotnet

ターミナルに上記を入力しEnterを押すとdotnet is hashed (/usr/local/share/dotnet/dotnet)の形で出力されます。()内のパスを後ほど使用します。

2 MessagePackCompiler(mpc)

type dotnet-mpc

同様に()内のパスを後ほど使用します。

コードを一部書き換える

書き換えてしまうのでWindowsで動作しなくなります。もしWindowsでも使う予定があればディレクティブなど使って工夫してください。違うMacでもパスが代わるので対応が必要になります。

1 Assets/Scripts/MessagePack/Unity/MessagePackWindow.csを開きます。
2 InvokeProcessStartAsyncの第一引数dotnetをすべて上記で取得したパスに修正します。例)

var list = await InvokeProcessStartAsync("/usr/local/share/dotnet/dotnet", "tool list -g");

3 153行目 ProcessHelper.InvokeProcessStartAsyncの第一引数dotnet-mpcを上記で取得したパスに修正します。例)

var log = await ProcessHelper.InvokeProcessStartAsync("/Users/account/.dotnet/tools/dotnet-mpc", "mpc " + commnadLineArguments);

以上です!
CodeGeneratorを開くと下記のような画面が表示されれば成功です。
もし表示されなければひとつずつ見直してみてください。

CodeGeneratorの設定

Windows -> MessagePack -> CodeGenerator

[セーブデータが含まれるcsprojの場所]

-i input path(csproj or directory):

../Assembly-CSharp.csproj

Assembly Definitionを利用していて、Auto ReferencedをOffにしている方は正しいcsprojを指定してください。

[中間コード出力先]

-o output filepath(.cs) or directory(multiple):

Scripts/MessagePackGenerated

拡張子.csを追加するとひとつのファイルにすべての中間コードをまとめてくれます(多分)。
逆に下記のように.csを含めなければクラス別に出力+その出力されたクラスを参照するファイルが出力されます。

中間コードの生成

「Generate」ボタンを押すことで生成されます。
※生成されたコードが表示されない場合は、Unity Editor以外の画面をクリック -> Unity Editorに戻ることで表示されます。

実装

最後に生成したGeneratedResolver.Instanceを登録して使えるようにして完了です。
必ず初めに初期化される必要があるようです。リファレンスでは、RuntimeInitializeOnLoadMethodを使って初期化してますが、プラグインの利用があってもなくても初期化が走るので、セーブデータにアクセスする前に初期化を済ませられればどのような実装でも良いと思います。

コードの参照元 : AOT Code Generation

using MessagePack;
using MessagePack.Resolvers;
using UnityEngine;

public class Startup
{
    static bool serializerRegistered = false;

    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    static void Initialize()
    {
        if (!serializerRegistered)
        {
            StaticCompositeResolver.Instance.Register(
                 MessagePack.Resolvers.GeneratedResolver.Instance,
                 MessagePack.Resolvers.StandardResolver.Instance
            );

            var option = MessagePackSerializerOptions.Standard.WithResolver(StaticCompositeResolver.Instance);

            MessagePackSerializer.DefaultOptions = option;
            serializerRegistered = true;
        }
    }

#if UNITY_EDITOR


    [UnityEditor.InitializeOnLoadMethod]
    static void EditorInitialize()
    {
        Initialize();
    }

#endif
}

最後に

MessagePack for C#いいですよね!
製作者のCysharp, Inc. CEO/CTOの河合 宜文さんに日々感謝です。
いつかお逢いしたいものです。
多分緊張しすぎてしゃべれないと思いますが