Unity

Photon PUN2からFusionへの移行メモ

現在開発中のゲームはPUN2で作っていたのですが、将来の事を考えて、Fusionに置き換えてみたので、PUN2からFusionに置き換える時、どういう変更が必要になるのかをまとめてみました。

最後に、Fusionのハマりどころをまとめておきます。

Fusionの公式ドキュメントは日本語版が古い場合があるので、英語版で見る方が良さそうですが、分かりやすいので参考リンクは日本語にしておきます。

 

 

サーバーとの接続

PUN2

PhotonNetworkのクラスメソッド、ConnectUsingSettings()、でロビーに接続。
ロビーに接続されたら、PhotonNetwork.JoinRandomRoom()、でルームに接続。
入れるルームがなかった場合は、入室の失敗をハンドリングして自分でルームの接続人数などを指定して作成 & 入室する。

Fusion

NetworkRunnerのインスタンスメソッド、runner.StartGame(StartGameArgs args)で、ルームの接続人数などを指定して入室。
入れるルームがなかった場合は自動的に作成されて、自動的に入室する。シンプル!

 

入室チェック

PUN2

入室に成功するとOnJoinedRoom()が呼ばれる。失敗するとOnJoinRandomFailed(short returnCode, string message)が呼ばれる。

Fusion

入室処理の戻り値でチェックする。

var result = await runner.StartGame(StartGameArgs args)
if (result.Ok) {}

 

接続可能人数と接続人数

PUN2

PhotonNetwork.CurrentRoom.MaxPlayers
PhotonNetwork.CurrentRoom.PlayerCount

Fusion

networkRunner.SessionInfo.MaxPlayers
networkRunner.SessionInfo.PlayerCount

似てる。

 

カスタムプロパティ

PUN2

Roomに紐づいた共有データとして、ルームカスタムプロパティ、プレイヤーに紐づいた共有データとして、プレイヤーカスタムプロパティ、というHashtableが用意されていて、みんなでわちゃわちゃ入れあって、データを共有できる。

Fusion

カスタムプロパティは廃止され、ネットワークプロパティと呼ばれる、[Networked]アトリビュートを付けた変数を使ってデータの共有ができる。

ただし、最初に入室したユーザー(Host)しかネットワークプロパティの値は変更できない。

またPUN2のカスタムプロパティにあった排他処理が無いので、最初に触ったプレイヤーしか値を変更できない、という仕様を実現する場合は変更権限のあるユーザー(Host)にRPCを使って変更を依頼し、Hostが一元管理する必要がある。

 

(ネットワークプロパティの公式ドキュメントは日本語が古いので英語を載せておきます。)

 

共有データ(旧カスタムプロパティ)のハンドリング

PUN2

ルームの共有データは、OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)、で
ユーザーの共有データは、OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)、で変更をハンドリングできる。

Fusion

ネットワークプロパティを定義する時に変更ハンドラーを指定できる。

[Networked(OnChanged = nameof(HogeChanged))]
NetworkString<_32> hogeString { get; set; }  // この形式で宣言しないとダメ

static void HogeChanged(Changed<HogeController> changed){} // staticじゃないとダメ

 

RPC

PUN2

[PunRPC]アトリビュートを付けた関数を、photonViewのRPC関数で呼び出す。

[PunRPC]
private void RPCHoge(string hoge) {}
photonView.RPC(nameof(RPCHoge), RpcTarget.All, “hoge”); // 呼び出し

Fusion

[Rpc]アトリビュートを付けた関数を、普通の関数のように呼び出せる。ただし関数名には「Rpc_」プリフィックスが必要。

PUN2の時に、RPC呼び出し時に指定していた受信対象(RpcTarget.All)は、定義の時に指定する。
追加で、RPCを呼び出せるユーザーの指定(RpcSources.All)もする。

[Rpc(RpcSources.All, RpcTargets.All)]
private void RPC_Hoge(string hoge) {}
RPC_Hoge(“hoge”); // 呼び出し

 

位置の同期

今回利用していないので、概要は分かっていますが合っているか分からないので割愛します。

 

 

Fusionのハマりどころ

ネットワークオブジェクト

Fusionは、ネットワークで共有する変数として、ネットワークプロパティという仕組みが新しく用意されています。

一見シンプルになってる?と思いきや、ネットワークプロパティはNetworkBehaviourを継承して、NetworkObjectをAdd Componentしたネットワークオブジェクトを用意して、その中に定義しないといけないので、何もしなくてもすぐ使えたPUN2のカスタムプロパティと比べると大分複雑です。
RPCもネットワークオブジェクト内にしか定義できません。

またネットワークオブジェクトには、NetworkRunnerのSpawnメソッドで生成して、Spawnedが呼ばれるまではアクセスできません。ここも分かるまで戸惑いました。

権限

PUN2にはなかったものとして、StateAuthorityという変更権限の概念が追加されています。そのため最初に接続したプレイヤー(Host)しか共有する変数を変更できないので、みんなでワチャワチャ自由に共有する変数を変更出来てたPUN2の感覚で取り組むと戸惑います。

MonoBehaviourPunCallbacksを継承したクラスを用意して後はその中に適当に処理を書けば割と思い通りの動きをしていたPUN2と違い、権限やネットワークオブジェクトなど、ちょっと厳密になった部分を把握できれば、後はすんなり作れそうです。

 

以下のPhoton運営事務局中の人にいつのまにかなっていたo8queさんの記事を何回も読みながら実装をしていれば、一通りFusionを把握できると思います。