ちゃこブログ

お絵かきとUnityとBlenderと日記

【Unity】【C#】MessagePackCSharpのコードジェネレーターのエラー回避方法について

※作業環境:Windows10、VisualStudio2017/2019、Unity2018.3.14f

GitHub - neuecc/MessagePack-CSharp: Extremely Fast MessagePack Serializer for C#(.NET, .NET Core, Unity, Xamarin). / msgpack.org[C#]

V1.7.3.6のCodeGeneratorのエラー

 MessagePackCSharpを利用する際、AndroidiOSでIL2CPPでビルドした場合にはCodeGeneratorを利用してコードを生成しないと実機で動きません。私は現在最新のreleaseバージョンであるVer1.7.3.6を利用しているのですが、このバージョンでは以下の謎のエラーが高頻度で発生します。

System.InvalidOperationException: Mismatched target events

f:id:charcotte:20190512131423p:plain
f:id:charcotte:20190512131432p:plain
 不思議なことに、プロセスを何回も繰り返していると数回に1回コードの生成に成功するので、脳死で何度も何度もプロセスを繰り返して10分以内に成功するといいな~という非常に頭の悪すぎる方法でエラーに対処していました。ところが、プロジェクトが大きくなるにつれて成功確率が低くなり、とうとうできなくなってしまいました。これでは非常に困るのでどうにかエラーを解決する方法がないかを探ってみました。
※なぜかはわからんですが、ソリューションが複雑になればなるほど生成が難しくなるみたいで、ごく単純なプロジェクトであれば失敗することはほぼないです。

このエラーに言及しているIssueを見つけました。
github.com
こちらのスレッドを見ても私には詳しいことはよくわかりませんでしたが、どうやらパスの問題みたいです。(でもなんでビルドを繰り返していると成功するんだろう・・・?)
 そして、このエラーに対応してくれているブランチが公開されています。
github.com
gitにコミットされているのはコードのみなので、このブランチを自分でビルドしてコードジェネレーターを生成する必要があります。VisualStudio全然わからないマンには非常につらかったですが、なんとか生成できたので記事に手順を記します。
※ちなみに本家にもこのエラーに対応しているブランチがあるのですが、こちらではなぜかmpc.exeが従来のエラーで動きませんでした。
github.com

新しいCodeGeneratorを取得する

コードジェネレーターの生成

 新しいmpc.exeをゲットするために、このブランチのソースコードをダウンロードします。
github.com
f:id:charcotte:20190512131853p:plain

global.json

 まず最初にやっておくことは、.NET Core SDKの確認です。ルートフォルダにあるglobal.jsonに書いてあるバージョンの.NET Core SDKがないとソリューションを読み込むことができません。
f:id:charcotte:20190512131947p:plain
今回で言うとバージョン2.1.500が指定されているのでない場合はインストールします。

Directory.Build.props

 次にルートフォルダにあるDirectory.Build.propsを編集します。以下のプロパティを削除します。

<ItemGroup>
    <PackageReference Include="Nerdbank.GitVersioning" Version="2.2.33" PrivateAssets="all" />
    <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0-beta-63127-02" PrivateAssets="All" />
</ItemGroup>

f:id:charcotte:20190512132133p:plain
普通にビルドすると以下のようにMicrosoft.Build.Tasks.Git.targetsのエラーがたくさんでるのですが、設定方法がよくわからなかったので、このパッケージを利用しないように設定することで回避しました。
f:id:charcotte:20190512132208p:plain

TypeCollector.cs

 TypeCollector.csの248行目の例外処理を削除します。
f:id:charcotte:20190512132319p:plain
なぜかは分かりませんが、この行があるとmpc.exeで毎回エラーが発生してコード生成が出来なくなります。しょうがないのでTypeCollector.csの該当箇所を削除することでエラーを回避しました。かなり良くない対処法だと思いますが、他に解決法が見つからなかったので…(´・ω・`)
f:id:charcotte:20190512132419p:plain

 ここでソリューションを開き、ビルドしてみます。ビルドに成功すれば新しいコードジェネレーターの生成の準備は完了です。

publish.bat

 MessagePack.UniversalCodeGenerator.csprojと同じディレクトリに入っているpublish.batを実行します。
f:id:charcotte:20190512132613p:plain
実行すると、同じディレクトリのbinフォルダ内に新しいコードジェネレーターが生成されます。新しいコードジェネレーターを使って、UnityのMessagePackObjectのコードを生成してみましょう。
※ここで謎のエラーが出る場合はglobal.jsonSDKのバージョンを変更すると成功するかもしれません。

コードジェネレーターを使う

 どうやらV1.7.3.6と仕様が異なっているみたいで、コードジェネレーターはTemp/binフォルダの中のdll群を参照しています。V1.7.3.6であれば、これはなくても生成可能だったので仕様が変更になったようです。なので、コードジェネレーターを利用する前に、UnityのソリューションをビルドしてTemp/binフォルダにdllを生成する必要があります。VisualStudioを使っていればワンクリックで生成できるのですが、他のエディタを使っている場合どうやるんですかね・・・
 ソリューションをビルドしdll生成後、mpc.exeを利用してコードを生成できるようになります。

余談

 実はこのブランチを見つける前は、masterブランチがいろいろ更新されているみたいだしmasterブランチの最新コミットを使えば直ってるのでは!?と思ってこっちでビルドしました。確かにmpc.exeには問題は全くなかったのですが、MessagePack自体の仕様が大幅に変わり、参照dllがめっちゃ増えてたりMessagePackSerializerやResolverの仕様が変わったりして全部コードを書き直す必要がありました。特にResolverはどのように書いたら良いか分からず、実機で動かすことができませんでした・・・
 neueccさんが新しいバージョンでは大幅に変更になるとツイートしていたので、正式リリースまでちょっとドキドキしながら様子をうかがって行こうと思います!