MagicOnion環境構築(Visual Studio for Mac)パターンA

環境

環境構築

フォルダ作成

全体のプロジェクトを入れるためのフォルダを作成する。

ここではMagicOnionSampleとする

Unityプロジェクト作成

MagicOnionSampleフォルダの中にUnityのプロジェクトを作成する。

プロジェクト名をここではSample.Unityとする。

PlayerSettings

  • APICompatibilityLevel.NET4.x に変更する(全てのプラットフォームで設定する)

  • Allow unsafe Code にチェックをいれる

  • Scripting Define SymbolsENABLE_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のダウンロード

https://packages.grpc.io

ここから、最新のビルドをクリックし、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 StudioSample.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に実行権限を追加してやると上手くいくようになる。

参考