PUN2からの移行
概要
ここでは、オブジェクト同期とゲームプレイに焦点を合わせて、PUN経験者がFusionを習得する方法を説明します。
PUNは非常に完成度が高く使いやすいネットワークエンジンですが、時代が進むにつれて、大人数のプレイヤー数・プレイヤーのアクションに対する正確なレプリケーション・権限処理など、現代的なマルチプレイヤーゲームには不十分な面も出てきました。Fusionは、PUNと同様の使いやすさで、多くのプロジェクトに適したものになるでしょう。
Fusionのモード
PUNからFusionに移行する際に理解しておくべき重要な点は、PUNは、すべてのクライアントに共有されているルームによる「分散型」の権限モデルであることです。
Fusionを共有モードで実行すると、PUNと同じ分散型権限モデルになります。シーンオブジェクトは、自動的に1人のプレイヤーによって制御されます。PUNのほとんどの概念は、Fusionの共有モードに応用可能ですが、Fusionのホスト(サーバー)モードには応用できません。
ここでは、PUNの知識をFusionの共有モードへ移行する方法を説明します。ホスト(サーバー)モードは、アプリケーションによっては、より良い選択肢となります。
相違点
対応表
| PUN | Fusion |
|---|---|
| PhotonNetwork | SimulationBehaviour.Runner と SimulationBehaviour.Object |
| MonoBehaviourPunCallbacks | SimulationBehaviour と NetworkBehaviour |
| PhotonNetwork.AddCallbackTarget(this) | N/A (自動) |
| PhotonNetwork.Instantiate() | Runner.Spawn() |
| PhotonView | NetworkObject |
| IPunObservable.OnPhotonSerializeView() | C#の自動実装プロパティ と 入力の同期 |
| PhotonTransformView | NetworkTransform |
| PhotonRigidbodyView | NetworkRigidbody |
| PhotonAnimatorView | NetworkMecanimAnimator |
| N/A | NetworkCharacterController |
| [PunRPC] | [Rpc] |
| PhotonNetwork.LoadLevel() | Runner.SetActiveScene() |
接続とマッチメイキング
マッチメイキングの主要概念は、PUNとFusionで同じです。ロビー・マッチメイキング・ルーム・マッチメイキング用のプロパティなどは、Fusionにも存在します。
FusionのマッチメイキングAPIは完全に異なり、NetworkRunnerから呼び出して使用します。Fusionにおける接続とマッチメイキングの詳細は、こちらをご覧ください。
設定ファイル / ConnectUsingSettingsの代替
PUNの多くの設定は、PhotonServerSettingsファイル(ScriptableObject)に格納されています。設定は主に、AppId・サーバー設定・プロトコル・ログなどについてです。
Fusionでは、設定が2つのファイルに分けられています。
PhotonAppSettingsが保持する情報は、クライアントがPhoton Cloudに接続するために使用されます。設定を変更する必要があるデータは、アプリケーションのAppIdのみであることがほとんどです。AppIdはFusion Hubからも設定できます。
NetworkProjectConfigでは、Fusionに関する多くのオプションを詳細に設定できます。デフォルトの設定のままでも使用できます。設定には、ティックレート・最大プレイヤー数などがあります。
認証
PUNと同じように、Fusionは認証プロバイダーに対応しています。詳細はカスタム認証のページをご覧ください。
オフラインモード
PUNのように、Fusionにもオフラインモードがあります。PhotonNetwork.OfflineModeのかわりに、NetworkRunner.StartGame呼び出し時にGameMode.Singleを使用してください。
ActorNumber
PUNでは、新規プレイヤーごとにPlayer.ActorNumberがカウントアップされていました。Fusionでは、PlayerRefが0からMaxPlayers - 1までカウントアップします。ゲームにホストが存在する場合、ホストプレイヤーのPlayerRefの値は常にMaxPlayers - 1になります。
NetworkRunner(PhotonNetworkの代替)
PUNの多くのAPIはPhotonNetworkクラスから利用可能でした。FusionはNetworkRunnerがインスタンスごとに存在します。NetworkBehaviourを継承したクラスは、NetworkRunnerとNetworkObjectにアクセスできるため、FusionのAPIはPUNと同じくらい簡単に使用できます。
UnityのヒエラルキーのコンテキストメニューにFusionのサブメニューがあり、シーン構成に便利なショートカットがあります。
コールバック(MonoBehaviourPunCallbacks / PhotonNetwork.AddCallbackTarget(this))
コールバックはPUNのAPIを支える要素で、接続の確立やランダムマッチメイキングの結果を待つために使用されます。PUNのコールバックは、いくつかのインターフェースの定義に分類されていて、それをスクリプトで実装します。そして、スクリプトを登録して、実行時にコールバックを受け取れるようにする必要があります。
PUNのMonoBehaviourPunCallbacksクラスを継承すると、特定のメソッドをオーバーライドしてコールバックを受け取れるようになるため、このワークフローを単純化できます。
FusionはINetworkRunnerCallbacksによって、セッション関連などのコールバックを提供します。Spawned/Despawnedなどのようなオブジェクト固有のコールバックは、NetworkBehaviourから直接利用可能です。
インスタンス化
Fusionでは、PhotonNetwork.Instantiate()のかわりにRunner.Spawn()を呼び出します。オブジェクトプールには、独自のIPunPrefabPoolのかわりにINetworkObjectProviderを使用します。
シーンオブジェクト
シーンオブジェクトは、PUNとFusionで同じような形で動作します。シーンが最初にロードされた時、マスタークライアントが、すべてのシーンオブジェクトの状態権限(StateAuthority)を自動的に持ちます。
手動インスタンス化
FusionでPUNの手動インスタンス化を置き換えるためには、独自のINetworkPrefabSourceから、スポーンに必要なプレハブを提供します。特定のネットワークオブジェクトインスタンスを作成するPUNとは異なり、プレハブのインスタンス化はINetworkObjectProviderによって行われます。
これは一般には非推奨で、ほとんどのFusion製アプリケーションには必要ありません。
シーン
シーンをロードするには、PhotonNetwork.LoadLevel()をRunner.LoadScene()に置き換えてください。
複数のシーン
Fusionは標準で、複数のシーンに対応しています。Runner.LoadScene()でAdditiveなシーンローディングが可能です。
PhotonView
PUNの重要な要素であるPhotonViewと全く同等なクラスは、NetworkObjectと呼ばれます。PUNと同じように、NetworkObjectは単なる識別子(ID)であり、任意の振る舞いは追加したコンポーネントに依存します。
MonoBehaviourPun
MonoBehaviourPUNは、FusionではNetworkBehaviourになります。NetworkBehaviourは、NetworkObjectと同じGameObjectおよび子のGameObjectに追加できます。
Fusionは、複数のNetworkObjectの入れ子に完全に対応しています。
PhotonTransformView
PhotonTransformViewはNetworkTransformに置き換えられます。NetworkTransformは、洗練された実装と多くの機能(親子関係の同期など)を、標準で搭載しています。
PhotonAnimatorView -> NetworkMecanimAnimator
PhotonAnimatorViewはNetworkMecanimAnimatorに置き換えられます。NetworkMecanimAnimatorは、PUNと同じように動作し、StateAuthorityを持つクライアントから他すべてのクライアント(プロキシ)へ、アニメーションを同期します。
CharacterController
PUNでは、プレイヤーキャラクターを動かすために、Unity標準のCharacterControllerを使用できました。Fusionの共有モードでは、多くの機能を備えた上位オプションとしてSimple KCCアドオンも利用可能です。
PhotonRigidbodyView -> NetworkRigidbody
Fusionには、PUNと同様に動作するネットワーク物理システムがあります。PhotonRigidbodyViewのかわりにNetworkRigidbody3Dコンポーネントを使用してください。オブジェクトの権限を持つクライアントは、Rigidbodyに対して物理シミュレーションを実行し、他すべてのクライアントは、Rigidbodyに対してビューを表示するだけのKinematicな動作になります。物理コンポーネントは2Dでも利用可能です。
PhotonRigidbodyViewはNetworkRigidbodyに置き換えられ、PhotonTransformViewはNetworkTransformに置き換えられます。どちらもPUNと同じように、2Dで利用可能です。
PhotonView.IsMine / オブジェクトの権限
PUNでは、クライアントがオブジェクトを操作するかどうかを決定するために、スクリプトでphotonView.IsMineをチェックすることが一般的でした。Fusionでは、photonView.IsMineがObject.HasStateAuthorityになります。
プレイヤー切断時の所有権移譲
PUNでは、所有者がいないネットワークオブジェクトに対して、マスタークライアントが変更された時に、自動的に新しいマスタークライアントに管理権限が移っていました。
Fusionでは、クライアントがルームから切断/退出した時の権限の移譲処理に、複数の選択肢が存在します。
NetworkObjectのIsMasterClientObjectを有効にすると、PUNの挙動と同じように、StateAuthorityが自動的に新しいマスタークライアントに移譲されるようになります。
Destroy When State Authority Leavesを有効にすると、権限を委譲するかわりにオブジェクトを破棄します。
RPC
可能な限り、変数の同期(ネットワークプロパティ)を使用してください。
リモートプロシージャコール(RPC)は洗練されていて、[Rpc]属性を付けたメソッドを、ローカルのメソッドのように呼び出すだけになりました。呼び出しは、ネットワークを通して動作するようにFusionによって変換されます。
カスタムプロパティにかわる変数の同期方法
PUNのカスタムプロパティは、Setterメソッドを持つハッシュテーブルでしたが、Fusionでは通常のC#プロパティが同期できます。NetworkBehaviour内で[Networked]属性を付けた自動実装プロパティは、ゲームの状態の一部となります。オブジェクトの権限者のみが値を変更でき、それが自動的にネットワークを通して複製されるため、チートのリスクが軽減されます。
プレイヤーのカスタムプロパティを置き換えるには、単純にNetworkBehaviourにネットワークプロパティを追加してください。
ルームのカスタムプロパティを置き換えるには、シーンオブジェクトを作成し、そのNetworkBehaviourにネットワークプロパティを追加してください。シーンオブジェクトは、FindObjectOfTypeやシングルトンパターンなどを使用して取得できます。
IPunObservable.OnPhotonSerializeView()は不要に
OnPhotonSerializeViewもネットワークプロパティに置き換えられます。ネットワークプロパティは、OnPhotonSerializeViewとカスタムプロパティの両方の機能を兼ね備えています。ティックに合わせて即時に更新され、変更があった時のみ同期され、変更を検知するコールバックが利用可能です。
Fusion 2の変更検知
PUNでは、ルーム/プレイヤーのプロパティが変更されると、PropertyChangedイベントが発生します。Fusionでは、OnChangeRenderかChangeDetectorが使用できます。
マルチピア
Fusionは1つのプロセスで、複数のNetworkRunnerインスタンスを実行して、テストやデバッグが可能です。エディター上のパネルから、可視化する/入力を取得するインスタンスを選択できます。
エディターで複数のピアを同時に実行すると、ピア開始時に現在のシーンがリロードされます。これに対応するように、ゲームロジックを修正する必要があります。PUNのように、スタンドアロンビルドからエディターに簡単に接続することができます。
特殊なケース
Fusionの共有モードは、PUNと同等の柔軟性と使いやすさを備えています。しかし、ハイペースな対戦ゲームなどに向けて、Fusionはホスト(サーバー)モードを提供しています。
このモードでは、サーバーまたはクライアントの1人が、ゲームの状態に対するすべての権限を持ちます。つまり、そのピアがすべての状態を保持し、そのピアのみが状態を変更できるということです。他のピアは、ローカルの予測や遅延を隠蔽するために状態を変更できますが、変更を有効にするにはサーバーから複製される必要があります。
自身のゲームでホスト(サーバー)モードを選択すべきかどうかを検討する際は、以下のQuadrantをご覧ください。
- 概要
- Fusionのモード
- 相違点
- 対応表
- 接続とマッチメイキング
- 設定ファイル / ConnectUsingSettingsの代替
- 認証
- オフラインモード
- ActorNumber
- NetworkRunner(PhotonNetworkの代替)
- コールバック(MonoBehaviourPunCallbacks / PhotonNetwork.AddCallbackTarget(this))
- インスタンス化
- シーンオブジェクト
- 手動インスタンス化
- シーン
- 複数のシーン
- PhotonView
- MonoBehaviourPun
- PhotonTransformView
- PhotonAnimatorView -> NetworkMecanimAnimator
- CharacterController
- PhotonRigidbodyView -> NetworkRigidbody
- PhotonView.IsMine / オブジェクトの権限
- プレイヤー切断時の所有権移譲
- RPC
- カスタムプロパティにかわる変数の同期方法
- IPunObservable.OnPhotonSerializeView()は不要に
- Fusion 2の変更検知
- マルチピア
- 特殊なケース