プリグラ(プリコネ!グランドマスターズ)で少し話題になったMagicOnionを試しに使ってみたいって方が環境構築するときに参考になれば幸いです。結構二番煎じだと思いますが、まだMagicOnionの文献が少ないので少しでも貢献できればいいな。
はじめに
MagicOnionは、アプリとサーバーをC#言語で統一しgRPCでつないでしまおうという通信フレームワークです。
何でC#言語かというとUnityがC#ってのが影響力大きいと思います(ただUnityのC#は「Unity独自のC#」なので厄介な問題があるんですけどね)。
Unityで使える貴重な通信フレームワーク(他には最近だと開発途上のNetcodeなど)なので詳しく知りたいという人はかなり多いと思いますし、最近は確実に企業での採用実績も増えてきています。
ただMagicOnion、環境構築が少しクセがあります。
アプリとサーバーを共通化する以上、環境構築の際に必要な知識もアプリ側、サーバー側と、今まで別々に担当者が分かれていた両面必要になるので、そこが曲者となってきます。
この記事では、その辺りも踏まえて解説していこうと思います。
ディレクトリ構成の完成予想図
まず最初に全体像を見てもらった方が分かりやすいかな。
MagicOnionは共通化という概念の自由度の高さから、各々のプロジェクトの都合に合わせて様々な構成を作ることができます。
逆に言えば千差万別になりやすく、それ故に初学者が目標を見失いやすい部分があります。
分かりやすさ重視として、私は今回こんな感じのディレクトリ構成にしました。
オレンジ:Unityプロジェクト
赤:アプリ側
黄緑:サーバー側
MagicOnion2というひとつの大きなUnityプロジェクト(3Dテンプレート)の中に、サーバー用のフォルダが内臓されている形になっています。
サーバー用のフォルダ(Server)をUnityプロジェクトの外に出して管理することも出来ますが、今回は分かりやすさ重視で。
この完成形を目指して環境構築を始めます。
Unityプロジェクトの作成
アプリ側の環境構築から行きますね。
Unityプロジェクトの作成については特に不要かと思いますが、UnityHubから「新しいプロジェクト」→テンプレート「3D」→エディタバージョン「2021.3.0f1」を選んでプロジェクト名(私のはMagicOnion2)を指定して「プロジェクトを作成」って感じです。
※今回はUnity2021での動作確認もかねていました。
プロジェクトが作成出来たら、プロジェクト設定を少し変更する。
API互換性レベルを「.NET standard 2.1」から「.NET Framework」に変更する。
(理由についてはアプリ実装の部分で解説します)
他所様では「スクリプティングバックエンドをIL2CPPにしなさい」ってあったりしますが、今回は不要です。
IL2CPPはC#をC++として変換する仕組みで、iOSビルドなどに必要になります。
(通常はMonoというUnity独自の.NET互換C#コンパイラを使います)
MagicOnionはC#で出来ているので、IL2CPPで構成する場合は同じようにC++変換する作業が必要です。その場合、コードジェネレーター(moc.zip)を使う必要があり環境構築が複雑になります。・・・ので、今回は使いません!
気付いた方もいらっしゃると思いますが、「スクリプティング ランタイム バージョン(Scripting Runtime Version)」という項目が無くなっています。
以前はそこで「.NET 4.x Equivalent」などを選択する必要がありましたが、Unity2019から「.Net3.5」が無くなったので項目が無くなりAPI互換性レベル(Api Compatibility Level)に統一されました。
つまりAPI互換性レベルを「.NET Framework」にしておけば、「.NET 4.x Equivalent」を選択するのと同じになります。
MagicOnionをプロジェクトに追加
公式ドキュメントから
https://github.com/Cysharp/MagicOnion#support-for-unity-client
MagicOnionリリースページへ
https://github.com/cysharp/MagicOnion/releases
そして「MagicOnion.Client.Unity.unitypackage」をダウンロードして、Unityプロジェクトにインポートします。
gRPCをプロジェクトに追加
公式ドキュメントからgRPC公式ページに行き
https://packages.grpc.io/
最新の「Build ID」項目にあるリンク→「C#」の「grpc_unity_package.2.47.0-dev202204190851.zip」をダウンロードして展開します。
zip展開した中の「Google.Protobuf」「Grpc.Core」「Grpc.Core.Api」だけをUnityプロジェクトのAsset/Pluginsにコピーします。
間違って全部コピーすると画像のようなエラーが発生しますが、先ほどの3つのフォルダ以外を削除すれば大丈夫です。
MessagePackをプロジェクトに追加
公式ドキュメントからMessagePackのリリースページに行き
https://github.com/neuecc/MessagePack-CSharp/releases
「MessagePack.Unity.2.3.85.unitypackage」をダウンロードしてUnityプロジェクトにインポートします。
インポートの際にMagicOnionの「System.Buffers.dll」「System.Memory.dll」「System.Runtime.CompilerServices.Unsafe.dll」「System.Threading.Tasks.Extensions.dll」の重複警告が出ますが上書きしてしまって大丈夫です。
VisualStudioCodeの環境構築
UnityプロジェクトにMagicOnionでアプリを作る準備は出来ました。
次はサーバーと行きたいところですが、その前にVSCodeでC#開発できるように環境構築をします。以下の参考サイト様とやることはほぼ同じです。
どうしてもC#をVSCodeで書きたい
https://qiita.com/_patrush/items/dc8b2f8ea4c59d49c1fd
参考サイトに従って必要な拡張機能をインストール
Unityプロジェクトのフォルダを開いて
「フォルダーをワークスペースに追加」をやって保存すればワークスペースファイルが作成されるので、サイトの内容をコピペした後、「**/Assets/Scripts/Generated」「**/Assets/Scripts/MagicOnion*」「**/Assets/Scripts/MessagePack」の行をコメントアウトします。
こうするとAssetsのスクリプトも見えるようになります。
(参考サイトでは非表示設定だけど、アプリ実装で表示する必要がある)
「extensions.json」はUnityプロジェクトの「.vscode」フォルダの中に入れます。
(VSCodeで開いたときに.vscodeフォルダが自動生成されるはず?)
これでC#の開発環境はだいたいOKだと思います。
MagicOnionサーバーの環境構築
VSCodeの設定が終わったら、そのままServerフォルダを作成して、その中にMagicOnionのサーバーを構築します。
(アプリもMagicOnionというのでややこしいです)
公式ドキュメントには「dotnet app package MagicOnion.Sever」(.NETコマンド)を使って追加すると書いてありますが、ちょっと初心者には説明不足で、そのまま実行すると失敗します。
(既に開いてるかもですが)先ほど作成したSeverフォルダを右クリックして「統合ターミナルで開く」を選択します。
メニュー「ターミナル」からでもいいですが、フォルダから開くとコマンドラインのパスがそこになるので便利です。
Severの中で「dotnet new grpc」を実行します。
MagicOnionはgRPCで作られているので、gRPCプロジェクトを指定して作成します。
(Severフォルダの中に色々追加されます)
その後に「dotnet add package MagicOnion.Sever」を実行します。
後は公式ドキュメントにある通り、Severの中に作成されたStartup.csの内容を変更します。
最後に「dotnet run」でサーバーが起動すれば完了です。
共通インタフェースの作成
ここまでお疲れさまでした。
環境構築が終わったら、いよいよ通信アプリの実装をやって行こうと思います。
まずはMagicOnionでの共通インタフェース「IMyFirstService.cs」を作成します。
IMyFirstServiceの内容は公式ドキュメントと同じで大丈夫です。
ファイルの位置だけ注意が必要で、このIMyFirstServiceをサーバーから参照設定するので、他の共通化しないファイルと別々に分ける必要があります。
また、UnityでIMyFirstServiceを使いたい場合、これをUnityコンパイルする必要があるので、Asset内に存在していないといけません。
ディレクトリ構成は自分も悩みましたが、namespaceと同じようなフォルダ構成で「Assets/Scrips/MyApp/Shared/IMyFirstService.cs」としました。ここら辺は割と自由だと思います。
アプリ部分の実装
次に通信アプリの実装を行います。
公式ドキュメントと以下のサイト様を参考に「SampleAppCall.cs」作りました。
UnityとMagicOnionの環境構築(IL2CPP)
https://zenn.dev/kumatta_ss/articles/dab376b180aa85
注意点としては、公式ドキュメントでは「GrpcChannel」を使っていますが、これはUnityでは利用することが出来ませんのでコメントアウトして、2行下の「new Channel」の方を使います。
またgRPCのssl通信が今のUnity環境では出来ないっぽい?ので、ポート番号5001を5000にして、ChannelCredentials.Insecure(安全でないセキュア)を指定します。
この辺りの問題は、Unityのプロジェクト設定「.NET standard 2.1」「.NET Framework」と密接に関係しています。
アプリのUnityコンパイルが通ったら、Unity上に空のオブジェクトを作成してコンポーネントにこの作成したスクリプトを設定して準備完了です。
サーバー部分の実装
まず共通インタフェースを参照できるようにします。
Severフォルダ内の「Sever.csproj」に「<Compile Include=”..\Assets\Scripts\MyApp\Shared\**\*.cs” LinkBase=”LinkFromUnity” />」を追加します。
これでShared以下のスクリプトを全て参照できるようになりました。
コンパイル参照が出来たら、Sever/Servicesの中に「MyFirstService.cs」を作成します。
(内容は公式ドキュメントにある通りです)
出来たらServerのターミナルを開いて、「dotnet run」を実行します。
asyncに関する警告が表示されますが、とりあえず無視でOK
(公式ドキュメント通りだもの)
サーバーを待機中にしたまま、Unityに戻ります。
最後にUnityで動作確認
後はUnityプロジェクトをテスト実行するだけです。
上手く行けば、Unityのコンソールと、VSCodeのターミナルにログが表示されます。
サーバーが起動していなかったり、何らかの問題があった時は、Unityのコンソールにエラーが表示されます。
(以下はサーバーが起動していなかったとき)
おまけ
MagicOnionの環境構築またやるか(3回目)
— 藤原工房 (@FujiwaraKoubou) April 21, 2022
コメントを残す