🔖
Unity+MagicOnion4.1.xを試す 環境構築&サービスでの通信編
チャプター
まえがき
- リアルタイム通信をするにあたってMagicOnionが良さそうだったので調査と環境構築
- サンプルで利用しているコードはMagicOnionのREADMEをほぼ利用しています
- この記事ではServiceのみ取り扱い、StreamingHubに関しては取り扱わない
- ディレクトリやプロジェクト名は適宜読み替えてください
環境
- Windows 10
- Visual Studio 2019
- Unity 2020.2.3f1
- MagicOnion 4.1.2
- MessagePack-CSharp 2.2.85
- gRPC 2.37.0
ディレクトリ構成
- 相対パスで参照する箇所があるので、クライアント、サーバーすべて同ディレクトリ内に入れる
MyApp
└┬MyApp-Client
├MyApp-Server
└MyApp-Shared
クライアント(Unity)の環境構築
新しいプロジェクトを作成
Api Compatibility Levelの変更
- Player Settings > Other Settings > Api Compatibility Level 4.xに変更する
MagicOnionをimport
-
GitHubのReleasesから
MagicOnion.Client.Unity.unitypackage
をDLしてプロジェクトにimport
MessagePack-CSharpをimport
-
GitHubのReleasesから
MessagePack.Unity.2.2.85.unitypackage
をDLしてプロジェクトにimport
gRCPをimport
-
gRCPのビルドから
grpc_unity_package.2.37.0-dev202102141315.zip
をDL- 最新のビルドが必要であればDaily Buildsから最新のTimestampの
Build ID
からDL
- 最新のビルドが必要であればDaily Buildsから最新のTimestampの
- zipを解凍してPluginsの中にあるディレクトリをUnity側にコピー
GitHubなどで管理する場合
- 赤で囲っているが、Google.Protobufは不要だと思われるので入れなくて良さそう
- iOS向けのlibgrpc.aのファイルサイズが100MBを余裕で越えているのでREADMEのStripping debug symbols from ios/libgrpc.aを参考に
strip
してあげると良い- ここでいう
strip
コマンドはXCodeのstripなのでMac環境じゃないと動かないと思われる
- ここでいう
-
Grcp.Core/runtimes
配下で不要なOSのディレクトリは削除して問題ないと思われるので利用しないOSがあれば削除推奨
必要なディレクトリを作成
- Assets > Scripts > MyApp > Shared > Service
サーバーと接続するためのインタフェースを作成
Assets/Scripts/MyApp/Shared/Services/IMyFirstService.cs
using MagicOnion;
namespace MyApp.Shared.Services
{
// Defines .NET interface as a Server/Client IDL.
// The interface is shared between server and client.
public interface IMyFirstService : IService<IMyFirstService>
{
// The return type must be `UnaryResult<T>`.
UnaryResult<int> SumAsync(int x, int y);
}
}
コントローラーを作成
Assets/Scripts/MyApp/MyFirstController.cs
using Grpc.Core;
using MagicOnion.Client;
using MyApp.Shared.Services;
using UnityEngine;
namespace MyApp
{
public class MyFirstController : MonoBehaviour
{
private Channel _channel;
private IMyFirstService _service;
void Awake()
{
_channel = new Channel("localhost", 5000, ChannelCredentials.Insecure);
_service = MagicOnionClient.Create<IMyFirstService>(_channel);
}
async void Start()
{
var x = Random.Range(0, 1000);
var y = Random.Range(0, 1000);
var result = await _service.SumAsync(x, y);
Debug.Log($"Result: {result}");
}
async void OnDestroy()
{
if (_channel != null)
{
await _channel.ShutdownAsync();
}
}
}
}
Sceneにスクリプトを追加
- 適当なScene(今回はお試しなのでデフォで存在しているSampleScene)に空のゲームオブジェクトを追加してMyFirstController.csをAdd Compornentする
ここまでで一旦、クライアント(Unity)側の作業は終了
サーバー側の環境構築
プロジェクトの作成
- VisualStudioで新しいプロジェクトをgRPCサービスを作成
- .NET 5.0を利用するように変更
不要なファイルの削除
- Protos、ServicesはMagicOnionを利用する上で不要なので削除
MagicOnion.Serverを追加
- NuGetで
MagicOnion.Server
をMyApp-Server
に対して追加
Startup.csの修正
Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace MyApp
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
+ services.AddMagicOnion(); // Add this line
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
// Replace to this line instead of MapGrpcService<GreeterService>()
+ endpoints.MapMagicOnionService();
- endpoints.MapGrpcService<GreeterService>();
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");
});
});
}
}
}
共有プロジェクトの作成
-
ソリューションエクスプローラーから新しいプロジェクトを追加
- MyApp-Shared
- MyApp-Shared
-
クラスライブラリ(.NET Standard)で作成
MagicOnion.Abstractionsを追加
- NuGetで
MagicOnion.Abstractions
をMyApp-Shared
に対して追加
MessagePack.UnityShimsを追加
- NuGetで
MessagePack.UnityShims
をMyApp-Shared
に対して追加
クライアント(Unity)のShared配下を参照
- MyApp-Shared.csprojを開いてクライアントで作成したShared配下を参照する
MyApp-Shared.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>MyApp.Shared</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MagicOnion.Abstractions" Version="4.1.2" />
<PackageReference Include="MessagePack.UnityShims" Version="2.2.85" />
</ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\MyApp-Client\Assets\Scripts\MyApp\Shared\**\*.cs" />
+ </ItemGroup>
</Project>
MyApp-ServerにMyApp-Sharedの参照を追加
- ソリューションエクスプローラーからプロジェクを参照でMyApp-Sharedを選択
Serviceの作成
services/MyFirstService.cs
using System;
using MagicOnion;
using MagicOnion.Server;
using MyApp.Shared.Services;
namespace MyApp.Services
{
// Implements RPC service in the server project.
// The implementation class must inehrit `ServiceBase<IMyFirstService>` and `IMyFirstService`
public class MyFirstService : ServiceBase<IMyFirstService>, IMyFirstService
{
// `UnaryResult<T>` allows the method to be treated as `async` method.
public async UnaryResult<int> SumAsync(int x, int y)
{
Console.WriteLine($"Received:{x}, {y}");
return x + y;
}
}
}
接続確認
サーバーの起動
- F5などでサーバーを起動
- 下記のようなログが出れば起動OK
"C:\Program Files\dotnet\dotnet.exe" D:/MagicOnion/MyApp/MyApp-Server/bin/Debug/net5.0/MyApp-Server.dll
info: Microsoft.Hosting.Lifetime[0]
Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: D:\MagicOnion\MyApp\MyApp-Server
クライアント(Unity)のシーンを実行
- SampleSceneを実行してコンソールにログが出ればOK
- サーバー側にもログが出力されているはず
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint 'gRPC - /IMyFirstService/SumAsync'
Received:750, 621
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'gRPC - /IMyFirstService/SumAsync'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished HTTP/2 POST http://localhost:5000/IMyFirstService/SumAsync application/grpc - - 200 - application/grpc 78.6627ms
Discussion