Coming From PUN
はじめに
この記事では、PUNからFusionに移行する方法について説明いたします。オブジェクト同期とゲームプレイをテーマとしています。
PUNは大変素晴らしい使いやすいネットワーキングソリューションですが、時代が進むにつれてプレイヤー人数の多さや、プレイヤーアクションの正確な複製、権限の処理などの近代的なマルチプレイヤーゲーム要素に対応しきれない点も出てきました。FusionはPUN同様の使いやすさでありながら、多くのプロジェクトにより適用するものです。
PUNとの違い
PUNからの移行の際に注意すべき点がいくつかあります。
FusionはプレイヤーごとにRunner
をインスタンス化し、これをいくつかのシーンに設定する必要があります。これを行うため、階層(Hierarchy)パネルのコンテキストメニューには、シーンのセットアップに便利なショートカット付きのFusionサブメニューがあります。
Fusionは、主にテストやデバッグの目的で、1つのプロセス内でRunner
インスタンスを複数実行することができます。エディタでのヘルパーパネルで表示するインスタンスや入力するインスタンスを選択できます。
エディタは、同時に複数のピアを実行している場合、開始時に現在のシーンの再読み込みを行います、これに対応するため、ゲームロジックを調整する必要がある場合があります。スタンドアロンのビルドはOUNと同様、簡単にエディタに接続することができます。
PUNの多くのAPIはPhotonNetwork
クラスから使用可能でした。Fusionではかわりに、インスタンスごとにRunner
があります。SimulationObject
またはNetworkObject
から継承されるあらゆるクラスはRunner
およびオブジェクトメンバーへアクセス可能なため、FusionのAPIはOUNと同様に簡単です。
PUNで提供していたのが「分散型」の権限("distributed" authority)のみであったのに対し、Fusionでは専用サーバー(Dedicated Server)
、クライアントホスト型(Client Hosted)
、共有モード(Shared Mode)
に対応しています。共有モード(Shared Mode)
はPUNと似ており、ネットワークオブジェクトの権限がプレイヤーに分配されます。シーンオブジェクトは自動的に1人のプレイヤーにコントロールされるようになっています。
PUNではオブジェクトの コントロール のコンセプトのみがあったのに対し、Fusionでは権限をステート権限と入力権限に細分化しています(共有モード
が使用されていない限り)。
PUNでのスクリプトは通常photonView.IsMine
を確認してクライアントがオブジェクトをコントロールしているか判定するのみでした。FusionではObject.HasStateAuthority
と Object.HasInputAuthority
の記録を個別でトラッキングします。PUNのポートは、Fusionの共有モード
を使用してHasStateAuthority
を確認してください。
PUNでは、新しいプレイヤーが入るごとにPlayer.ActorNumber
がカウントされていました。Fusionでは、0の時点でPlayerRef
が開始され、 MaxPlayers - 1
まで上昇します。ゲームのホストがいる場合、そのプレイヤーは常にPlayerRef
値としてMaxPlayers - 1
を取得します。
Fusionはプロジェクトのシーンを把握する必要があります。シーンはプロジェクトビルド設定でアレンジし、そこからインポートすることができます。
PUNとの類似点
Fusionで期待されることはPUNのそれとは大きく異なるかもしれませんが、Fusionは多くのアイディアをPUNから引きついています。
PUNの主な要素はPhotonView
で、これはNetworkObject
という直接の同等物があります。PUNと同様、NetworkObjectは識別子であるのみで、追加のコンポーネントに依拠して希望の挙動を提供します。
Fusionには共通のコンポーネントの置換があります。例えば、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メソッドを持つHashtablesであったのに対し、FusionではかわりにプレーンなC#プロパティを同期します。NetworkBehaviour
の一部として、自動実装プロパティはゲームステートの一部となるために [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() |