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);
}
}
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.