読者です 読者をやめる 読者になる 読者になる

tanaka's Programming Memo

プログラミングについてのメモ。

Unity5.1 ネットワークシステム Object Visibility

前へ | 次へ

UNet Unity5.1からの新しいネットワークシステム
Unity5.1のネットワークマニュアル斜め読み(2)
UNet NetworkManagerの利用
Unity5.1 ネットワークシステムのオブジェクト生成
Unity5.1 ネットワークシステムの状態同期
Unity5.1 ネットワークシステムのRemote Actions
Unity5.1 ネットワークシステム PlayerObjects
Unity5.1 ネットワークシステム Object Visibility
Unity5.1 ネットワークシステム Network Messages
Unity5.1 ネットワークシステム Matchmaker
Unity5.1 ネットワークシステム Scene Objects
Unity5.1 ネットワークシステム:シングルプレイヤーゲームを多人数に対応させる
Unity5.1 ネットワークシステム Multiplayer Lobby
Unity5.1 ネットワークシステム Network Clients and Servers
Unity5.1 ネットワークリファレンス概要

公式サイトの以下のページの斜め読みメモです。
Unity - マニュアル: Object Visibility

途中に差し込んでいるソースコードは公式サイトからの転載です。

Object Visibility

UNetは、サーバー上の全てのオブジェクトが、ゲーム内の全てのキャラクターから見えなくてもよい、という考え方を実現できます。これは"Area of Interest"(興味あるものの範囲)などと呼び、プレイヤーにはゲームプレイに関連したり、面白さを提供すると判断したオブジェクトのみが見えるようにできます。Fog Of War(プレイヤーから見えるようになるまで敵や地形を隠すシステム)や、ステルス、隣接しないと見えないようなオブジェクトなど、いくつかのゲームシステムにこの機能が利用できます。これは特にサーバー上のゲームフィールドが広大であったり、多くのネットワークオブジェクトが存在する場合に重要です。プレイヤーに見えるオブジェクトを制限して、プレイヤーに見えるオブジェクトへのデータ更新のみにすれば、ログイン時間や通信量を削減できます。

ネットワークの近さの確認(NetworkProximityChecker)

プレイヤーが見えるオブジェクトを削減する最も簡単な方法は、組み込みのNetworkProximityCheckerコンポーネントを利用することです。このコンポーネントは3D Physicsや2D Physicsシステムと一緒に動作して、プレイヤーに接近して見えるようになったオブジェクトのみを有効にします。このコンポーネントを利用するには、表示を抑制したいネットワークオブジェクトのプレハブにこのコンポーネントを追加します。NetworkProximityCheckerはいくらかの設定パラメータがあります。"Vis Range"に設定した距離より離れたオブジェクトはプレイヤーから見えなくなります。また、"Vis Update Interval"に設定した秒数ごとに、プレイヤーから見えるオブジェクトが再計算されて更新されます。

NetworkProximityCheckerを動作させるオブジェクトにはなんらかのPhysics Colliderを設定する必要があります。

リモートクライアント上での表示(Visibility on Remote Clients)

リモートのクライアントがネットワークゲームに参加すると、そのプレイヤーに見えるオブジェクトのみがそのクライアントにspawnされます。そのため、ゲームフィールドが広大で大量のネットワークオブジェクトが存在するゲームに参加する場合でも、参加時にそれほど待たされずに済みます。これはシーン内のネットワークオブジェクトでも同様ですが、登録するプレハブや、シーンのオブジェクトなどのアセットを読み込む時間は削減されません。

ゲームワールド内でのプレイヤーの移動によって、オブジェクトの表示設定は変化します。これらの変化はクライアントに報告されます。オブジェクトが見えなくなると、クライアントにObjectHideメッセージが送信されます。このメッセージに最初に設定されている動作はオブジェクトをdestroyすることです。オブジェクトが見えるようになると、クライアントはObjectSpawnメッセージを受信します。オブジェクトが最初に作成された時も同様です。その後、最初に設定されている動作によって、他のオブジェクトと同様に生成してspawnされます。

ホスト上での表示(Visibility on the Host)

ホストはサーバーと同じシーンを共有しているので、ローカルプレイヤーから見えなくなったオブジェクトを削除することはできません。削除する代わりに、NetworkBehaviour上の仮装関数が呼ばれます。

public virtual void OnSetLocalVisibility(bool vis)
{
}

この関数は、ホスト上で見えるかどうかの状態が変更されたオブジェクトに設定されている全てのネットワークスクリプト上で呼び出されます。これにより、各スクリプトにHUDを消したり、描画したりするような処理を設定することができます。NetworkProximityCheckerに最初に設定されている動作は、オブジェクト上の全ての描画コンポーネントを無効にしたり、有効にすることです。

Custom Visibility

NetworkProximityCheckerはUNetのpublicなインターフェースを使って実装されています。このインターフェースを使えば、開発者は自らが設計した表示の判定を使うことができます。NetworkIdentityごとにプレイヤーから見えるかどうかを監視できます。これらはオブジェクトの"observers"(監視者)と呼びます。

NetworkIdentity上の関数の一つを挙げます。

// call this to rebuild the set of players observing this object
public void RebuildObservers(bool initialize);

NetworkProximityCheckerは決まった時間間隔でこの関数を呼び出します。そして、プレイヤーごとの表示オブジェクトが動きに合わせて更新されて設定されます。

NetworkBehaviourに、表示を決めるための仮装関数がいくつか用意されています。

// called when a new player enters the game(ゲームに新しいプレイヤーが参加した時に呼ばれます)
public override bool OnCheckObserver(NetworkConnection newObserver);

// called when RebuildObservers is invoked (RebuildObserverが呼ばれた時に呼ばれます)
public override bool OnRebuildObservers(HashSet<NetworkConnection> observers, bool initial);

OnCheckObservers関数は、ゲームに新しいプレイヤーが参加した時に、ネットワークオブジェクトごとにサーバー上で呼び出されます。trueを返すと、そのプレイヤーはオブジェクトに監視者として追加されます。NetworkProximityCheckはこの関数の実装内で簡単な距離チェックを実行します。

OnRebuildObservers関数は、RebuildObservers()が呼び出された時にサーバー上で呼び出されます。この関数は、そのオブジェクトを見ることができるプレイヤーをobserversに追加するためのものです。NetworkServerは古い表示セットと新しい表示セットの違いをチェックして、ObjectHide()やObjectSpawn()メッセージを送信します。NetworkProximityCheckerはPhysics.OverlapSphere()を利用して、このオブジェクトから見えるプレイヤーを見つけます。

対象のオブジェクトから見える、有効なNetworkIdentityインスタンスの"connectionToClient"を持っているプレイヤーをobserversに追加する例を以下に挙げます。

    var hits = Physics.OverlapSphere(transform.position, visRange);
    foreach (var hit in hits)
    {
        // (if an object has a connectionToClient, it is a player)
        var uv = hit.GetComponent<NetworkIdentity>();
        if (uv != null && uv.connectionToClient != null)
        {
            observers.Add(uv.connectionToClient);
        }
    }


前へ | 次へ