環境
macOS Catalina 10.15.3
Unity 2019.3.5f1
Jet Brains Rider 2019.3.4
環境構築
フォルダ作成
全体のプロジェクトを入れるためのフォルダを作成する。
ここでは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/Scripts
- MagicOnionSample/Sample.Unity/Assets/Scripts/Generated
- MagicOnionSample/Sample.Unity/Assets/Scripts/Shared
- MagicOnionSample/Sample.Unity/Assets/Plugins
- GeneratorTools (MagicOnionSampleと同じ階層に作る)
.gitignoreを編集
Pluginsフォルダ以下はGit管理の対象外とする。
.gitignoreに次の文を追加
**/Plugins/
gRPCのダウンロード
ここから、最新のビルドをクリックし、C#のカテゴリにある、grpc_unity_packageと名前が付いているものをダウンロード
ダウンロードして解凍したPluginsフォルダの中から、
- Grpc.Core
- Grpc.Core.Api
の2つをMagicOnionSample/Sample.Unity/Assets/Plugins/ の中に入れる
MessagePack for CSharp
Releases · neuecc/MessagePack-CSharp · GitHub
から
- MessagePack.Unity.x.x.xx.unitypackage
- mpc.zip
の2つをダウンロード
MessagePack.Unity.x.x.xx.unitypackage をインポート
mpcをGeneratorToolsフォルダの中に入れる。
MagicOnionをインストール
Releases · Cysharp/MagicOnion · GitHub
から
- MagicOnion.Client.Unity.unitypackage
- moc.zip
の2つをダウンロード。
MagicOnion.Client.Unity.unitypackage をインポート。
moc.zipを解凍し、GeneratorToolsフォルダの中に入れる。
サーバーへ接続するための Script の用意
MagicOnionSample/Sample.Unity/Assets/Scene/ フォルダに次のようなスクリプトを作成する。
using Grpc.Core; 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/Shared以下に置いてあるスクリプトを全て共有する設定を行う。
MagicOnionSample/Sample.Unity/Assets/Scripts/Shared/ に次のようなスクリプトを作成する。
using MessagePack; using UnityEngine; namespace Sample.Shared { [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; } } }
サーバー側の設定
サーバー用のソリューションを作成
Riderで New -> .NET Core -> Console Application
Solution NameとProject NameをSample.Serverに設定
Project DirectoryはMagicOnionSample/ 直下になるようにする。
Put solution and project in the same directoryにチェックを入れる
Create -> New window
MagicOnionをServerにインストール
Rider上でSample.Serverを右クリック -> Manage NuGet Packages
Packagesタブに切り替え、MagicOnionと検索
MagicOnion.Hostingを選択し、Sample.Serverの右の+マークをクリック
MessagePack.UnityShims のインストール
同様にMessagePack.UnityShimsをインストール
クライアントコードを共有する
Sample.Server.csprojを開いて次の文を追加する
(Sample.Server.csprojを開くには、RiderのExplolerでSample.Serverを右クリック -> Edit -> Edit Sample.Server.csproj)
<ItemGroup> <Compile Include="..\Sample.Unity\Assets\Scripts\Shared\**\*.cs" LinkBase="Shared" /> </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) { // gRPC のログをコンソールに出力するよう設定 GrpcEnvironment.SetLogger(new Grpc.Core.Logging.ConsoleLogger()); await MagicOnionHost.CreateDefaultBuilder() .UseMagicOnion( new MagicOnionOptions(isReturnExceptionStackTraceInErrorDetail: true), // エラー発生時のメッセージがコンソールに出力されるようにする new ServerPort("localhost", 12345, ServerCredentials.Insecure)) // MagicOnion サーバーが localhost:12345 で Listen する .RunConsoleAsync(); } } }
補足
もし実行時に「開発元を確認できないため、開けません」と表示された時は、
システム環境設定 -> セキュリティとプライバシー -> 一般 -> このまま許可(開く)
とする
(参考 : 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 = "/osx-x64/moc"; var psi = new ProcessStartInfo() { CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, FileName = filePath + exeFileName, Arguments = $@"-i ""{rootPath}/MagicOnionApiDemo.Server/MagicOnionApiDemo.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 = "/osx/mpc"; 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
補足
「開発元を確認できないため~~」 と表示された場合
もし実行時に「開発元を確認できないため、開けません」と表示された時は、
システム環境設定 -> セキュリティとプライバシー -> 一般 -> このまま許可(開く)
とする
(参考 : Macで「開発元を確認できないため、開けません」と表示された時の対処法 | ゴリミー)
MessagePack for C#のコードジェネレートで失敗した場合
chmod +x ./GeneratorTools/mpc/osx/mpc
のようにしてmpc
に実行権限を追加してやると上手くいくようになる。
InitialSettings スクリプトの作成
次のようなスクリプトを作成し、Assets/Scripts 以下に置いておく。
using MessagePack; using MessagePack.Resolvers; using UnityEngine; namespace Assets.Scripts { class InitialSettings { [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] static void RegisterResolvers() { // NOTE: Currently, CompositeResolver doesn't work on Unity IL2CPP build. Use StaticCompositeResolver instead of it. StaticCompositeResolver.Instance.Register( MagicOnion.Resolvers.MagicOnionResolver.Instance, MessagePack.Resolvers.GeneratedResolver.Instance, BuiltinResolver.Instance, PrimitiveObjectResolver.Instance, MessagePack.Unity.UnityResolver.Instance, MessagePack.Unity.Extension.UnityBlitWithPrimitiveArrayResolver.Instance ); MessagePackSerializer.DefaultOptions = MessagePackSerializer.DefaultOptions .WithResolver(StaticCompositeResolver.Instance); } } }