見出し画像

gRPCとProtocol Buffersによるアプリケーション間通信 / Unity

「gRPC」でアプリケーション間通信を行い、別アプリからテキストと画像を取得するスクリプトを作ります。

1. 開発ツールのインストール

Macで「Protocol Buffers」のコンパイラをインストールするコマンドは、次の通りです。

$ brew install protobuf

2. Grpc.Toolsとgrpc_unity_package

Grpc.Tools」は、protoファイルのコンパイルに利用するファイル群です。
grpc_unity_package」は、UnityのAssetsに追加するファイル群です。
取得手順は次の通りです。

(1)ブラウザで以下のサイトを開く。
gRPC Packages
(2)Daily Builds of master Branchの最新のBuild IDのリンクをクリック。

画像1

(3)C#の「Grpc.Tools」と「grpc_unity_package」をダウンロード。

画像2

(4)「Grpc.Tools」の拡張子「nupkg」を「zip」に変更して解凍し、親フォルダ名(「Grpc.Tools.2.24.0-dev201909091001」など)をGrop.Toolsに変更。
(5)「grpc_unity_package」を解凍し、「Pluginsフォルダ」をUnityの「Assetsフォルダ」に配置。
(6)Unityのメニュー「File → Build Settings → Player Settings → Other Settings」で「Api Compatibility Level」を「.Net 4.x」に指定。

3. 最新のGoogle.Protobuf.dllの上書き

これで設定完了...といきたいところですが、2019年9月現在「grpc_unity_package」内の「Google.Protobuf.dll」が古いので、C#のビルド時に以下のようなエラーがでます。そこで、新しいもので上書きします。

Assets/Chat.cs(35,17): error CS1729: 'GeneratedClrTypeInfo' does not contain a constructor that takes 7 arguments

(1)以下のサイトを開き、Download packageをクリックし、「google.protobuf.3.9.1.nupkg」をダウンロード
NuGet Gallery | Google.Protobuf 3.9.1
(2)拡張子「nupkg」を「zip」に変更して解凍。
(3)「google.protobuf.3.9.1/lib/net45/Google.Protobuf.dll」を「Plugins/Google.Protobuf/lib/net45/Google.Protobuf.dll」に上書き。

4. protoファイルの生成

構造化データを定義する「protoファイル」を生成します。前回との違いは「csharp_namespace」になります。

【simple.proto】

syntax = "proto3";

option csharp_namespace = "Simple.Grpc";

package simple;

//リクエスト
message SimpleRequest{
}

//レスポンス
message SimpleResponse{
  string text = 1;
  string image = 2;
}

//RPCインタフェースの定義
service SimpleService{
  rpc SimpleSend (SimpleRequest) returns (SimpleResponse) {}
}

5. protoファイルのコンパイル

protoファイルのコンパイルは「protoc」を使います。「--plugin=protoc-gen-grpc=」には、先ほどダウンロードした「Grop.Toolsのフォルダ」のパスを指定します。

$ protoc -I . --csharp_out=. --grpc_out=. simple.proto --plugin=protoc-gen-grpc=Grpc.Tools/tools/macosx_x64/grpc_csharp_plugin

以下の2つのファイルが生成されます。UnityのAssetsに配置します。

Simple.cs : シリアライズのインタフェース
SimpleGrpc.cs : gRPCのインタフェース

6. サーバーの実装

サーバーを実装します。Assets/StreamingAssetsに「image.jpg」を配置します。

【SimpleServer.cs】

using System.Threading.Tasks;
using UnityEngine;
using Grpc.Core;
using Simple.Grpc;
using System;
using System.Text;

//シンプルサーバー
public class SimpleServer : MonoBehaviour {
    //シンプルサービスサーバーの定義
    class SimpleServiceImpl : SimpleService.SimpleServiceBase {
        //チャット送信の処理
        public override Task<SimpleResponse> SimpleSend(
            SimpleRequest request, ServerCallContext context) {
            var text = "This is TEST!";
            var bytes = System.IO.File.ReadAllBytes(
                Application.streamingAssetsPath + "/" + "image.jpg");
            string b64 = Convert.ToBase64String(bytes);
            return Task.FromResult(new SimpleResponse {Text = text, Image = b64});
        }
    }

    //スタート時に呼ばれる
    void Start() {
        //サーバーの開始
        Server server = new Server {
            Services = {SimpleService.BindService(new SimpleServiceImpl())},
            Ports = {new ServerPort("localhost", 50051, ServerCredentials.Insecure)}
        };
        server.Start();
        print("サーバーの開始");
    }
}

7. クライアントの実装

クライアントを実装します。

【SimpleClient.cs】

using UnityEngine;
using Grpc.Core;
using Simple.Grpc;
using System;
using System.Text;
using System.IO;

//シンプルクライアント
public class SimpleClient : MonoBehaviour {
    //スタート時に呼ばれる
    void Start() {
        //サーバーとの接続
        Channel channel = new Channel("localhost:50051", ChannelCredentials.Insecure);
        SimpleService.SimpleServiceClient client = new SimpleService.SimpleServiceClient(channel);
        var response = client.SimpleSend(new SimpleRequest());
        print("text: " + response.Text);
        byte[] im_bytes = Convert.FromBase64String (response.Image);
        File.WriteAllBytes(Application.dataPath + "/../client.jpg", im_bytes);
    }
}

8. サーバーとクライアントの実行

Unityアプリ同士だけでなく、前回作ったPythonスクリプトとも連携できます。

9. Macのアプリとしてビルドして実行

Macのアプリとしてビルドして実行すると、以下のようなエラーが発生しました。「grpc_csharp_ext」が見つからないようです。

System.DllNotFoundException: grpc_csharp_ext

「パッケージの内容を表示」で確認すると、以下にありました。

ContentsPluginsx64grpc_csharp_ext.bundlex86grpc_csharp_ext.bundle

試しに、x64の「grpc_csharp_ext.bundle」をPlugins直下に置いたところ、見つけられたようで、正常に動きました。

ContentsPluginsgrpc_csharp_ext.bundle

この記事が気に入ったらサポートをしてみませんか?