PUNからの移行
はじめに
この記事は、オブジェクトの同期とゲームプレイに焦点を合わせて、PUNからFusionに移行する方法を説明します。
PUNは非常に完成度が高く使いやすいネットワーキングソリューションですが、時代が進むにつれて、大人数のプレイヤー数、状態の正確なレプリケーション、権限の取り扱いなど、現代的なマルチプレイヤーゲーム開発に対応しきれない点も出てきました。FusionはPUNと同様の使いやすさながら、より多くのプロジェクトに適したものとなるでしょう。
PUNとの違い
PUNからの移行の際には注意すべき点がいくつかあります。
FusionはプレイヤーごとにNetworkRunner
をインスタンス化し、シーン内でセットアップする必要があります。HierarchyパネルのコンテキストメニューにはFusionのサブメニューがあり、シーンをセットアップする便利なショートカットが存在しています。
Fusionは、主にテストやデバッグの目的で、一つのプロセス内でNetworkRunner
インスタンスを複数実行することができます。エディタのヘルパーパネルから、どのインスタンスの表示や入力を有効にするかを選択できます。
エディタ上で同時に複数のピアを実行している場合、ゲーム開始時に現在のシーンの再読み込みが行われます。これに対応するには、ゲームロジックを調整する必要があります。スタンドアロンビルドは、PUNと同じように簡単にエディタに接続することができます。
PUNの多くのAPIはPhotonNetwork
クラスから使用可能でした。Fusionではかわりに、インスタンスごとのNetworkRunner
があります。SimulationBehaviour
かNetworkBehaviour
を継承するクラスは、NetworkRunner
とオブジェクトの変数にアクセス可能なため、FusionのAPIはPUNと同様に簡単に扱えます。
PUNでは「分散型」の権限のみを提供していましたが、Fusionはサーバーモード、ホストモード、共有モードに対応しています。共有モードはPUNと似ており、ネットワークオブジェクトの権限が各プレイヤーに分散されます。シーンオブジェクトは自動的に一人のプレイヤーのコントロール下に置かれます。
PUNはオブジェクトに対する所有権のみがあったのに対して、Fusionでは権限が状態権限と入力権限に分けられています(共有モードを除く)。
PUNのスクリプトでは、クライアントがオブジェクトの所有権を持っているかどうかはphotonView.IsMine
をチェックするだけで判定できました。FusionではObject.HasStateAuthority
とObject.HasInputAuthority
が別々に保持されています。PUNからFusionへの移植は、共有モードを使用してHasStateAuthority
を確認することになるでしょう。
PUNでは、新しいプレイヤーが入るごとにPlayer.ActorNumber
が増加していました。Fusionでは、PlayerRef
の値は0から始まりMaxPlayers - 1
まで増加します。ゲームのホストが存在する場合、そのプレイヤーのPlayerRef
の値は常にMaxPlayers - 1
になります。
FusionはUnityのシーンを認識する必要があります。シーンはUnityのBuild Settingsで設定したものが読み込まれます。
PUNとの類似点
FusionはPUNとは大きく異なるように見えますが、実際には多くのアイデアがPUNから引き継がれています。
PUNの重要な要素であるPhotonView
と全く同等なクラスはNetworkObject
と呼ばれます。PUNと同様に、NetworkObject
は単なるIDであり、任意の振る舞いはオブジェクトに追加したコンポーネントに依存することになります。
FusionにはPUNのコンポーネントの代替が用意されています。例えば、PhotonRigidbodyView
はNetworkRigidbody
に置き換えられ、PhotonTransformView
はNetworkTransform
になります。PUNと同様に、どちらも2Dでも使用可能です。
PhotonAnimatorView
はNetworkMecanimAnimator
で置き換えられます。キャラクターを操作する用途では、FusionはPUNには無い汎用的なNetworkCharacterController
があります。
コンポーネントの個々の設定は異なりますが、多くの場合はデフォルトの値で問題ありません。NetworkObject
とその子オブジェクトの全コンポーネントは、自動的に検出されます。Fusionは必要に応じたNetworkObject
の入れ子構造を完全にサポートしています。
PUNと同様に、NetworkObject
はあらかじめシーン上に置いたり、ランタイム時にインスタンス化したりすることができます。Fusionでは、PhotonNetwork.Instantiate()
のかわりにRunner.Spawn()
を呼び出します。シーンを読み込むには、PhotonNetwork.LoadLevel()
をRunner.SetActiveScene()
に置き換えます。
PUNの他の重要なクラスにはMonoBehaviourPun
とMonoBehaviourPunCallbacks
があります。Fusionでは、NetworkBehaviour
を継承するスクリプトにゲームロジックを記述したり状態を保持したりします。状態を保持しない場合、スクリプトはSimulationBehaviour
を継承することもできます。スクリプトの初期化は、PUNではOnPhotonInstantiate()
を呼び出していましたが、FusionではSpawned()
コールバックを使用します。
PUNのカスタムプロパティはsetterメソッドを持つハッシュテーブルでしたが、Fusionはかわりに普通のC#のプロパティを同期します。NetworkBehaivour
の[Networked]
属性を付けた自動実装プロパティは、ゲームの状態の一部となります。オブジェクトの状態権限を持つプレイヤーのみが値を変更することが可能で、その値はネットワーク上で自動的に複製されるため、チートの影響が抑えられる側面もあります。
リモートプロシージャコール(RPC)もサポート済みで、より高水準になりました。メソッドに[Rpc]
属性を付けてローカルのメソッドと同様に呼び出すと、Fusionはその呼び出しをネットワーク上で動作するように変換します。
対応表
PUN | Fusion |
---|---|
PhotonNetwork | SimulationBehaviour.Runner and SimulationBehaviour.Object |
MonoBehaviourPunCallbacks | SimulationBehaviour and NetworkBehaviour |
PhotonNetwork.AddCallbackTarget(this) | N/A (automatic) |
PhotonNetwork.Instantiate() | Runner.Spawn() |
PhotonView | NetworkObject |
IPunObservable.OnPhotonSerializeView() | C# auto-implemented properties and Input Sync |
PhotonTransformView | NetworkTransform |
PhotonRigidbodyView | NetworkRigidbody |
PhotonAnimatorView | NetworkMecanimAnimator |
N/A | NetworkCharacterController |
[PunRPC] | [Rpc] |
PhotonNetwork.LoadLevel() | Runner.SetActiveScene() |