NetworkedVar を用いた変数同期【MLAPI】

NetworkedVar を用いて変数の同期を行います。

前回記事

xrdnk.hateblo.jp

こちらの続きみたいなものです。

NetworkedVar

公式の説明はこんな感じ。

NetworkedVar is the way data can be synchronized between peers in abstracted ways.
The data can be custom containers and complex structures such as inventory structs.
(NetworkedVarは、抽象化された方法でデータをピア間で同期させることができる方法です。
データは、カスタムコンテナやインベントリ構造体などの複雑な構造体を使用することができます。)

SyncedVar との違い

NetworkedVar は SyncedVar に比べて以下の面で優れています。

  • 速度が早い
  • 書き取り、読み取り権限の制御がある
  • 変数同期の最大時間の指定が出来る

他にも優劣がありますが、ピックアップするのはこんな感じでしょうか。
NetworkedVar と SyncedVar の差異の詳細はこちらのドキュメントから。

mlapi.network

利用方法

SyncedVar と比較します。

SyncedVar の場合

using MLAPI.NetworkedVar;


... 略

    [SyncedVar]
    private bool isCubeVisible = false;

....略

    private void Update()
    {
        if (IsLocalPlayer)
        {
            isCubeVisible = Input.GetKey(KeyCode.C);
        }
        _sphere.SetActive(isCubeVisible);
    }

NetworkedVar の場合

using MLAPI.NetworkedVar;

...略

    private NetworkedVarBool isCubeVisible = new NetworkedVarBool(new NetworkedVarSettings
    {
        WritePermission = NetworkedVarPermission.Everyone
    }, false);

...略

    private void Update()
    {
        if (IsLocalPlayer)
        {
            isCubeVisible.Value = Input.GetKey(KeyCode.C);
        }
        _sphere.SetActive(isCubeVisible.Value);
    }

順に解説します。

NetworkedVar

bool 型の変数を同期させたい場合は、NetworkedVarBool または NetworkedVar と宣言します。
ここの使い方は自由ですが、BoolReactiveProperty または ReactiveProperty みたいなものですかね…。

NetworkedVarXXX 的な書き方は以下の通り他にもあります。つまり以下の型がNetworkedVarに対応していると認識できそうです。

  • NetworkedVarBool
  • NetworkedVarByte
  • NetworkedVarSByte
  • NetworkedVarUShort
  • NetworkedVarShort
  • NetworkedVarUInt
  • NetworkedVarInt
  • NetworkedVarULong
  • NetworkedVarLong
  • NetworkedVarFloat
  • NetworkedVarVector2
  • NetworkedVarVector3
  • NetworkedVarVector4
  • NetworkedVarColor
  • NetworkedVarColor32
  • NetworkedVarRay
  • NetworkedVarQuaternion

mlapi.network

コンストラク

コンストラクタは4種類宣言の仕方があります。

NetworkedVarBool()

一番簡易的な書き方です。

private bool isCubeVisible;
// 上のNetworkedVarBool 版
private NetworkedVarBool isCubeVisible = new NetworkedVarBool();

NetworkedVarBool(bool value)

初期値を設定したい場合の書き方です。

private bool isCubeVisible = false;
// 上のNetworkedVarBool 版
private NetworkedVarBool isCubeVisible = new NetworkedVarBool(false);

NetworkedVarBool(NetworkedVarSettings settings)

NetworkedVar の設定をカスタマイズすることができます。

NetworkedVarSettings

例えば以下のように設定することができます。

    private NetworkedVarBool isCubeVisible = new NetworkedVarBool(new NetworkedVarSettings
    {
        WritePermission = NetworkedVarPermission.Everyone,
        ReadPermission = NetworkedVarPermission.Everyone,
        SendTickrate = 0,
        SendChannel = "SampleChannel"
    }, false);
WritePermission

書き取り可能な権限を設定することができます。Everyone、ServerOnly、OwnerOnly、Custom の中から選べます。
デフォルトだとServerOnlyのようです。

ReadPermission

読み取り可能な権限を設定することができます。Everyone、ServerOnly、OwnerOnly、Custom の中から選べます。
デフォルトはEveryOneのようです。

SendTickrate

変数が同期される最大時間を秒単位で指定できます。
値が0の場合、変数が変更された後、できるだけ早く同期できます。
0未満、つまりマイナスの値を指定すると、スポーン時に一度だけ同期されて二度と更新されてなくなります。
デフォルトは0になっております。

SendChannel

送信するチャネルを指定できます。

github.com

mlapi.network

NetworkedVarBool(NetworkedVarSettings settings, bool value)

これまでの説明でわかる通り、第一引数でNetworkedVar設定を変えることができ、第二引数で初期値を設定できます。 今回こちらを利用します。

プロパティ

Value

NetworkedVar の値を設定する際は、 ReactiveProperty の如く、Value プロパティを通して設定する必要があります。
以下の感じ。

    private void Update()
    {
        if (IsLocalPlayer)
        {
            isCubeVisible.Value = Input.GetKey(KeyCode.C);
        }
        _sphere.SetActive(isCubeVisible.Value);
    }

動作確認

NetworkedVarBool でも同期できました。

gyazo.com

これだけだとSyncedVarの時と変わらないと色々設定を変えてみましょう。
SendTickrate を-1にしてみます。

gyazo.com

クライアント側へ同期されなくなりました…。

また、WritePermission を ServerOnly にしてみましょう。(デフォルトは ServerOnly なので記述をなくします。)
その後、クライアント側でSphereの表示をしてみます。予想では表示制御がうまくいかないはずですが…。

    private NetworkedVarBool isCubeVisible = new NetworkedVarBool(false);

左側がホスト、右側がクライアント側です。

gyazo.com

クライアント側に書き取り権限がないので、変数が同期されず、ホスト側にキューブが表示されません。
ホスト側で Debug.LogError が出てますね。クライアント側にパーミッションがないぞって怒ってます。

[MLAPI] Client wrote to NetworkedVar without permission. No more variables can be read. This is critical. NetworkId: 2 BehaviourIndex: 2 VariableIndex: 0
UnityEngine.Debug:LogError(Object)
MLAPI.Logging.NetworkLog:LogError(String)
MLAPI.NetworkedBehaviour:HandleNetworkedVarDeltas(List`1, Stream, UInt64, NetworkedBehaviour)
MLAPI.Messaging.InternalMessageHandler:HandleNetworkedVarDelta(UInt64, Stream, Action`2, PreBufferPreset)
MLAPI.NetworkingManager:HandleIncomingData(UInt64, String, ArraySegment`1, Single, Boolean)
MLAPI.NetworkingManager:HandleRawTransportPoll(NetEventType, UInt64, String, ArraySegment`1, Single)
MLAPI.NetworkingManager:Update()

よって、ホスト側に表示するためには、WritePermission を EveryOne か OwnerOnly にする必要があります。

    private NetworkedVarBool isCubeVisible =
        new NetworkedVarBool(new NetworkedVarSettings { WritePermission = NetworkedVarPermission.OwnerOnly }, false);

OwnerOnly にしてみます。

gyazo.com

無事にホスト側にも同期できるようになりました。