LoginSignup
15
22

UnityMagicOnion導入方法(2023年最新)

Last updated at Posted at 2023-01-18

はじめに

MagicOnionを導入する敷居が高いと聞いていて、実際導入しようとしたら一発で導入できなかったので記事にまとめようと思いました。
出回っている情報でも古くなってしまっているので、2023年の最新バージョンということで書いていきます。

環境

クライアント

Unity 2021.4.14f1
gRPC UnityPackage 2.47.0
MessagePack v2.4.59
MagicOnion v5.0.2

サーバー

.Net 7.0
MagicOnion v5.0.2

その他

Rider 2022.3.1

Unityインストール

Unityの設定

ProjectSettings/Player/Configuration
Api Compatibility Levelを.NET Frameworkに設定
image.png

Scriptiong Backendは今回Monoにしていますが、IL2CPPにする場合、追加の手順が必要になります。

gRPC

以下のgrpcのデイリービルドからUnityPackageをダウンロードするのですが、

最近のデイリービルドからUnityPackageがなくなってしまっています。
地道に遡ってみたところ、2022/4/19のビルドには存在していたので、こちらからダウンロードできます。

image.png

---2023/08/05追記---

Cysharp様がサポートされなくなったgRPCのUnityパッケージの代わりとなるものをリリースしました!
(現時点ではプレビュー版)
gRPCが使えるだけではなくhttp2通信も可能です。

まだ試していないですが、聞いたところMagicOnionに簡単に導入できるらしいです。

---2023/12/17追記---

導入手順を別記事でまとめました!
Unityインストール手順とUnity側のコードを上記の記事で置き換えてご参照ください。

---追記終わり---

ダウンロードして解凍後、UnityのAssets/Plugin配下に

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

の3つを配置します。

gRPCで100MBを超えるファイルがあるので、Gitを利用する場合はLFSの設定が必要です。
Assets/Plugins/Grpc.Core/runtimes/android/arm64-v8a/libgrpc_csharp_ext.so
Assets/Plugins/Grpc.Core/runtimes/ios/libgrpc.a

MessagePack

リリースページから最新版のUnityPackageをダウンロードします。
(2023/1/18現在の最新はv2.4.59)

ダウンロード完了しましたら、インポートしてMessagePackの導入は完了です。

MagicOnion

MagicOnionもMessagePackと同様に最新版をリリースページからダウンロードします。
(2023/1/18現在の最新はv5.0.2)

ダウンロード完了しましたら、インポートして導入完了です。

サーバーインストール

私はRider上で構築したので、Riderの方法で書いていきます。

プロジェクト作成

Unityプロジェクトと同じリポジトリ内に.NET CoreのConsole Applicationのプロジェクトを作成します。

2023-01-18 164251.png

MagicOnion

NuGetで現時点での最新バージョン5.0.2をインストールします。

2023-01-18 164805.png

MagicOnionをインストールすれば、gRPCやMessagePackなどの必要なパッケージも自動的にインストールされます。
しかし、Unityとは異なるバージョンがインストールされるので、手動でそろえておいたほうが良いかもしれません。

起動スクリプト

Program.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.DependencyInjection;

static class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);
        builder.WebHost.UseKestrel(options =>
        {
            options.ConfigureEndpointDefaults(endpointOptions =>
            {
                endpointOptions.Protocols = HttpProtocols.Http2;
            });    
        });
            
        builder.Services.AddGrpc();
        builder.Services.AddMagicOnion();

        var app = builder.Build();

        app.MapMagicOnionService();
        
        app.Run();
    }
}

前半のエンドポイントのプロトコルをHTTP2に設定している個所ですが、こちらを設定しないとUnity側がリクエストを送ったときにエラーになってしまいます。

HelloWorld

シンプルな足し算APIを作成していきます。

共通コード

サーバーとクライアントで共通のコードはどこで管理するかは、討論になる話題かと思いますが今回はUnity側に置きます。
Assets配下であれば、任意の場所で大丈夫です。
ex) Assets/Scripts/Shared/

今回使用するインターフェースはこちらです。

IMyFirstService.cs
using MagicOnion;

namespace App.Reversi.Shared
{
    public interface IMyFirstService : IService<IMyFirstService>
    {
        UnaryResult<int> SumAsync(int x, int y);
    }
}

xとyの和を返すシンプルなインターフェスです。

サーバーサイドのプロジェクトに読み込み

上で作成したインターフェースをサーバーのプロジェクトにも読み込ませる必要があります。
csprojのItemGroupに、csprojからの相対パスでUnity内の共通コードのディレクトリを指定します。

<ItemGroup>
    <PackageReference Include="MagicOnion.Server" Version="5.0.2" />
+   <Compile Include="..\..\Assets\Scripts\Shared\**\*.cs" LinkBase="LinkFromUnity" />
</ItemGroup>

ちなみに私の環境のリポジトリの構造は以下のようになっています。

Repository
- Assets
 - Scripts
  - Shared
   - IMyFirstService.cs 
- Packages
- ProjectSettings
- Server ←サーバープロジェクト
 - Server
  - Server.csproj

サーバー側の実装

以下のファイルをプロジェクトに追加するだけで実装完了です。

MyFirstService.cs
using App.Reversi.Shared;
using MagicOnion;
using MagicOnion.Server;

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

他のファイルいじる必要がないので、簡単ですね。
おそらく起動スクリプト内でリフレクションで取得しているのかと思います。

そして追加が終わりましたら、プログラムを実行しておきましょう。

Unity側の実装

以下のファイルを作成して、

Sample.cs
using App.Reversi.Shared;
using Grpc.Core;
using MagicOnion.Client;
using UnityEngine;

public class Sample : MonoBehaviour
{
    async void Start()
    {
        var channel = new Channel("localhost", 5000, ChannelCredentials.Insecure);
        var client = MagicOnionClient.Create<IMyFirstService>(channel);
        var result = await client.SumAsync(1, 2);
        Debug.Log($"Result: {result}");
        await channel.ShutdownAsync();
    }
}

適当なシーンを作成して、適当なゲームオブジェクトにAddComponentして、実行します。

実行結果
image.png

最後に

導入に手こずりましたが、導入さえできれば実装は簡単そうですね。
次は、リアルタイム通信の実装方法やその応用について書いていこうと考えています。

15
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
22