Network Object
概要
ネットワークオブジェクトは、NetworkObject
コンポーネントを持つGameObject
で、ルーム内のネットワーク上の要素(Entity)の一つを表します。
ネットワークオブジェクトは、スポーンするかシーンオブジェクトとしてロードすることで生成できます。
NetworkId
サーバーはNetworkObject
コンポーネントにNetworkId
の値を割り当てます。NetworkId
は、ルーム内のオブジェクトのユニークな整数の識別子で、全てのピア間で一貫性があり、ネットワーク上のオブジェクトを参照するために使用されます。
NetworkId
をNetworkRunner.TryFindObject()
に渡して呼び出すことで、ローカル上のネットワークオブジェクトのインスタンスを検知できます。
ネットワークオブジェクトのスポーン
ネットワークオブジェクトを生成する方法は、以下の二つがあります。
Runner.Spawn()
を呼び出すSpawn
を呼び出すと、NetworkObject
コンポーネントを持つゲームオブジェクトが生成され、スポーン操作が複製されます。Runner.StartGame()
で渡すINetworkObjectProvider
に、スポーンするオブジェクトをどのように生成するかの実装が含まれます。例えば、プレハブからインスタンス化する・既存のオブジェクトをコピーする・コードからオブジェクトを生成する・オブジェクトプールから取得する、などです。- ネットワークオブジェクトが置かれたシーンをロードする
どちらの方法でも、生成されたネットワークオブジェクトはサーバーにアタッチされ、そのオブジェクトの状態は、関心を持つ全てのピアに複製されます。
Runner.Spawn()
Runner.Spawn()
は、ホストモードのサーバーか、共有モードでオブジェクトの状態権限を持たせたいクライアントでのみ呼び出します。呼出し後、指定したプレハブがインスタンス化されて、NetworkObject
コンポーネントがNetworkRunner
にアタッチされます。スポーン操作は、オブジェクトに関心がある他のクライアントに複製されます。
プレハブ / オブジェクトテーブル
ネットワークオブジェクトをスポーンするには、インスタンス化に使用するためのプレハブが必要になります。プレハブのパラメーターをFusionに認識させる(さらに、全てのクライアントが正確にプレハブを識別する)ためには、プレハブ自体がFusionに登録されている必要があります。通常、Fusionツールセットが自動的にプレハブを検出し登録しますが、NetworkProjectConfig
のRebuild Object Tableを押すことで、手動で検出を行うこともできます。
実行時のNetworkBehaviourの追加/削除
既にスポーンされたネットワークオブジェクトではNetworkBehaviour
の追加/削除はできませんが、スポーンする前であれば、実行時にNetworkBehaviour
の追加/削除が可能です。その際にはいくつか検討する点があります。
NetworkObject
はベイクされている必要があります- 独自のネットワークオブジェクトのインスタンス化は、通常
INetworkObjectProider
の実装で処理されます
シーンオブジェクトのロード
シーン上のネットワークオブジェクトをロードするのは、オブジェクトを生成してアタッチするためのもう一つの方法です。ISceneManager
を使用してシーンがロードされると、シーン上の有効なネットワークオブジェクトは、サーバー(ホストモード)またはマスタークライアント(共有モード)にアタッチされます。その後、各シーンオブジェクトに割り当てられたNetworkId
はその他全てのクライアントに複製されます。そして各クライアントで、そのNetworkId
が割り当てられたシーンオブジェクトがアタッチされます。
アタッチ
ネットワークオブジェクトは、スポーンするかシーンからロードすることでアタッチされます。アタッチとは、ネットワークオブジェクトにNetworkId
を割り当て、NetworkBehaviour
のネットワークプロパティのためにメモリを確保し、全ての関連するNetworkBehaviour
を初期化するプロセスになります。アタッチ後、NetworkObject
は、全ての子のNetworkBehaviour
のSpawned()
を呼び出します。そしてSpawned()
が呼び出されると、ネットワークオブジェクト自身と、そのネットワークプロパティやRPCが有効となり、FixedUpdateNetwork()
やRender()
のようなイベントメソッドやインターフェースのメソッドが呼び出されるようになります。
状態権限
アタッチされたネットワークオブジェクトの、明示的または暗黙的な状態権限は、PlayerRef
で指定されます。Runner.StateAuthority
の値がPlayerRef.None
の場合、サーバーが暗黙的な状態権限を持ちます。
ホストモード(専用サーバー/シングルプレイヤー)
サーバーが常に状態権限を持つため、Runner.StateAuthority
は常にPlayerRef.None
になります。状態権限を変更することはできません。
共有モード
Runner.StateAuthority
は常に有効なPlayerRef
になります。状態権限は変更できますが、いくつかの制限があります。
- 状態権限を渡すことはできません。たとえ状態権限を持つプレイヤーだとしても、他のプレイヤーにその状態権限を渡すことはできません。
- 状態権限は取得することができます。プレイヤーは
Object.RequestStateAuthority()
を呼び出して、状態権限の取得を試みることができます。
RequestStateAuthority()
は、以下の場合のみ成功します。
NetworkObject.AllowStateAuthorityOverride
がtrueに設定されている場合- 前に状態権限を持っていたプレイヤーが
Object.ReleaseStateAuthority()
を呼び出していた場合
入力権限
入力権限はホストモード(サーバー/シングルプレイヤー)固有のもので、共有モードでは適用されません。GetInput()
が呼び出された時にどのプレイヤーの入力を返すべきかは、入力権限によって決定されます。
レプリケーション
アタッチされたネットワークオブジェクトは、ティックごとのシミュレーションを進めます。その結果となる状態は、状態権限者からその他全てのピアに複製されます。
重要: ネットワークプロパティは、状態権限者から他のピアにのみ複製されます。他のピアがネットワークオブジェクトに加えた変更は、状態権限者の変更を受信した際に上書きされます。入力権限者の場合、通常の予測プロセスとして、受信したサーバーの状態より先のティックのシミュレーションを進め、新しいサーバーの状態を受信するたびに、ロールバックと再シミュレーションを行います。
インタレストマネジメント
関心領域のような様々なインタレストマネジメントのメカニズムを使用して、ネットワークオブジェクトをどのプレイヤーに複製するかをカリングできます。インタレストマネジメントは、特定のプレイヤーへ送信するオブジェクトの更新を除外するデータ削減メカニズムで、大量のネットワークオブジェクトが存在したり、大人数が参加したりするゲームでは非常に重要な機能になります。
ネスティング
Fusionは、ネットワークオブジェクトの入れ子に対応しています。ネスティングとは、あるネットワークオブジェクトが他のネットワークオブジェクトの子要素になることです。ネットワークオブジェクトは、複数のネットワークオブジェクトを含むことができます。ネットワークオブジェクトがアタッチされる時、各ネットワークオブジェクトは、親や子のネットワークオブジェクトとは個別の要素として扱われます。NetworkBehaviour
は最も近い親オブジェクトに関連付けられて、ルートのネットワークオブジェクトには、子オブジェクトに属するNetworkBehaviour
はアタッチされません。