🐻

UnityとMagicOnionの環境構築(IL2CPP)

20 min read

はじめに

Unityを始めたばっかり! や、サーバー分らん! という方でも、
順番にやっていけば、動作を確認できるように記載しています

スクロールが小さくて長いように見えますが、説明画像がほとんどなのでご安心を!!

不備・不明点等あればコメントへどうぞ!!

MagicOnionのREADMEをベースに、ローカル動作確認の環境構築をしていきます!!

今回のゴールは、
Unityのクライアントから、サーバー側の関数の結果を受け取れるところまで!!
サーバーへ数値を2つ渡し、足した結果をクライアントに戻してもらうシンプルなものです!

MagicOnionのREADMEは英語なので、日本語の備忘録的に・・・(ToT)
英語できる人すごいですよね~(>ω<)

環境

前提条件

下記がインストール済みである事

  • VisualStudio 2019
  • Unity 2020.3.13f1

手順

フォルダ名等の名称は、任意の値で問題ありません!!
適宜読み替えてください!!

  1. 作業用フォルダの作成
  2. Unityのクライアントプロジェクト作成・設定
  3. サーバー関数の呼び出し実装
  4. gRPC用のサーバープロジェクト作成・設定
  5. 通信用インターフェース共有プロジェクトの作成
  6. サーバー側の関数の実装
  7. 動作確認

■作業用フォルダの作成

クライアントとサーバーのプロジェクトを、格納するフォルダを任意の場所に作成

特殊記号、スペース、日本語を含む場所に作成するのは、
問題を引き起こす可能性があるので避けましょう!!

クライアントとサーバーで、通信用インターフェースを相対パスで共有するので、
プロジェクトは作成したフォルダ配下に格納していきます

最終的な構成は、こんな感じ

例:D:/work/KumattaApp
KumattaApp ← このルートフォルダを任意の場所に作成
  ├─ KumattaApp-Client
  ├─ KumattaApp-Server
  └─ KumattaApp-Shared

■Unityのクライアントプロジェクト作成・設定

プロジェクトの作成

プロジェクトの設定

Edit -> Project Settings...」を押下


Player -> Other Settings -> Configuration」の設定を変更

項目 設定値
Scripting Backend IL2CPP
App Compatibility Level* .Net 4.x

Scripting Backend」は、初期設定では「Mono」が指定されていますが、
iOSのビルドをしたい場合、「IL2CPP」になるので、IL2CPPを基準に設定をします

MessagePackをインポート

MessagePackのunitypackageをダウンロードし、作成したプロジェクトへインポート
MessagePack 2.2.85

MessagePackのコード補完用の拡張をインストール

MessagePackのunitypackageをダウンロードし、ダブルクリックでインストール

gRPCを配置

gRPCのUnity向けzipをダウンロードし、解凍した「Plugins」の配下にある、
下記のフォルダを、Unityプロジェクトの「Plugins」配下にコピー
gRPC 2.40.0

  • Google.Protobuf
  • Grpc.Core
  • Grpc.Core.Api

MagicOnionをインポート

MagicOnionのunitypackageをダウンロードし、作成したプロジェクトへインポート
MagicOnion 4.3.1

クライアントスクリプト用のフォルダを作成

少し階層が多いですが、スクリプトの区別の為に分けています

パス(KumattaApp/Scriptsの配下) 用途
MagicOnion/Client/Generated 後述のサーバービルドで、生成されるスクリプトを格納
MagicOnion/Server/Services/Interface サーバー通信用インターフェースを格納
MyApp 動作確認用のスクリプトを格納

KumattaApp
  └─Scripts
      ├─MagicOnion
      │  ├─Client
      │  │  └─Generated
      │  └─Server
      │      └─Services
      │          └─Interface
      └─MyApp

サーバー通信用のインターフェース作成

  1. サーバー通信用インターフェースのフォルダを選択
  2. 右クリックして、「Create -> C# Script」を押下し、「IMyFirstService」を作成

Assets/KumattaApp/Scripts/MagicOnion/Server/Services/Interface/IMyFirstService.cs
using MagicOnion;

namespace MyApp.Shared
{
    public interface IMyFirstService : IService<IMyFirstService>
    {
        // The return type must be `UnaryResult<T>`.
        UnaryResult<int> SumAsync(int x, int y);
    }
}

■サーバー関数の呼び出し実装

クライアント処理を作成

前述と同様の手順で、下記のフォルダにサーバー処理呼出しのスクリプトを作成

MagicOnionのREADMEだと、https通信になっていて、
証明書等の設定が必要になってくるので、今回は省略する為にhttp通信で対応します

var channel = new Channel("localhost", 5001, new SslCredentials());
Assets/KumattaApp/Scripts/MyApp/KumattaAppCall.cs
using UnityEngine;
using Grpc.Core;
using MagicOnion.Client;
using MyApp.Shared;

public class KumattaAppCall : MonoBehaviour
{
    void Start()
    {
        CallTest();
    }
    public async void CallTest() 
    {
        string host = "localhost";
        int port = 5001;

        // http用に変更
        var channel = new Channel(host, port, ChannelCredentials.Insecure);

        var client = MagicOnionClient.Create<IMyFirstService>(channel);
        var result = await client.SumAsync(100, 23);
        Debug.Log($"Result: {result}");
    }
}

スクリプトを動作させる為に、GameObjectへアタッチ

Hierarchy」で右クリックして、「Create Empty」を押下



  1. 作成した「GameObject」を選択
  2. Inspector -> Add Component」押下
  3. 上記で作成したスクリプト「KumattaAppCall」を検索して押下
  4. アタッチを確認出来たら「Ctrl + s」で、シーンの変更を保存

■gRPC用のサーバープロジェクト作成・設定

プロジェクトの作成

VisualStudio 2019を起動して、「新しいプロジェクトの作成(N)」を押下


検索条件に下記を設定して、検索結果に表示される
ASP.NET Core gRPC サービス」を選択し、「次へ」を押下

項目
テンプレートの検索 gRPC
言語 C#
プラットフォーム すべてのプラットフォーム
プロジェクトの種類 コンソール


プロジェクト名と、前述で作成した作業用フォルダを指定して、「次へ」を押下


ターゲットフレームワークに「.Net Core 3.1 (長期的なサポート)」を選択し、「次へ」を押下

MagicOnion.Serverの追加

  1. 作成したサーバープロジェクトを選択
  2. 右クリックして「NuGetパッケージ管理」を押下


NuGet画面の「参照」を押下


  1. 検索に「MagicOnion.Server」を入力
  2. 検索結果の「MagicOnion.Server」を選択
  3. バージョンは「4.3.1」選択
  4. インストール」を押下


OK」を押下

プロジェクトの不要ファイルを削除

MagicOnionでは、「Protos」、「Services」は利用しない為、フォルダを削除

「Startup.cs」を変更

MagicOnionをロードする為に、スクリプトを変更

Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace KumattaApp_Server
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddGrpc();
            services.AddMagicOnion();  // ← MagicOnionを追加
        }
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapMagicOnionService();  // ← MagicOnionにアクセスする為、変更
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
                });
            });
        }
    }
}

通信を「http」に変更

applicationUrl」が「https」になっているので、「http」に変更

httpsだと、証明書等の設定が必要になってくるので、今回は省略する為にhttpで対応

Properties/launchSettings.json
{
  "profiles": {
    "KumattaApp-Server": {
      "commandName": "Project",
      "launchBrowser": false,
      "applicationUrl": "http://localhost:5001",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

■通信用インターフェース共有プロジェクトの作成

共有プロジェクトの作成

ソリューションを右クリックして、「追加 -> 新しいプロジェクト」を押下


検索条件に下記を設定して、検索結果に表示される
クラス ライブラリ」を選択し、「次へ」を押下

項目
テンプレートの検索 クラス
言語 C#
プラットフォーム すべてのプラットフォーム
プロジェクトの種類 すべてのプロジェクトの種類


プロジェクト名と、前述で作成した作業用フォルダを指定して、「次へ」を押下


ターゲットフレームワークに「.Net Standard 2.1」を選択し、「次へ」を押下


自動で作成される「Class1.cs」は、不要なので削除

NuGetからパッケージの追加

前述の「MagicOnion.Serverの追加」の手順と同様に、下記のパッケージを追加

パッケージ名 バージョン
MagicOnion.Shared 4.3.1
MagicOnion.MSBuild.Tasks 4.3.1
MessagePack.UnityShims 2.1.194
MessagePack.MSBuild.Tasks 2.1.194

記事の投稿時点で、MessagePackの最新は、「2.2.85」でしたが、
自動生成時に、引数のエラーが発生する為、バージョンを落としています

  1. 作成した共有プロジェクトを選択
  2. 右クリックして「NuGetパッケージ管理」を押下


NuGet画面の「参照」を押下


  1. 検索に「パッケージ名」を入力
  2. 検索結果の「パッケージ名」を選択
  3. 指定バージョン」選択
  4. インストール」を押下


OK」を押下

Unityクライアントのサーバー通信用インターフェースの参照追加

  1. 共有プロジェクトを選択
  2. 右クリックして「プロジェクトファイルの編集」を押下

下記の3つの要素を追加

★1つ目は、サーバー通信用のインターフェース
前述の「クライアントスクリプト用のフォルダを作成」で作成したフォルダを設定

KumattaApp
  └─Scripts
      ├─MagicOnion
      │  ├─Client
      │  │  └─Generated
      │  └─Server  ← このフォルダの相対パスを設定!!!
      │      └─Services
      │          └─Interface
      └─MyApp
<ItemGroup>
  <Compile Include="..\Unityプロジェクト名から「Server」までのパス\**\*.cs" Link="Server/%(RecursiveDir)/%(FileName)%(Extension)" />
</ItemGroup>


★次は、IL2CPP用のスクリプト自動生成を2つ追加

自動生成が必要な理由については、記事の目的と違うので説明しません!!
気になる方は、下記のURLを参照してください!
MessagePack-CSharp - Unity support
MagicOnion - Support for Unity client

KumattaApp
  └─Scripts
      ├─MagicOnion
      │  ├─Client
      │  │  └─Generated  ← このフォルダに出力する用に設定!!!
      │  └─Server
      │      └─Services
      │          └─Interface
      └─MyApp
<Target Name="GenerateMessagePack" AfterTargets="Compile">
  <MessagePackGenerator Input="$(ProjectPath)" Output="..\Unityプロジェクト名から「Generated」までのパス\MessagePack.Generated.cs" />
</Target>
<Target Name="GenerateMagicOnion" AfterTargets="Compile">
  <MagicOnionGenerator Input="$(ProjectPath)" Output="..\Unityプロジェクト名から「Generated」までのパス\MagicOnion.Generated.cs" />
</Target>


修正後

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.1</TargetFramework>
    <RootNamespace>KumattaApp_Shared</RootNamespace>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="MagicOnion.MSBuild.Tasks" Version="4.3.1" />
    <PackageReference Include="MagicOnion.Shared" Version="4.3.1" />
    <PackageReference Include="MessagePack.MSBuild.Tasks" Version="2.2.85">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="MessagePack.UnityShims" Version="2.2.85" />
  </ItemGroup>


  <!-- =========================== 以下を追加 =========================== -->
  <ItemGroup>
    <Compile Include="..\KumattaApp-Client\Assets\KumattaApp\Scripts\MagicOnion\Server\**\*.cs" Link="Server/%(RecursiveDir)/%(FileName)%(Extension)" />
  </ItemGroup>

  <Target Name="GenerateMessagePack" AfterTargets="Compile">
    <MessagePackGenerator input="$(ProjectPath)" output="..\KumattaApp-Client\Assets\KumattaApp\Scripts\MagicOnion\Client\Generated\MessagePack.Generated.cs" />
  </Target>
  <Target Name="GenerateMagicOnion" AfterTargets="Compile">
    <MagicOnionGenerator Input="$(ProjectPath)" Output="..\KumattaApp-Client\Assets\KumattaApp\Scripts\MagicOnion\Client\Generated\MagicOnion.Generated.cs" />
  </Target>
  <!-- ================================================================== -->
</Project>

■サーバー側の関数の実装

サーバープロジェクトに、共有プロジェクトの参照を追加

  1. サーバープロジェクトを選択
  2. 右クリックして「追加 -> プロジェクト参照」を押下


共有プロジェクトにチェックをつけて、「OK」を押下

サーバー側の関数を作成

  1. サーバープロジェクトを選択
  2. 右クリックして「追加 -> 新しいフォルダ」を押下
  3. Services」のフォルダを作成

前述で削除したフォルダですが、初期で生成されるスクリプトの削除漏れを防ぐ為、
フォルダごと削除していました


  1. 作成した「Services」を選択
  2. 右クリックして「追加 -> クラス」を押下


  1. クラス」を選択
  2. 名前に「MyFirstService.cs」を入力
  3. 追加」を押下


KumattaApp-Server/Services/MyFirstService.cs
using MagicOnion;
using MagicOnion.Server;
using MyApp.Shared;
using System;

namespace KumattaAppServer.Services
{
    public class MyFirstService : ServiceBase<IMyFirstService>, IMyFirstService
    {
        public async UnaryResult<int> SumAsync(int x, int y)
        {
            Console.WriteLine($"Received:{x}, {y}");
            return x + y;
        }
    }
}

Unityクライアントプロジェクトに、自動生成されるスクリプトを適用

メニューの「ビルド -> ソリューションのビルド」を押下して、ソリューションをビルド


出力画面でビルドが成功している事を確認


Unityクライアントプロジェクトに、スクリプトが生成されている事を確認
出力先は前述の「クライアントスクリプト用のフォルダを作成」で作成したフォルダ

KumattaApp
  └─Scripts
      ├─MagicOnion
      │  ├─Client
      │  │  └─Generated ← このフォルダに生成されている!!!
      │  └─Server
      │      └─Services
      │          └─Interface
      └─MyApp


生成されたスクリプトをロードするスクリプトを作成

  1. 上記のフォルダで、右クリックして「Create -> C# Script」を押下
  2. MagicOnionLoad」を作成

Assets/KumattaApp/Scripts/MagicOnion/Client/Generated/MagicOnionLoad.cs
using MessagePack;
using MessagePack.Resolvers;
using UnityEngine;

public class MagicOnionLoad 
{
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    static void RegisterResolvers()
    {
        StaticCompositeResolver.Instance.Register(
            MagicOnion.Resolvers.MagicOnionResolver.Instance,
            MessagePack.Resolvers.GeneratedResolver.Instance,
            StandardResolver.Instance
        );

        MessagePackSerializer.DefaultOptions = MessagePackSerializer.DefaultOptions
            .WithResolver(StaticCompositeResolver.Instance);
    }
}

■動作確認

サーバーの起動

メニューの「KumattaApp-Serrver」を押下


コマンドプロンプトが起動し、URLが前述の「通信を「http」に変更」で設定した
applicationUrl」の値になっている事を確認

Unityクライアントの実行

Unityのメニューの再生ボタンを押下



Unityの「Console」に計算結果が、表示されていれば成功!!!

サーバーのコマンドプロンプト側

クライアント、サーバーの停止

Unityクライアントは、メニューの再生ボタン押下で停止


サーバーの停止は、コマンドプロンプトを選択している状態で、「Ctrl+C」を押下

お疲れさまでした!!!
以上で、動作確認の環境構築は完了です!!!!!!

あとがき

構築した環境のGitHub

ここまで読んでいただきありがとうございます!!!
参考になりましたか?
次回は、この環境を元に、Android、iOSの動作確認をしようと思います!!

記事を書くモチベーションにしたいので、よろしければサポートをお願いします!!

Discussion

ログインするとコメントできます