環境
macOS Catalina 10.15.3
Unity 2019.3.4f1
Visual Studio for Mac Community 8.4.8
環境構築
フォルダ作成
全体のプロジェクトを入れるためのフォルダを作成する。
ここではMagicOnionSampleとする
Unityプロジェクト作成
MagicOnionSampleフォルダの中にUnityのプロジェクトを作成する。
プロジェクト名をここではSample.Unityとする。
PlayerSettings
APICompatibilityLevel を .NET4.x に変更する(全てのプラットフォームで設定する)
Allow unsafe Code にチェックをいれる
Scripting Define Symbolsに
ENABLE_UNSAFE_MSGPACK
と入力する
フォルダ作成
- MagicOnionSample/Sample.Unity/Assets/Editor
- MagicOnionSample/Sample.Unity/Assets/Plugins
- MagicOnionSample/Sample.Unity/Assets/Scripts
- MagicOnionSample/Sample.Unity/Assets/Scripts/Generated
- MagicOnionSample/Sample.Unity/Assets/Scripts/ServerShared
- MagicOnionSample/Sample.Unity/Assets/Scripts/ServerShared/Hubs
- MagicOnionSample/Sample.Unity/Assets/Scripts/ServerShared/MessagePackObjects
- MagicOnionSample/Sample.Unity/Assets/Scripts/ServerShared/Services
- MagicOnionSample/GeneratorTools
MagicOnionをインストール
Releases · Cysharp/MagicOnion · GitHub
から
- MagicOnion.Client.Unity.unitypackage
- moc.zip
の2つをダウンロード。
MagicOnion.Client.Unity.unitypackage をインポート。
moc.zipを解凍し、GeneratorToolsフォルダの中に入れる。
MessagePack for C#
Releases · neuecc/MessagePack-CSharp · GitHub
から
- MessagePack.Unity.2.1.90.unitypackage
- mpc.zip
の2つをダウンロード
MessagePack.Unity.2.1.90.unitypackage をインポート
mpcをGeneratorToolsフォルダの中に入れる。
gRPCのダウンロード
ここから、最新のビルドをクリックし、C#のカテゴリにある、grpc_unity_packageと名前が付いているものをダウンロード
ダウンロードして解凍したPluginsフォルダの中から、
- Grpc.Core
- Grpc.Core.Api
の2つをMagicOnionSample/Sample.Unity/Assets/Plugins/ の中に入れる
サーバーへ接続するための Script の用意
MagicOnionSample/Sample.Unity/Assets/Scene/ フォルダに次のようにSampleController.csを作成する。
using Grpc.Core; using System.Collections; using System.Collections.Generic; using UnityEngine; public class SampleController : MonoBehaviour { private Channel channel; void Start() { this.channel = new Channel("localhost:12345", ChannelCredentials.Insecure); } async void OnDestroy() { await this.channel.ShutdownAsync(); } }
Start() でサーバーへ接続し、OnDestroy() で切断するようになっている。
SampleController という空のゲームオブジェクトを作成し、SampleControllerをアタッチする。
サーバー側の設定
Unity ⇔ サーバー間のコード共有の動作確認用の class の用意
MagicOnionSample/Sample.Unity/Assets/Scripts/ServerShared以下に置いてあるスクリプトを全て共有する設定を行う。
MagicOnionSample/Sample.Unity/Assets/Scripts/ServerShared/MessagePackObjects/ に次のようにPlayer.csを作成する。
using MessagePack; using UnityEngine; namespace Sample.Shared.MessagePackObjects { [MessagePackObject] public class Player { [Key(0)] public string Name { get; set; } [Key(1)] public Vector3 Position { get; set; } [Key(2)] public Quaternion Rotation { get; set; } } }
ソリューションへサーバー側のプロジェクトを追加
Visual Studio上でSample.Unityを右クリックし、追加 -> 新しいプロジェクト -> .NET Core -> コンソールアプリケーション
プロジェクト名をSample.Serverに設定
場所はMagicOnionSample フォルダ 直下に置く
MagicOnion.HostingをServerにインストール
Sample.Serverを右クリック -> NuGet パッケージの管理 を選択
MagicOnion.Hostingを追加
MessagePack.UnityShims をServerにインストール
同様にMessagePack.UnityShimsをインストール
Unity側のコードを読み込む設定
Visual StudioでSample.Server.csprojを選択して右クリック -> ツール -> ファイルの編集
以下を追加
<ItemGroup> <Compile Include="..\Sample.Unity\Assets\Scripts\ServerShared\**\*.cs" LinkBase="LinkFromUnity" /> </ItemGroup>
Program.csの編集
using Grpc.Core; using MagicOnion.Hosting; using MagicOnion.Server; using Microsoft.Extensions.Hosting; using System.Threading.Tasks; namespace Sample.Server { class Program { static async Task Main(string[] args) { GrpcEnvironment.SetLogger(new Grpc.Core.Logging.ConsoleLogger()); await MagicOnionHost.CreateDefaultBuilder() .UseMagicOnion( new MagicOnionOptions(isReturnExceptionStackTraceInErrorDetail: true), new ServerPort("0.0.0.0", 12345, ServerCredentials.Insecure)) .RunConsoleAsync(); } } }
スタートアッププロジェクトを設定
Sample.Serverを選択し、右クリック -> スタートアッププロジェクトとして設定
補足
もし実行時に「開発元を確認できないため、開けません」と表示された時、次のサイトを参考にしてください
Macで「開発元を確認できないため、開けません」と表示された時の対処法 | ゴリミー
コードジェネレート
IL2CPPに対応するためにコードジェネレートする。(IL2CPPは動的なコード生成に対応していないため)
次のようなスクリプトを作成し、Editorフォルダに入れる。
#if UNITY_EDITOR using System.Diagnostics; using UnityEditor; using UnityEngine; public class MenuItems : MonoBehaviour { [MenuItem("MagicOnion/CodeGenerate")] private static void GenerateFormatters() { // Generate MagicOnion code. ExecuteMagicOnionCodeGenerator(); // Generate MessagePack code. ExecuteMessagePackCodeGenerator(); } private static void ExecuteMagicOnionCodeGenerator() { UnityEngine.Debug.Log($"{nameof(ExecuteMagicOnionCodeGenerator)} : start"); var exProcess = new Process(); var rootPath = Application.dataPath + "/../.."; var filePath = rootPath + "/GeneratorTools/MagicOnion.Generator/bin/moc"; var exeFileName = ""; #if UNITY_EDITOR_WIN exeFileName = "/win-x64/moc.exe"; #elif UNITY_EDITOR_OSX exeFileName = "/osx-x64/moc"; #elif UNITY_EDITOR_LINUX exeFileName = "/linux-x64/moc"; #else return; #endif var psi = new ProcessStartInfo() { CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, FileName = filePath + exeFileName, Arguments = $@"-i ""{rootPath}/Sample.Server/Sample.Server.csproj"" -o ""{Application.dataPath}/Scripts/Generated/MagicOnion.Generated.cs""", // Pathの「Sample.Server」と「Sample.Server.csproj」は実際のものに書き換えてください }; var p = Process.Start(psi); p.EnableRaisingEvents = true; p.Exited += (object sender, System.EventArgs e) => { var data = p.StandardOutput.ReadToEnd(); UnityEngine.Debug.Log($"{data}"); UnityEngine.Debug.Log($"{nameof(ExecuteMagicOnionCodeGenerator)} : end"); p.Dispose(); p = null; }; } private static void ExecuteMessagePackCodeGenerator() { UnityEngine.Debug.Log($"{nameof(ExecuteMessagePackCodeGenerator)} : start"); var exProcess = new Process(); var rootPath = Application.dataPath + "/../.."; var filePath = rootPath + "/GeneratorTools/mpc"; var exeFileName = ""; #if UNITY_EDITOR_WIN exeFileName = "/win/mpc.exe"; #elif UNITY_EDITOR_OSX exeFileName = "/osx/mpc"; #elif UNITY_EDITOR_LINUX exeFileName = "/linux/mpc"; #else return; #endif var psi = new ProcessStartInfo() { CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, FileName = filePath + exeFileName, Arguments = $@"-i ""{Application.dataPath}/../Assembly-CSharp.csproj"" -o ""{Application.dataPath}/Scripts/Generated/MessagePack.Generated.cs""", }; var p = Process.Start(psi); p.EnableRaisingEvents = true; p.Exited += (object sender, System.EventArgs e) => { var data = p.StandardOutput.ReadToEnd(); UnityEngine.Debug.Log($"{data}"); UnityEngine.Debug.Log($"{nameof(ExecuteMessagePackCodeGenerator)} : end"); p.Dispose(); p = null; }; } } #endif
MessagePack for C#のコードジェネレートで失敗した場合
chmod +x ./GeneratorTools/mpc/osx/mpc
のようにしてmpc
に実行権限を追加してやると上手くいくようになる。