Unity Networking では、サーバー上のすべてのゲームオブジェクトがゲーム内のすべてのプレイヤーに見える必要はないという考えを適用しています。この考えは「関心領域」と呼ばれます。関連性がある、または、プレイヤーが興味を持つと判断されるゲームオブジェクトに対してのみ、プレイヤーは可視性を与えられます。このコンセプトは、ゲームでは「戦場の霧」、「ステルス」、「近似に基づく視界」の手法に使われています。これは、ゲーム世界がサーバー上で非常に大きい場合や、ネットワークに接続されたゲームオブジェクトが多数含まれている場合に特に重要です。プレイヤーに可視であるゲームオブジェクトのセットを減らすことで、ログイン時間や進行中の帯域幅を減らすことができます。なぜなら、プレイヤーにはそのプレイヤーが可視であるゲームオブジェクトの更新だけを送信するからです。
プレイヤーに対するゲームオブジェクトの可視性を制限する最も簡単な方法は、ビルトインの NetworkProximityChecker コンポーネントを使用することです。 これは Unity 3D 物理、または、2D 物理システムと連携して、プレイヤーが近くにあるゲームオブジェクトだけを見られるようにします。このコンポーネントは、可視性を制限したいネットワークに接続されたゲームオブジェクトのプレハブに加えて使用します。NetworkProximityChecker にはいくつかの設定可能なパラメーターがあります。visRange よりも離れた位置にあるゲームオブジェクトはプレイヤーから見ることができず、各プレイヤーが可視であるゲームオブジェクトのセットは visUpdateInterval 秒ごとに再計算されます。
ゲームオブジェクトを NetworkProximityChecker で使用するには物理コライダーを設定しなければなりません。
リモートクライアント上のプレイヤーがネットワークゲームに参加すると、そのプレイヤーが可視であるべきゲームオブジェクトのみがそのクライアントに生成されます。 したがって、プレイヤーがネットワークに接続された多くのゲームオブジェクトを持つ大きな世界に入ったとしても、世界に入った時点で見えるものは妥当な範囲に保たれます。 この処理はシーン内のネットワークに接続したゲームオブジェクトに適用されますが、アセットの読み込みには影響しません。保存されたプレハブやシーンゲームオブジェクトのアセットは読み込まれます。
プレイヤーが世界の中で移動すると、可視のゲームオブジェクトのセットが変更されます。 このような場合、クライアントはこれらの変更に関する通知を受けます。 ObjectHide
メッセージはゲームオブジェクトが可視でなくなったときにクライアントに送信されます。 このメッセージを処理するデフォルトの動作は、ゲームオブジェクトを破棄することです。ゲームオブジェクトが可視になると、オブジェクトが初めて作成された場合と同様に、クライアントは ObjectSpawn
メッセージを受信します。 したがってデフォルトでは、ゲームオブジェクトは他の生成されたゲームオブジェクトのようにインスタンス化されます。
ホストはサーバーと同じシーンを共有するため、ローカルプレイヤーに可視性のないゲームオブジェクトを破棄することはできません。 代わりに、 呼び出された NetworkBehaviour
の仮想関数を使用します。
public virtual void OnSetLocalVisibility(bool vis)
{
}
この関数は、ゲームオブジェクトのネットワークに接続されたすべてのスクリプト上で呼び出され、ホストの可視状態を変更します。これにより、各スクリプトは、HUD 要素やレンダラーを無効にするなど応答する方法をカスタマイズすることができます。 NetworkProximityChecker
のデフォルトの実装では、ゲームオブジェクト上のすべてのレンダラーコンポーネントを無効または有効にします。
NetworkProximityChecker
は、Unity Networking の public の可視インターフェースを使用して実装されています。このインターフェースを使用することで、開発者が望むすべての種類の可視性ルールを実装できます。各 NetworkIdentity は、オブジェクトを見ることができる (可視である) プレイヤーのセットを追跡します。 これらのプレイヤーはゲームオブジェクトの「観察者」と呼ばれます。
NetworkIdentity
には 1 つ関数があります。
// このゲームオブジェクトを見るプレイヤーのセットを再構築するためにこの関数を呼び出します。
public void RebuildObservers(bool initialize);
NetworkProximityChecker
は決められた時間間隔でこの関数を呼び出します。そのため、各プレイヤーが見ることができるゲームオブジェクトのセットはゲームオブジェクトが動きにしたがって更新されます。
NetworkBehaviour
には、可視範囲を決定するための仮想関数がいくつかあります。
// 新しいプレイヤーがゲームに参加するときに呼び出されます
public override bool OnCheckObserver(NetworkConnection newObserver);
// RebuildObservers が発生するときに呼び出されます
public override bool OnRebuildObservers(HashSet<NetworkConnection> observers, bool initial);
OnCheckObservers
関数は、新しいプレイヤーがゲームに参加したときに、ネットワークに接続された各ゲームオブジェクトのサーバー上で呼び出されます。 true を返す場合は、そのプレイヤーはゲームオブジェクトの観察者に加えられます。NetworkProximityChecker
は、この関数で簡単な距離の確認を行います。
RebuildObservers
が実行されると、OnRebuildObservers
関数がサーバー上で呼び出されます。この関数は、ゲームオブジェクトを見ることができるプレイヤーを観察者のセットに加えます。すると、NetworkServer
は、古い可視セットと新しい可視セットの違いに基づいて、ObjectHide
と ObjectSpawn
メッセージの送信を処理します。NetworkProximityChecker
はPhysics.OverlapSphere
を使用して、このゲームオブジェクトの可視範囲内にいるプレイヤーを検索します。
ゲームオブジェクトがプレイヤーかどうかを調べるには、 NetworkIdentity
に有効な connectionToClient
があるかどうかを確認します。以下はその例です。
var hits = Physics.OverlapSphere(transform.position, visRange);
foreach (var hit in hits)
{
// (ゲームオブジェクトが connectionToClient を持つ場合は、プレイヤーです)
var uv = hit.GetComponent<NetworkIdentity>();
if (uv != null && uv.connectionToClient != null)
{
observers.Add(uv.connectionToClient);
}
}