とかげ備忘録

IT系の備忘録です。

自分に合ったクラス図作成ツールを探した【UML】

はじめに

自分に合ったクラス図作成ツールを探すネットサーフィンの旅に出ました。
調査対象は有料。
できれば買い切りで欲しい。

一応たどり着いた結論

  • astah* Professional

調査

①Lucidchart

LucidchartUI

概要

お値段:月900円、年12000円
支払いタイプ:サブスク

お試しクラス図

Lucidchartのお試しクラス図

よかったこと

  • UIが見やすい、使いやすい
  • おしゃれ
  • ナビゲーションやチュートリアルが親切
    • 困ったらCtrl + Spaceしてやりたいことを検索すればすぐ使えそう
    • 例:「エクスポート」で検索かけると、実際のメニューの場所を矢印で示してくれる。
      Lucidchartのナビが親切

気になること

  • 特に不快な要素はなかった。

②Wondershare EdrawMax

EdrawMaxUI

概要

お値段:19600円
支払いタイプ:買い切り

お試しクラス図

EdrawMaxのお試しクラス図

よかったこと

  • 下のカラーパレットがおしゃれ

  • 図の折り畳み機能がある

    • 図形にアクションボタンが付いていて、これを押すと、参照元もしくは参照先をまとめて表示/非表示にできる。
    • コンパクトにまとめたいときに便利
  • 買い切りにしては安いと思う。

気になったこと

  • 矢印の配置が少し面倒くさい?
    • 2つ以上の矢印を同じ場所に繋げようとしたとき、そのまま図形から矢印線を引いた場合だと線がまとまらなかった。矢印が微妙にズレて重なって、見栄えが良くない。
      • ただし、サイドバーの図形から矢印オブジェクトを置いて繋げたらきれいに矢印がまとまった。こっちが正攻法かな?
      • (自分が操作を知らないだけの可能性はあるので、簡単にきれいに引く方法はあるかもしれない。)
  • サイドバーの図形の矢印オブジェクトの矢じりが小さくて見にくい。
    • 矢印オブジェクトも図形として登録されているが、何の矢印か見にくい。(自分の視力のせいもあるかもしれないけど・・・。)
      • 設定でサイドバーのアイコン大きくできたりするのか・・・?

③astah* Professional

astahUI

概要

お値段:30800円
支払いタイプ:買い切り

お試しクラス図

astahのお試しクラス図

よかったこと

  • 操作が直観的で作るのが簡単だった。
    • 画面内でダブルクリックするだけで、クラス図がポンポン作れる。
      • 変数、メソッドの初期構文のないシンプルなクラス図が作れる。
      • 配置した図形から矢印の種類などが直接選択できたり、同じ場所を参照する矢印線もあとで簡単にまとめられた。
      • 各変数、メソッドは1行ずつ挿入、削除できる

気になったこと

  • 特に不快な要素はなかった。

おわりに

3年使えば元が取れる!

Oculus Quest 2でPCに無線接続する

はじめに

Oculus Quest 2でPCに無線接続する方法を記す。
最終目的はSteamVRを触ること。
私の知る限り下記2パターンのやり方がある。

方法1.Virtual Desktop を使う方法

有料アプリのアレを使うパターン。
(2000円くらい)

www.oculus.com

手順(SteamVRを遊ぶまで)

↓これの手順にそってやればOK(*一部スキップ箇所あり)

参考:oculus quest 2 - SteamVRを無線で利用する - コトバノウタカタ

*「Virtual Desktop VR Patchを入れる」のところはスキップした。
(現在はもう入れなくていいようになっている。)

方法2.Oculus Air Link を使う方法

公式の説明: https://support.oculus.com/363042741730476/?locale=ja_JP

手順

①OculusのPCアプリをインストール

https://www.oculus.com/rift/setup/

②PC側の設定

[設定]→[ベータ]→Air Link を オン

f:id:ttokage2233:20210523034209p:plain

③Quest2側の設定

ユニバーサルメニューから
[設定]→[テスト機能]→Air Link をオン

f:id:ttokage2233:20210523034414p:plain

クイックアクションからOculusAirLinkの項目を押して、

f:id:ttokage2233:20210523110452p:plain

ペアリング & 接続すればOK

f:id:ttokage2233:20210523034508p:plain

バーチャルデスクトップはメニューから押せば開ける。

f:id:ttokage2233:20210523034545p:plain

④PCのSteamVRを遊ぶ場合

PCのOculusアプリの
[設定]→[一般]から
提供元不明 にチェックを入れる。

f:id:ttokage2233:20210523034640p:plain

おわりに

私の場合、PCの接続目的がSteamVRをやることだけなので、
普段使いは「Virtual Desktop」だと思う。

理由は、PC側のアプリが自動起動しているのですぐ繋げるから。
(AirLinkは、24時間使用されていないと自動でオフになってしまうみたい。)

Air Linkは、無料 & ホーム画面でいろいろ遊べるから触ってみる価値はあると思う。

AWSのまだ動いていたサービスを調べて削除する

はじめに

AWSにて、 使用していたサービスを覚えているものは片っ端から削除したが、 1か月経って、まだ課金されているサービスがあったので、調べた。

内容

使用をやめるときにAWSのアクティブなサービスを削除していくのだが、 いざ削除しようと思ったときに、 何のサービスを使ったか、何に紐づけられているか把握しておくのは、きつい。

なのでその使用サービス一覧を見て対処していくのがよい?

AWS Systems Managerで使用しているサービス一覧を調べる

公式ドキュメント docs.aws.amazon.com

ナビゲーションメニューより、 ▼変更管理 → 自動化 に遷移

オートメーション実行で AWSSupport-ListEC2Resources を検索して →  それを選択して次へ

f:id:ttokage2233:20210411234739p:plain

f:id:ttokage2233:20210411234802p:plain

シンプルな実行

タグでフィルタリングできるみたいだが、 個人でそんなにサービス立ち上げていたわけではないので、

そのまま「シンプルな実行」で実行する。

実行結果を見る

「出力」を確認。

私の中ではすべてサービス終了させていたはずなので、 ほぼ、No Resources Foundが出力されたが、 一か所Elastic IPで動いているサービスが残っていた。

このアドレスを開放するには、このURLからできますよ。という案内も出力してくれるので 助かる。

そこのサービスを見に行って、削除した。めでたし

おわりに

これで来月は請求がなくなるはず。

追記 (2022/04/09)

何かRDSのスナップショットデータが残っていたらしく、15円ほど請求された。 気づかねーよこんなのw

RDSのページ → スナップショット → 残っていたやつを削除

UnityでVRアプリをビルドして試してみる

はじめに

UnityでOculus Quest 2向けの環境設定を行って、VRアプリをビルドして実機で確認するまでの流れ

  • Unity:2019.4.15.f1
  • VR機器:Oculus Quest 2

手順

1.アセットストアからOculus Integrationを導入

assetstore.unity.com

これを入れる。

2.Build SettingsでPlatformをAndroidにする。

[Texture Compression (テクスチャー圧縮)]を[ASTC]に設定します。

3.Project Settingsより、XRSettings → Virtual Reality Supportedにチェックを入れる

入れ子になった下の方のチェックは勝手に付いていた。よくわからん。)

f:id:ttokage2233:20210411230011p:plain

4.Graphics APIsの「Vulkan」を消してね。とのエラーが出たので。これも消す。

Error building Player: BuildFailedException: XR is currently not supported when using the Vulkan Graphics API. Please go to PlayerSettings and remove 'Vulkan' from the list of Graphics APIs.

f:id:ttokage2233:20210411230529p:plain

5.Oculus Quest 2を接続してRun Deviceでデバイスを指定する。

f:id:ttokage2233:20210411230956p:plain

6.ビルドシーンについて

アセット付属のDemoシーンをビルドしてもいいし、 自作のシーンをビルドしてもいい。(←自作の場合は、とりあえずアセット付属のVR用のカメラをシーンに配置しておけばOK)

7.Build and Runを押す

ビルド後、実機確認ができる。

8.もう一度そのアプリを確認するには

Oculus Quest 2起動後のホーム画面で、 右手のコントローラーのOculusのマーク?を押して、 メニュー画面 → アプリを押す。 アプリ画面の右上のところの「すべて」を 「提供者不明」に変えると、先ほど実機で実行したアプリが表示される。

9.実機確認したやつ

10.おわりに

はい終わり

【光回線】おてがる光契約したよ。の話

はじめに

2020/09/25現在
契約して2週間くらい経ちました。
こういうのって情報あんまり出てないと思ったから書いておこうと思う。

使用感は良い。

オプション

付けたオプションは2つ。そのうち1つはぶっちゃけ強制だけど。

↑契約前の問い合わせで確認済み。

速度

テキトーに計測

wifi

土日のお昼過ぎ頃

f:id:ttokage2233:20200925005631p:plain:w300 f:id:ttokage2233:20200925005645p:plain:w300

有線LAN

ケーブルはCAT7のLANケーブル使用。

平日の夜中0時過ぎころ
f:id:ttokage2233:20200925005724p:plain f:id:ttokage2233:20200925005731p:plain

以上。

アセットストアのアセットのダウンロード先フォルダを変更する

割と記事は出ているけど自分用にメモ

目的

Cドライブが圧迫されていたので、保存先をDドライブの方に変更したい。
Cドライブの容量を少しでも軽くしてあげたい。

やること

1.CドライブにあるアセットのフォルダをDドライブに移動

f:id:ttokage2233:20200925000754p:plain
CドライブのアセットフォルダをDドライブに変更

2.Cドライブから、Dドライブの方へジャンクションを作成する。

コマンドプロンプト開いて 、ジャンクションを作成する。

mklink /j "C:\Users\<user_name>\AppData\Roaming\Unity\Asset Store-5.x" "D:\Unity\Asset Store-5.x"

f:id:ttokage2233:20200925002728p:plain
ジャンクション作成

はいできた。

MagicOnionを使ってリアルタイム通信を試す。【Unity】

はじめに

1年ほど前に使ったことがあったので、 久しぶりに導入してみたら躓いたので、 記録として残しておきます。

とりあえず覚えながら作ってみたやつ

MagicOnionについて

Web API ライクな通信や、リアルタイム通信ができるフレームワーク

特徴

サーバー側もクライアント側もC#で書ける。
gRPCを使用。(HTTP/2や、Protocol Buffersを使っていて、高速)
MessagePack for C#を使用。(LZ4で圧縮されてサイズが小さく、高速)
フィルタ機能を持ち、多段に重ねて処理を行うことができる。 ←この様子がMagicOnionの由来だとか
(↑通信の前後に追加の処理を行うことができる。)


色々調べていたら、チャットとか、マルチプレイを実現できそうなものとして、下記のようなものもありました。

  • SignalR

  • Photon(PUN2)

MagicOnionを選んだ理由は、1度勉強会で扱ったことがあるからです。

使うイメージ

クライアント側とサーバー側が共有するインターフェースを用意して、 それぞれ実装します。 互いのメソッドを呼び出してあげれば通信できます。

f:id:ttokage2233:20200425235331p:plain

準備

  • Unity

2018.4.2f1

各種ダウンロード

ダウンロードファイルの***.zipファイルですが、MagicOnionをIL2CPP環境で使う場合に使用します。 この対応については、最後の方に後述します。

MagicOnion

https://github.com/cysharp/MagicOnion/releases

バージョン

3.0.11

取得するファイル

  • MagicOnion.Client.Unity.unitypackage

  • moc.zip

gRPC

https://packages.grpc.io/

バージョン

2.26.0


https://packages.grpc.io/archive/2019/11/b5e0d5e0443e229841225a8727f5fb268544953f-18403aac-451d-4f74-8850-c2747419fe76/index.xml

取得するファイル

  • grpc_unity_package.2.26.0-dev.zip


その時最新だった2.29.0で試したが、VisualStudioでプロジェクト作成して作業しようとしたら、「予期せぬエラーです。」と表示されてしまった。
分からなかったので、このバージョンに落とした。

もしかしたら、System.Memory.dllバージョンが噛み合ってないからだろうか・・・。
https://github.com/grpc/grpc/issues/21908

↑2.26.0で動いたというコメントがあったので、このバージョンを使用した。

MessagePack for C#

https://github.com/neuecc/MessagePack-CSharp/releases

バージョン

2.1.90

取得するファイル

  • MessagePack.Unity.2.1.90.unitypackage

  • mpc.zip

導入

Unityの設定変更

「File」→「Build Settings」から、 「Player Settings...」 を押す。

ビルド対象OSの 「Other Settings」項目 → 「Configuration」項目の

Api Compatibility Level」 → .NET 4.x 「Allow 'unsafe' Code」 → チェック

に設定する。

f:id:ttokage2233:20200426000150p:plain

用意したファイルのインポート

Unityプロジェクトを立ち上げ、**.unitypackageのファイルをインポートします。

  • MagicOnion.Client.Unity.unitypackage

  • MessagePack.Unity.2.1.90.unitypackage

f:id:ttokage2233:20200426000713p:plain f:id:ttokage2233:20200426000725p:plain

ファイルの競合

導入時に、Assets/Plugins/ 直下の

System.Buffers
System.Memory
System.Runtime.CompilerServices.Unsafe
System.Threading.Tasks.Extensions

上記のファイルが競合するので、
名前を変えて、競合を回避する。
なんか消すのが怖かったので、実際どうなんだろう・・・。

これらを行えば、とりあえずUnity Editor上のエラーは消えた。

ひとまずテキトーにスクリプトを開いてVisual Studioを立ち上げる。

VisualStudioの設定

VisualStudioに.Net Core SDKとランタイムをインストールしていない場合は、インストールしておきます。 私の環境だと入っていたので、多分この辺りを確認すればよいと思います。

f:id:ttokage2233:20200426010710p:plain

f:id:ttokage2233:20200426010421p:plain f:id:ttokage2233:20200426010441p:plain

クライアント側の用意

特になし

サーバー側の用意

Unityのソリューションから右クリックで、
新規のプロジェクトを作成する。

f:id:ttokage2233:20200426013314p:plain f:id:ttokage2233:20200426013646p:plain

サーバー側にパッケージをインストールする。

  • MagicOnion.Hosting

  • MessagePack.UnityShims

f:id:ttokage2233:20200426012156p:plain f:id:ttokage2233:20200426012356p:plain 図:パッケージインストール例

(今思えば、これらのパッケージを参考にクライアント側のバージョンを合わせてダウンロードすればよかったのでは?と思う自分であった。)

クライアント - サーバー間の共有ファイルの設定

サーバー側のプロジェクトファイルを編集して、共有するフォルダの設定を行います。

  • クライアント側

f:id:ttokage2233:20200426014214p:plain

  • サーバー側

サーバー用プロジェクトの設定に、
Unityプロジェクトの共有用フォルダのパスを指定します。
f:id:ttokage2233:20200426015506p:plain

クイックスタートをやってみる

GitHubに載ってたクイックスタートを参考にやってみる。
https://github.com/cysharp/MagicOnion

サーバーのスタート処理

  • Program.cs(サーバー側)
using System;
using Grpc.Core;
using MagicOnion.Server;

namespace MagicOnionDemoServer
{
    class Program
    {
        static void Main(string[] args)
        {
            GrpcEnvironment.SetLogger(new Grpc.Core.Logging.ConsoleLogger());

            // setup MagicOnion and option.
            var service = MagicOnionEngine.BuildServerServiceDefinition(isReturnExceptionStackTraceInErrorDetail: true);

            var server = new global::Grpc.Core.Server
            {
                Services = { service },
                Ports = { new ServerPort("localhost", 12345, ServerCredentials.Insecure) }
            };

            // launch gRPC Server.
            server.Start();

            // and wait.
            Console.ReadLine();
        }
    }
}

API通信

コーディング

共有するインターフェースを作成する。

  • IMyFirstService.cs
using Grpc.Core;
using MagicOnion;
using MagicOnion.Server;
using System;

namespace ServerShared.Services {
    public interface IMyFirstService : IService<IMyFirstService>
    {
        /// <summary>
        /// 足し算を行う
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        UnaryResult<int> SumAsync(int x, int y);
    }
}

サーバー側実装

  • MyFirstService.cs
using System.Collections.Generic;
using System.Text;
using Grpc.Core;
using MagicOnion.Hosting;
using MagicOnion;
using MagicOnion.Server;
using ServerShared.Services;

    class MyFirstService : ServiceBase<IMyFirstService>, IMyFirstService
    {
        public async UnaryResult<int> SumAsync(int x, int y)
        {
            Logger.Debug($"Received:{x}, {y}");
            return x + y;
        }
    }

クライアント側実装

  • ApiConnectionTest.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Grpc.Core;
using MagicOnion.Client;
using ServerShared.Services;

public class ApiConnectionTest : MonoBehaviour
{
        async void Start() {
        // standard gRPC channel
        var channel = new Channel("localhost", 12345, ChannelCredentials.Insecure);

        // get MagicOnion dynamic client proxy
        var client = MagicOnionClient.Create<IMyFirstService>(channel);

        // call method.
        var result = await client.SumAsync(100, 200);
        Debug.Log("Client Received:" + result);
    }
}

動作確認

サーバー側のプロジェクトをスタートアッププロジェクトに設定し、
プログラムを実行します。

f:id:ttokage2233:20200426025149p:plain f:id:ttokage2233:20200426030111p:plain

クライアント側は、 空のGameObjectを作成して、ApiConnectionTest.csをアタッチして実行します。

f:id:ttokage2233:20200426025857p:plain

f:id:ttokage2233:20200426030230p:plain

通信できました。

リアルタイム通信

コーディング

インターフェースを作成

  • IGamingHub.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MagicOnion;
using ServerShared.MessagePackObjects;
using UnityEngine;

namespace ServerShared.GamingHub
{
    /// <summary>
    /// クライアント → サーバー 処理
    /// </summary>
    public interface IGamingHub : IStreamingHub<IGamingHub, IGamingHubReceiver>
    {
        /// <summary>
        /// 入室処理
        /// </summary>
        /// <param name="roomName"></param>
        /// <param name="userName"></param>
        /// <param name="position"></param>
        /// <param name="rotation"></param>
        /// <returns></returns>
        Task<Player[]> JoinAsync(string roomName, string userName, Vector3 position, Quaternion rotation);

        /// <summary>
        /// 退出処理
        /// </summary>
        /// <returns></returns>
        Task LeaveAsync();

        /// <summary>
        /// 移動処理
        /// </summary>
        /// <param name="position"></param>
        /// <param name="rotation"></param>
        /// <returns></returns>
        Task MoveAsync(Vector3 position, Quaternion rotation);
    }

    /// <summary>
    /// サーバー → クライアント 処理
    /// </summary>
    public interface IGamingHubReceiver
    {
        /// <summary>
        /// 入室を接続クライアント全員に通知
        /// </summary>
        /// <param name="player"></param>
        void OnJoin(Player player);

        /// <summary>
        /// 退出を接続クライアント全員に通知
        /// </summary>
        /// <param name="player"></param>
        void OnLeave(Player player);

        /// <summary>
        /// 移動したことを接続クライアント全員に通知
        /// </summary>
        /// <param name="player"></param>
        void OnMove(Player player);
    }
}

サーバー側実装

  • GamingHub.cs
using System;
using System.Collections.Generic;
using System.Text;
using MagicOnion;
using MagicOnion.Server.Hubs;
using Grpc.Core;
using ServerShared.MessagePackObjects;
using ServerShared.GamingHub;
using System.Threading.Tasks;
using UnityEngine;
using System.Linq;

namespace MagicOnionDemoServer
{
    public class GamingHub : StreamingHubBase<IGamingHub, IGamingHubReceiver>, IGamingHub
    {
        IGroup room;
        Player self;
        IInMemoryStorage<Player> storage;

        public async Task<Player[]> JoinAsync(string roomName, string userName, Vector3 position, Quaternion rotation)
        {
            self = new Player() { Name = userName, Position = position, Rotation = rotation };

            // Group can bundle many connections and it has inmemory-storage so add any type per group. 
            (room, storage) = await Group.AddAsync(roomName, self);

            // Typed Server->Client broadcast.
            Broadcast(room).OnJoin(self);

            return storage.AllValues.ToArray();
        }

        public async Task LeaveAsync()
        {
            await room.RemoveAsync(this.Context);
            Broadcast(room).OnLeave(self);
        }

        public async Task MoveAsync(Vector3 position, Quaternion rotation)
        {
            self.Position = position;
            self.Rotation = rotation;
            Broadcast(room).OnMove(self);
        }

        /// <summary>
        /// 切断処理
        /// </summary>
        /// <returns></returns>
        protected override ValueTask OnDisconnected()
        {
            // on disconnecting, if automatically removed this connection from group.
            return CompletedTask;
        }
    }
}

クライアント側実装

  • GamingHubClient.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Grpc.Core;
using MagicOnion.Client;

using ServerShared.GamingHub;
using ServerShared.MessagePackObjects;
using UnityEngine;

public class GamingHubClient : IGamingHubReceiver
{
    Dictionary<string, GameObject> players = new Dictionary<string, GameObject>();

    IGamingHub client;

    public async Task<GameObject> ConnectAsync(Channel grpcChannel, string roomName, string playerName)
    {
        client = StreamingHubClient.Connect<IGamingHub, IGamingHubReceiver>(grpcChannel, this);

        var roomPlayers = await client.JoinAsync(roomName, playerName, Vector3.zero, Quaternion.identity);
        
        /* 今いるプレイヤーの生成(自分も含めて生成される)
        foreach (var player in roomPlayers)
        {
            (this as IGamingHubReceiver).OnJoin(player);
        }
        */

        return players[playerName];
    }

    // methods send to server.

    public Task LeaveAsync()
    {
        return client.LeaveAsync();
    }

    public Task MoveAsync(Vector3 position, Quaternion rotation)
    {
        return client.MoveAsync(position, rotation);
    }

    // dispose client-connection before channel.ShutDownAsync is important!
    public Task DisposeAsync()
    {
        return client.DisposeAsync();
    }

    // You can watch connection state, use this for retry etc.
    public Task WaitForDisconnect()
    {
        return client.WaitForDisconnect();
    }

    // Receivers of message from server.

    void IGamingHubReceiver.OnJoin(Player player)
    {
        Debug.Log("Join Player:" + player.Name);

        var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        cube.name = player.Name;
        cube.transform.SetPositionAndRotation(player.Position, player.Rotation);
        players[player.Name] = cube;
    }

    void IGamingHubReceiver.OnLeave(Player player)
    {
        Debug.Log("Leave Player:" + player.Name);

        if (players.TryGetValue(player.Name, out var cube))
        {
            GameObject.Destroy(cube);
        }
    }

    void IGamingHubReceiver.OnMove(Player player)
    {
        Debug.Log("Move Player:" + player.Name);

        if (players.TryGetValue(player.Name, out var cube))
        {
            cube.transform.SetPositionAndRotation(player.Position, player.Rotation);
        }
    }
}
  • RealTimeConnectionTest.cs

テキトーなGameObjectを作成して、アタッチします。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using Grpc.Core;
using ServerShared.GamingHub;

public class RealTimeConnectionTest : MonoBehaviour
{
    public static GamingHubClient gamingHubClient;
    Channel channel;
    async void Start()
    {

        this.channel = new Channel("localhost:12345", ChannelCredentials.Insecure);

        RealTimeConnectionTest.gamingHubClient = new GamingHubClient();

        await gamingHubClient.ConnectAsync(channel, "SampleRoom", "tarou");
    }

}

動作確認

API通信と同様、サーバー側を実行しておいて、 クライアント側を実行します。

うまくいけば、四角いプレイヤーオブジェクトが生成されます。 これに、プレイヤーを動かすスクリプトを実行中にアタッチして、 確認してみます。

  • PlayerController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{

    float speed = 3f;
    Vector3 pos, currentPos;

    void Update()
    {
        Move();
    }
    
    void Move()
    {
        pos = transform.position;
        currentPos = pos;

        if (Input.GetKey("left"))
        {
            pos.x -= speed * Time.deltaTime;
        }
        if (Input.GetKey("right"))
        {
            pos.x += speed * Time.deltaTime;
        }
        if (Input.GetKey("up"))
        {
            pos.y += speed * Time.deltaTime;
        }
        if (Input.GetKey("down"))
        {
            pos.y -= speed * Time.deltaTime;
        }

        if (currentPos == pos) //値が変わらなかったら何もしない
        {
            return;
        }
        //サーバーを通して移動できるか確認したいので、コメントアウト
        //transform.position = pos;

        //移動情報送信
        RealTimeConnectionTest.gamingHubClient.MoveAsync(pos, transform.rotation);
    }

}

f:id:ttokage2233:20200426141854j:plain ↑*静止画です
移動はガタガタですが、情報のやりとりができました。

IL2CPP対応

MagicOnionをIL2CPP環境で使う場合は、事前のコードジェネレートが必要になります。
mpc.zipとmoc.zipファイルの中にコードジェネレートのための実行ファイルがあるので、
それを設定します。

minamiさんの記事が参考になりました。

  • Unity+.NET Core+MagicOnionの環境構築ハンズオン

https://qiita.com/_y_minami/items/c7899fdf1db505c06ba2

その中のMenuItems.csを、こちらが使うファイルパスに変更して、InitialSettings.csは下記のように設定してみました。
(このあたりのインスタンス登録処理は手探り状態で、どれを登録したらよいか、よくわかっていない。)

  • InitialSettings.cs
using MagicOnion.Resolvers;
using MessagePack.Resolvers;
using MessagePack.Unity;
using MessagePack;
using UnityEngine;

class InitialSettings
{
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    static void RegisterResolvers()
    {

        StaticCompositeResolver.Instance.Register(

                UnityResolver.Instance,
                MagicOnionResolver.Instance,
                GeneratedResolver.Instance,
                BuiltinResolver.Instance,
                PrimitiveObjectResolver.Instance
        );

        var options = MessagePackSerializerOptions.Standard.WithResolver(StaticCompositeResolver.Instance);

        MessagePackSerializer.DefaultOptions = options;

    }
}

MagicOnionResolver.Instance、GeneratedResolver.Instanceあたりは、
はじめは参照エラーだったが、
コードジェネレートした後に確認したら、参照エラーが解決していた。

さいごに

Taskや、await/asyncなどの理解をもう少し深めようと思った。
設計って難しい。
ここの処理はクライアント側orサーバー側に持たせる。とか
レスポンス速度これくらいで大丈夫かな。とか
通信が途中で切断したときどうしよう。とか
そういうところ意識しないとな。

参考

  • MagicOnion入門

https://www.slideshare.net/torisoup/magiconion-174973732

https://tech.cygames.co.jp/archives/3181/

  • Unity+.NET Core+MagicOnionの環境構築ハンズオン

https://qiita.com/_y_minami/items/c7899fdf1db505c06ba2