Help us understand the problem. What is going on with this article?

UnityでgRPCを動かす

More than 1 year has passed since last update.

準備

前提

Unity + gRPCでは、MagicOnionというライブラリが有名ですが、ここではそれを使いません。
ただし、MagicOnionの修正内容は参考にしました...

以下をUnityプロジェクトに入れる

  • gRPCのC#のソースコード
    grpc/src/csharp/Grpc.Core
  • protobufのC#のソースコード
    protobuf/csharp/src/Google.Protobuf

エラーを粛々と取り除く

IAsyncEnumeratorが無いと怒られる

Assets/Grpc.Core/IAsyncStreamReader.cs(53,46): error CS0246: The type or namespace name `IAsyncEnumerator' could not be found. Are you missing an assembly reference?

IAsyncEnumeratorというインターフェースが無く、コンパイルエラーが出ますので、以下のような定義を追加します。

public interface IAsyncEnumerator<T> : IDisposable
{
    T Current { get; }
    Task<bool> MoveNext(CancellationToken token);
}

MoveNextの引数がないと言われる

Assets/Grpc.Core/Internal/ServerCallHandler.cs(69,69): error CS1501: No overload for method `MoveNext' takes `0' arguments

これは、Grpc.CoreがRx.NETに依存しているためこのようなエラーが表示されます。
なので、さらに以下のコードを追加します(namespaceやファイルの配置場所はそれぞれの事情に合わせてやってね)

    public static class AsyncEnumerator
    {
        public static Task<bool> MoveNext<T>(this IAsyncEnumerator<T> enumerator)
        {
            if (enumerator == null)
                throw new ArgumentNullException(nameof(enumerator));

            return enumerator.MoveNext(CancellationToken.None);
        }
    }

これは、Rx.NETのコードの中身そのままです。
Rx.NETまでUnityに入れようか悩みましたが、UniRxの競合とかとも考えられるためこの程度にしています。

この時点でコンパイルが通る

エラーが出なくなりました。では、次に実行してみましょう。

デバッグ実行用のSSLの証明書がないと言われる

実行するとこのエラーが出ました

IOException: Error loading the embedded resource "Grpc.Core.roots.pem"

SSLの証明書がない場合のエラーと考察し、どうしようかと考えていましたがここで、MagicOnion の修正方法を参考にさせていただきました。DefaultSslRootsOverride.cs を以下のように書き換えます。まあ、中身はまるっとその処理を無視するような内容です。

using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;

namespace Grpc.Core.Internal
{
    /// <summary>
    /// Overrides the content of default SSL roots.
    /// </summary>
    internal static class DefaultSslRootsOverride
    {
        //const string RootsPemResourceName = "Grpc.Core.roots.pem";
        static object staticLock = new object();

        /// <summary>
        /// Overrides C core's default roots with roots.pem loaded as embedded resource.
        /// </summary>
        public static void Override(NativeMethods native)
        {
            lock (staticLock)
            {
                //var stream = typeof(DefaultSslRootsOverride).GetTypeInfo().Assembly.GetManifestResourceStream(RootsPemResourceName);
                //if (stream == null)
                //{
                //    throw new IOException(string.Format("Error loading the embedded resource \"{0}\"", RootsPemResourceName));
                //}
                //using (var streamReader = new StreamReader(stream))
                //{
                //    var pemRootCerts = streamReader.ReadToEnd();
                //    native.grpcsharp_override_default_ssl_roots(pemRootCerts);
                //}
            }
        }
    }
}

これはMagicOnionのソースコードそのままです。
これで、この実行時のエラーは出なくなります。

DllNotFoundException: grpc_csharp_ext

grpc_charp_exが無いとエラーが表示されます。

DllNotFoundException: grpc_csharp_ext
Grpc.Core.Internal.NativeLogRedirector.Redirect (Grpc.Core.Internal.NativeMethods native) (at Assets/Grpc.Core/Internal/NativeLogRedirector.cs:49)

なので、それを入手してDLLをAssets配下に置く必要があるのですが、ここで自分は手間取りました。
Ubuntsu on Windowsを使っていたせいなのかはわからないですが、grpc本家のREADMEを読みつつビルドを試しましたが、うまくいかず、結局サンプルコードをVisual Studioでビルドし、NuGetパッケージの中かからdllを抜き出すということをしました

参考

なんだかんだあって、grpc_csharp_ext.dllをUnityプロジェクトに入れる

ここで、grpcのレポジトリ内にあるサンプルプロジェクトをビルドし、サーバーを立ち上げます。
https://github.com/grpc/grpc/tree/master/examples/csharp/helloworld

この中身をVisual Studioでビルドするだけでサーバー側のプログラムまでビルドされるので、ビルドしたサーバー側のexeファイルを立ち上げます。Windows以外の環境であれば、READMEの手順の通りに .NET Core インストールしつつビルドすることで実行できるかと思います。

クライアント側のサンプルコードを参考にしつつUnity側のプログラムを書く

まず、gRPC自体のサンプルプロジェクトには .proto と言われるサーバー側との通信規約をもとにしたコードもあるので、それをUnityプロジェクトに入れます。
3bdce428a37fe5aba1e59e6acdbf54b8.png

ここにある HelloWorld.cs/HelloWorldGRPC.cs がそれです。
これは、gRPCのコード生成プログラムによって吐かれるコードですがサンプルプロジェクトには含まれています。

UnityからCallする処理を入れる

以下のようなコードを書きます

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using Grpc.Core;
using Helloworld;


public class TestGrpc : MonoBehaviour 
{
    void Start () 
    {
        Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure);

        var client = new Greeter.GreeterClient(channel);
        String user = "Test UserName";

        var reply = client.SayHello(new HelloRequest { Name = user });
        Debug.Log("Greeting: " + reply.Message);
    }
}

これは、gRPCのC#サンプルプロジェクトの中身をそのままUnityのStartに入れ込んだだけです。
適当なGameObjectにこれをアタッチして実行します。
サーバー側のプログラムを立ち上げた上で実行すると、以下のようにちゃんとレスポンスを受け取れました!

d77a882b1dc6e1bce7cc29c7ad487ddf.png

その他

Android/iOSで動かすには、grpc_csharp_ext.dll をそれぞれのプラットフォームごとコンパイルするという苦行が待ってます。
https://github.com/grpc/grpc/blob/master/src/csharp/experimental/README.md
こちらにそのやり方は書かれてますが、まだiOSはTBD扱いです。。。
UniRxの作者の方が、いろいろやり取りされているので、できるんだと思います。
(grpc_csharp_extの中身はCのコードなのでXCodeでゴニョゴニョするとできるはず)

次は各プラットフォームの対応 + リアルタイムチャットなどをgRPCで出来たらなと思います。

rookx
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした