Unet は、必ずしもサーバー上のすべてのオブジェクトがすべてのプレイヤーに対して表示されるべきではないという概念を理解しています。これは “Area of Interest” と呼ばれることがあります。つまり、各プレイヤーから見て、どのオブジェクトに関連性や関心があるかをゲーム側で判断し、各プレイヤーごとに、見えるオブジェクトを変えることができます。Fog Of War、Stealth といったゲームはこの概念を利用した作品の例です。また、近接度によって変化する表示方法もこの一例です。ゲーム世界がサーバーに占める割合が大きい場合やネットワークオブジェクトが多く含まれている場合、これが特に重要になります。プレイヤーに対して表示されるオブジェクトの数を減らせば、更新も表示されているオブジェクトに関わるものだけで済み、ログイン時間や継続的なデータ処理量の削減につながります。
プレイヤーに対するオブジェクト表示を制限するための最も簡単な方法は、ビルトインの NetworkProximityChecker コンポーネントを使用することです。これは Unity の 3D フィジックス や 2D フィジックスのシステムと連携して機能し、プレイヤーに近接したオブジェクトのみを表示するようにするものです。このコンポーネントを使用するには、表示を制限したいネットワーク オブジェクトのプレハブにこれを追加してください。NetworkProximityChecker にはいくつかの設定可能なパラメーターがあります。“Vis Range” よりも遠くにあるオブジェクトはプレイヤーから非表示になり、各プレイヤーに対して表示されるオブジェクトは、“Vis Update Interval” に設定された秒数ごとに再計算されます。
オブジェクトは物理コライダーを持っていないと NetworkProximityChecker と連携機能しません。
リモートクライアント上のプレイヤーがネットワークゲームに参加すると、そのプレイヤーに対して表示されるオブジェクトのみがそのクライアント上に生成されます。そのため、ネットワーク オブジェクトが沢山ある大きな世界にプレイヤーが参加した場合でも、参加にかかる時間を妥当な長さに抑えられます。これはシーン内のネットワーク オブジェクトに適用されるもので、アセットのローディングには影響しません。登録されたプレハブやシーンオブジェクトのアセットはロードされます。
プレイヤーが世界の中を移動すると、表示されるオブジェクト一式もそれに応じて変化し、その変更がクライアントに伝えられます。あるオブジェクトが見えなくなると、ObjectHide メッセージがクライアントに送られます。このメッセージへのデフォルト対応は、オブジェクトの破棄です。オブジェクトが表示されると、クライアントはオブジェクトの初回作成時と同様、ObjectSpawn メッセージを受け取ります。したがってそのオブジェクトはデフォルトでは、生成されたその他のオブジェクトと同様にインスタンス化されます。
ホストはサーバーと同じシーンを共有しているため、ローカルプレイヤーに対してオブジェクトが非表示になっていてもそれを破棄することはできません。代わりに、NetworkBehaviour の仮想関数が実行されます。
public virtual void OnSetLocalVisibility(bool vis)
{
}
この関数は、ホスト上で表示状態が変化するオブジェクトのすべてのネットワーク スクリプトで実行されます。これにより、それぞれのスクリプトで反応をカスタマイズすることが可能になります。(例えば HUD 要素やレンダラーを無効化する等。) NetworkProximityChecker のデフォルト実装では、オブジェクトのすべての Renderer コンポーネントが有効化あるいは無効化されます。
NetworkProximityChecker は、Unity Networking のパブリックの表示インターフェースを使って実装されています。このインターフェースを使用すれば開発者は、表示に関するどんな規則も思いのままに実装することができるでしょう。各 NetworkIdentity は、それがどのプレイヤーに対して表示されるべきかを把握しています。こういったプレイヤーは、オブジェクトの「オブザーバー (observer)」と呼ばれます。
NetworkIdentity には関数がひとつあります。
// オブジェクトを監視するプレイヤーを再作成するためにこれを呼び出します
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 を返すと、そのプレイヤーがオブジェクトのオブザーバーとして追加されます。NetworkProximityCheck は、この関数の実行に際して簡単な距離の確認を行います。
OnRebuildObservers 関数は RebuildObservers が実行されるとサーバー上で呼び出されます。この関数は、オブジェクトを見ることができる各プレイヤーとオブザーバー一式が共に追加されることを前提に機能します。その上で NetworkServer が、古い表示一式と新しい表示一式の差を基に、ObjectHide および ObjectSpawn メッセージの送信を行います。NetworkProximityChecker は Physics.OverlapSphere() を使用してオブジェクトの表示距離内にいるプレイヤーを見付けます。
(注)あるオブジェクトがプレイヤーであるかどうかを見分けるには、それが、有効な “connectionToClient” を NetworkIdentity に持っているかどうか確認してください。例えば:
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);
}
}