オーナーシップの移行デモ
この簡単なデモは、理解がむずかしいPUNの機能の入門篇です。
分かりやすく言えば、オーナーシップの移行では任意のネットワークオブジェクトの管理を移行することができます。このページではこの機能の使い方やバックグラウンドの説明をし、より処理が複雑なケースについて解説します。
デモでは、だれでもオブジェクトをインスタンス化できます。
クリックすると、オーナーシップの移行がリクエストされます。
現在のオーナーはオーナーシップを移行するか、リクエストを拒否することが出来ます。
各オブジェクト上のポインタは、所有されている(管理されている)GameObjectをクライアントごとに示します。
基本
PUNでは、どのオブジェクトもコントロール可能です。
クライアントが何かをインスタンス化した際、そのクライアントが新しいオブジェクトのオーナーとなり、 PhotonView.isMine
はそのクライアントでのみtrueとなります。もしOnPhotonSerializeView
を使用した場合には、そのクライアントのみがPhotonStreamに書き込みを行います。
他のクライアントは受信と更新のみをおこないます。
もしGameObjectの管理を他のクライアントに移行したい場合は、まずPhotonViewを設定する必要があります。
インスペクターの中に、GameObjectのオーナーが表示されます(プレハブは実行時に、オーナーを1つのみ持ちます)。
同じ行に、デフォルトでFixed
に設定されているドロップダウンがあります。その他のオプションはTakeover
とRequest
です。
- 「Fixed」の場合、GameObjectのクリエイターがオーナーであり続けます。
- 「Takeover」の場合、どのクライアントも現在のオーナーからGameObjectを取得できます。
- 「Request」 は、現在のオーナーにオーナーシップの移行をリクエストします。このリクエストは拒否することが可能です。
PhotonViewの設定
「OwnershipSphere」を選択してTakeOver
に設定されていることを確認してください。
これは、シーンで1回のみ使用されます。
この設定によりオブジェクトがシーンオブジェクトになり、誰でも取得することができます。
"OwnershipCube"プレハブはRequest
に設定されているため、現在のオーナーはオーナーシップを転送または拒否することができます。
このデモでは、トグルボタンとして右上角に追加されています(実行時)。
デフォルトでは、誰がそのGameObjectを管理するかにかかわらず、クリエイターがルームを退室するとそのGameObjectは破壊されます。
オーナーシップのリクエストと移行
どちらのプレハブにもOnClickRequestOwnership
コンポーネントがあります。
PhotonViewが設定されたGameObjectをクリックすると、そのPhotonViewがどのような設定であるかにかかわらず、このスクリプトはthis.photonView.RequestOwnership();
を呼び、オーナーシップをリクエストします。
リクエストに答えるのは、DemoOwnershipGui
スクリプトです(Request
設定の場合)。
このスクリプトはOnOwnershipRequest()
を実装します。
C#
public void OnOwnershipRequest(object[] viewAndPlayer)
{
PhotonView view = viewAndPlayer[0] as PhotonView;
PhotonPlayer requestingPlayer = viewAndPlayer[1] as PhotonPlayer;
Debug.Log("OnOwnershipRequest(): Player " + requestingPlayer + " requests ownership of: " + view + ".");
if (this.TransferOwnershipOnRequest)
{
view.TransferOwnership(requestingPlayer.ID);
}
}
オーナーシップがリクエストされると、現在のオーナーであるクライアント上のPUNによってオーナーシップが呼ばれます。
現在のオーナーは、PhotonViewを実際に移行するためview.TransferOwnership(requestingPlayer.ID)
を呼びます。
GameObjectの現在のオーナーが退出すると、マスタークライアントが新しいオーナーになります。
GameObjectを作成したプレイヤーがオーナーシップを取り戻すには、オーナーシップをリクエストする必要があります。
むずかしい状況
オーナーシップの転送自体は、比較的簡単です。
GameObjectの管理はリクエストや移行が可能で、もし現在のオーナーがいなくなった場合は、マスタークライアントが引き継ぎます。
上記のとおり、管理が変更されてもGameObjectのライフタイムには影響がありません。
デフォルトでは、1人のプレイヤーによって作られたGameObjectはそのプレイヤーが退出すると破壊されます。
RPCs
RPCはGameObjectのライフタイムに限定されません。
インスタンス化していないGameObject上でRPCを使用すると、(バッファされた)RPCが参加プレイヤーに送信される可能性があります。
これらには、無視してよい場合もありますが、把握しておく必要があります。
また、PhotonViewや退出したプレイヤーに対応するRPCをクリーンアップすることが可能です。
PhotonNetwork.RemoveRPCs()
を参照してください。
シーンオブジェクト
プレイヤーが、管理中のGameObjectを紛失してしまう可能性があります。
問題がない場合もありますが、問題が発生する場合もあります。
これはマスタークライアントがGameObjectsをInstantiateSceneObject()
でインスタンス化することで対処できます。
こうすれば、最後のプレイヤがルームを退出するまでGameObjectがルームに残ります。
もちろん、このGameObjectを破壊することもできます。
また、GameObjectを管理すべきプレイヤーにマスタークライアントがオーナーシップを転送することもできます。
または、PhotonNetwork.autoCleanUpPlayerObjects
をfalseに設定して、イベントバッファの自動クリーンアップを無効にすることも可能です。この設定後、Photonはプレイヤーが退出した後もプレイヤーのすべてのイベントを保持します。
インスタンス化コールや、バッファされたRPCをクリーンアップしないと、バッファが増大します。
実行時間の長いゲーム(プレイヤーが長時間にわたって参加したり、退出したりするゲーム)の場合には、このようにしてバッファ対象のイベントが集積し壊れてしまう可能性があります(Photonには、これに関する上限がありません)。