Unity のネットワーキング システムでは、ゲームは一つのサーバーと複数のクライアントを持ちます。専用サーバーがある場合は、クライアントの一つがサーバーの役割を果たします。このクライアントのことを「ホスト」と呼びます。
ある処理において、ホストは、サーバーでもありクライアントもあります。ホストは LocalClient と呼ばれる特殊なクライアントを使用します。それ以外のクライアントは RemoteClient です。LocalClient は、一次関数コールとメッセージキューを用いて(ローカルの)サーバーと交信します。同じ処理に含まれるからです。LocalClient はシーンをサーバーと共有します。RemoteClient は通常のネットワーク接続でサーバーと交信します。
ネットワーキング システムの目的の1つは、LocalClient と RemoteClient のコードを同一にすることで、開発者がほとんどの場合において、一種類のクライアントだけを考えればよいようにすることです。
Unity では、GameObject.Instantiate によって Unity ゲーム オブジェクトが新しく作成されます。ただしネットワーキング システムにおいては、オブジェクトがネットワーク上でアクティブになる為にはそれが “生成 (Spawn)” される必要もあります。これはサーバー上でのみ行うことが可能で、オブジェクトは接続されたクライアント上に作成されます。オブジェクトを生成されると、オブジェクト生成システム(Spawning System)は、オブジェクトのライフサイクルに則ってオブジェクトを分配し、原則に沿ってステートの同期を行います。
詳しくは オブジェクトの Spawn(生成)を参照してください。
ネットワークシステムにおいて、プレイヤーオブジェクトは特殊な存在です。ゲームをプレイするそれぞれの人に一つプレイヤーオブジェクトが関連付けられ、コマンドはそのオブジェクトに送られます。自分以外の人のプレイヤーオブジェクトへのコマンドを呼び出すことはできません。呼び出せるのは自分自身のプレイヤーオブジェクトに関してのみです。したがって「自分の」プレイヤーオブジェクト、という概念が存在します。プレイヤーが追加されて特定の接続との関連付けが成されると、そのプレイヤーオブジェクトがそのプレイヤーのクライアントの「ローカルプレイヤー」オブジェクトとなります。isLocalPlayer プロパティーは True に設定され、OnStartLocalPlayer() コールバックは該当クライアントのオブジェクトに対して呼び出されます。下図は、二つのクライアントとそのローカルプレイヤーを表しています。
「自分の」プレイヤーオブジェクトのみが isLocalPlayer フラッグセットを持ちます。これは、入力処理のフィルタリングやカメラの取り付け、またその他すべての、「自分の」プレイヤーだけに対して行われるべきクライアント側の処理に使用できます。
isLocalPlayer の他に、一つのプレイヤーオブジェクトが “ローカル権限” を持つことができます。これは、オーナーのクライアント上のプレイヤーオブジェクトが、オブジェクトに対して責任を持つ(つまり権限を持つ)ことを意味します。これは動きの制御に使用されることがもっとも多いですが、それ以外の用途でも使用できます。NetworkTransform コンポーネントはこれを理解し、これが設定されているとクライアントから動きを送ります。NetworkIdentity には LocalPlayerAuthority を設定するためのチェックボックスがあります。
プレイヤー以外のオブジェクト(敵など)には関連付けられたクライアントがないため、権限はサーバーに属します。
NetworkBehaviour に “hasAuthority” というプロパティーがあり、これは特定のオブジェクトに権限があるかどうかの確認に使用できます。したがって、プレイヤー以外のオブジェクトはサーバーに権限を持ち、localPlayerAuthority セットを持つプレイヤーオブジェクトはそのオーナーのクライアントに権限を持つということになります。
Unity 5.2 から、非プレイヤー オブジェクトに対してクライアント権限を持たせることが可能になりました。これを行うには二つの方法があります。ひとつは、NetworkServer.SpawnWithClientAuthority を使用してオブジェクト生成を行い、所有権を持たせるクライアントのネットワーク接続をパスする方法。もうひとつは、所有権を持たせるクライアントのネットワーク接続に NetworkIdentity.AssignClientAuthority を使用する方法です。
クライアントに権限を与えるとオブジェクトの NetworkBehaviour に OnStartAuthority() が呼び出され、hasAuthority プロパティーが true になります。その他のクライアントの hasAuthority プロパティーは false のままになります。クライアント権限のあるプレイヤー以外のオブジェクトは、プレイヤー同様、コマンドを送ることができます。このコマンドは、接続に関連付けられたプレイヤーではなく、サーバーにあるオブジェクト インスタンスで実行されます。
クライアント権限を持たせる非プレイヤー オブジェクトは、NetworkIdentity の LocalPlayerAuthority のチェックボックスがオンになっている必要があります。
下記の例では、オブジェクトを生成し、その生成を行ったプレイヤーのクライアントに権限を与えています。
[Command]
void CmdSpawn()
{
var go = (GameObject)Instantiate(otherPrefab, transform.position + new Vector3(0,1,0), Quaternion.identity);
NetworkServer.SpawnWithClientAuthority(go, connectionToClient);
}
NetworkBehaviour クラスには、ネットワーク上のオブジェクトのネットワークコンテキストをいつでもスクリプトに知らせることができるプロパティーがあります。
これらのプロパティーは、Inspector にあるオブジェクトのプレビューウィンドウで確認できます。