😂

PhotonFusionのシーンオブジェクトがnetwork化されなくてハマった話

2023/09/28に公開
5

PhotonFusionをPUN2と使い勝手が一番近いshared Modeで利用していた際に、PUN2と同じような使い方をしてたら、ハマってしまった話です。

バージョン

Unity2022.2.2f1
PhotonFusion 1.1.8

ハマった問題

シーン内に直接networkObjectを置いたオブジェクト(シーンオブジェクト)をネットワーク化する際に、networkObjectを置いている同じシーン内でNetworkRunnerを生成し、セッションを開始するとそのオブジェクトはnetwork化されないという問題です。

networke化されない場合下のような状態になります。

問題といっていますが、PUN2と異なりそうゆう仕様だと思われます。

解決方法

シーンオブジェクトを置いているシーンの前に、シーンを一つ用意してnetworkRunnerを生成し、セッションを開始してから次のシーンにFusionの用意しているシーンローダーで遷移するとシーンオブジェクトとして生成されます。

追記:o8queさんから、discussionで解決策を指摘いただきました。

NetworkRunner.StartGame()の引数でSceneは設定してるでしょうか?
セッション開始時にシーンオブジェクトを生成するには、シーンオブジェクトを置いているシーンをSceneから指定する必要があります!

NetworkRunner.StartGame()の際に、StartGameの引数としてロードしたいSceneを指定すればシーンオブジェクトとしてnetwork化できるようです!
公式サイトにも、StartGameの引数としてシーンが入っているものがありました。
https://doc.photonengine.com/ja-jp/fusion/current/tutorials/host-mode-basics/2-setting-up-a-scene

詳細

シーンオブジェクトとは

シーンオブジェクトとは、シーンにあらかじめ配置してnetwork化させるnetworkObjectのことで、シーンに一つだけしかないネットワークオブジェクトを生成したいときに便利なものです。
例えば、独自のModelやNetworkManagerなどで利用します。
シーンオブジェクトとしてnetwork化されると、networkObjectの中の値のInSceneObjectにチェックが入ります。(↓参考画像)

o8queさんの記事でも紹介されています。

ネットワークオブジェクトはRunner.Spawn()で生成しても良いですが、あらかじめシーン上に配置したネットワークオブジェクトは、ホストがシーンを読み込んだ際にシーンオブジェクト(Network Scene Object)として自動的に生成されるため、シーンに一つ(または決まった数)しかないネットワークオブジェクトを生成したい時に便利です。

https://zenn.dev/o8que/articles/afe59cfb76404b

PUN2での仕様

PUN2での仕様では、このシーンオブジェクトというような呼び名はなかったものの同じようなことができ、その場合はネットワークに接続した際のシーンにおいてあるnetworkObject(PUN2の場合はphotonView)であっても、network化してくれていました。
これがハマった理由で、同じことができるはずだと思い込んでNetworkRunnerと同時に生成されるSceneManagerをちょっと改造してみたのですが、ネットワーク化することはできてもほかでエラーが出てしまい断念しました。

解決方法

解決方法は、上に先に書きましたがシーンを一つ最初に入れ、そこでnetworkRunnerを起動してからシーン遷移する事です。networkRunnerが走った状態でのシーン遷移には、NetwokrkRunner.SetActiveScene()というメソッドが用意されているので、そちらを利用する必要があります。

仕様なのか?→ たぶん仕様 そんなことはなかった。

PUN2のゲームを移植する場合、大きな変更が必要があるのですが、恐らく仕様だと思われます。
NetworkRunnerが生成されるときに生成されるSceneManagerをカスタムすればできるのかもしれませんが、そこまでは突っ込んでみれていません。

Discord上で、シーンオブジェクトについては結構議論が飛んでいるのですが。シーンロードがらみの回答が来ており、基本的にはシーンロード時がnetwork化のタイミングなのだと思われます。(もし、間違っていたらご教示ください。。)

↓ディスコードの回答の例
Seems like Spawned() isn't called on a scene NetworkObject though?

It should unless you are loading the scene incorrectly (not over the network scene manager)

追記:o8queさんから、discussionで解決策を指摘いただきました。

NetworkRunner.StartGame()の引数でSceneは設定してるでしょうか?
セッション開始時にシーンオブジェクトを生成するには、シーンオブジェクトを置いているシーンをSceneから指定する必要があります!

NetworkRunner.StartGame()の際に、StartGameの引数としてロードしたいSceneを指定すればシーンオブジェクトとしてnetwork化できるようです!
公式サイトにも、StartGameの引数としてシーンが入っているものがありました。
https://doc.photonengine.com/ja-jp/fusion/current/tutorials/host-mode-basics/2-setting-up-a-scene

おわりに

Fusionの実装自体は、sharedモードでは恩恵が少ないもののティックベースシミュレーションのおかげでメッセージ数をかなりコントロールしやすくなっていたり、値の共有もかなり楽になっているので今後もFusionを使っていけたらなと思っています。

Discussion

o8queo8que

NetworkRunner.StartGame()の引数でSceneは設定してるでしょうか?
セッション開始時にシーンオブジェクトを生成するには、シーンオブジェクトを置いているシーンをSceneから指定する必要があります!

やまゆやまゆ

こっちに返信できたんですね。すいません。
そして全く、関係ないところなんですがo8queさんにFusionのことで、少しお聞きしたことがあります。
もし、ご存じでしたら回答いただけたら嬉しいです。

内容的には、Fusionの秒間メッセージ数をどのように測ればよいか。ということです。
いまFusionStatsのavg per secondをavg per Sampleで割った数が大体メッセージ数だと認識していて500メッセージ超えるか見ているのですが、これで正しいでしょうか?
もしくは、ほかにメッセージ数を見る方法があれば教えていただけたら嬉しいです。

o8queo8que

これはそもそもなのですが、現在のFusionではメッセージ数制限がなくなっているので、計測すること自体の必要が無くなっているという感じです!

だからと言って無茶な通信をすれば、ゲームの動作が不安定になったり、転送量超過料金が発生するという所は変わらないので、その辺りをFusionStats等で確認して調整するのが良いかと思います。

やまゆやまゆ

なるほど!そうなんですね。
PUN2と比べると、すごく大きなアドバンテージですね。

ご回答ありがとうございます!

やまゆやまゆ

コメントありがとうございます!

設定してないです。。
StartGame時にシーンを指定できるんですね!
(よく見たら、ここのサンプルにもSceneを指定してますね。。)
https://doc.photonengine.com/ja-jp/fusion/current/tutorials/host-mode-basics/2-setting-up-a-scene

記事の解決策として追記しておきます。

いつも質の高い記事を投稿とてもいただき助かっています。
ご指摘ありがとうございました。