This document is about: PUN 2
SWITCH TO

PUN Classic (v1)、PUN 2、Boltはメンテナンスモードとなっております。Unity2022についてはPUN 2でサポートいたしますが、新機能が追加されることはありません。お客様のPUNプロジェクトおよびBoltプロジェクトが停止することはなく、将来にわたってパフォーマンス性能が落ちることはありません。 今後の新しいプロジェクトについては、Photon FusionまたはQuantumへ切り替えていただくようよろしくお願いいたします。

Optimization Tips

パフォーマンスの最適化

インスタンス化のプールオブジェクト

PUNには、読み込まれたリソースからではなく、プールからオブジェクトをインスタンス化するオプションが備え付けられています。(稼働速度を上げるため、メモリ上に保管されています。)インスタンス化に関するドキュメントページのプレハブプールの使用を参照してください。

RPCターゲットをキャッシュ

ゲーム内で大量のRPCを使用するケースもあるでしょう。
ターゲットGameObjectのあらゆるコンポーネントはRPCを実装することができるので、PUNはリフレクションを使用して適切なメソッドを見つけます。
もちろん、コンポーネントが変更されない場合は、これにはコストも手間もかかり無駄になります。

デフォルトで、PUNはスクリプトのタイプごとにMethodInfoリストをキャッシュします。
GameObject上で潜在的なターゲットであるMonoBehavioursはキャッシュしません。

PhotonNetwork.UseRpcMonoBehaviourCache = trueを設定して、RPCのPhotonView毎のMonoBehavioursをキャッシュできます。
これにより呼び出すコンポーネントを検出する速度が上がります。
GameObject上のスクリプトが変更されたら、必要に応じてphotonView.RefreshRpcMonoBehaviourCache()を呼び出しアップデートしてください。

ネットワークトラフィックの最適化

コンパクトなシリアル化

送信しているものとその方法を詳しく調べることで、トラフィックをかなり最適化できます。 これは、開発の後半で、多くの余分な手間をかけずに行うことができます。 最適化では通常どおり、最も頻繁に送信されるメッセージから始めます。

多くの場合、値とオブジェクトは、状態を共有するために必要な値よりも多くの値で送信されます。キャラクターがスケールできない場合、スケールを同期しないでください! キャラクターが横に傾かない場合、回転は単一のフロートになる可能性があります。実際には、精度を大幅に低下させることなく、1バイトでローテーションを行うことができます。 これは、非物理オブジェクトには適しています。

一般的に、 OnPhotonSerializeViewとRPCで何をするかを見てください。 OnPhotonSerializeViewごとに可変量の値を送信できます。 多くの場合、コンパクトなバイト配列を送信する方が、多くのカスタム型を登録して送信するよりも効率的です。

多くの手間をかけずに手間を省くツールがあります。 Network Transform Sync パッケージをご覧ください。 最適化されたトラフィックで高度な変換同期を提供します。送信するものを単純化する場合のオプションとしてはTransform Crusher - Free があります。

シリアル化に役立つ別のライブラリは NetStackです。他にもさまざまな便利な機能が備わっています。

ネットワークカリングとインタレストグループ

かなりの帯域幅を節約するもう1つの手法は、「ネットワークカリング」です。Interest Groupsを御覧ください。

Other Tips

すぐに送信

発生したRPCとイベントは、photonView.RPCまたはPhotonNetwork.RaiseEventを呼び出した瞬間には送信されません。
PhotonNetwork.LeaveRoomPhotonNetwork.SetMasterClientSetPropertiesのようなオペレーションリクエストの場合も同じです。
代わりに、定期的なルーチンが PhotonHandlerによって呼び出されるまでキューに入れられます(頻度は PhotonNetwork.SendRateを使用して設定されます)。
これにより、メッセージがより少ないパッケージに集約されてトラフィックのオーバーヘッドが回避されますが、多少の可変遅延が発生します。
この遅延を回避し、RPCまたはイベントをすぐに送信するには、次の行で PhotonNetwork.SendAllOutgoingCommands()を呼び出します。

これは、ゲームがこれらのメッセージのタイミングに依存している場合に意味があります。例:

  • タイミングの良い競争力のある雑学やクイズゲーム。早いほど良いです。
  • 相手があなたの番を待っている。

ただし、メッセージの送信など、これには他のユースケースがあります。

  • 切断する前
  • ルームを出る前
  • アプリを終了する前( OnApplicationQuit内)
  • アプリがバックグラウンドに移動するか、フォーカスを失う前(OnApplicationPause内またはOnApplicationFocus内)

これらの場合、次のことを知っておく必要があります。

  • OnApplicationQuitはすべてのプラットフォーム、たとえばAndroidで呼び出されるわけではありません。アプリケーションがシステムによって終了された場合、これは呼び出されません。
    代わりにOnApplicationPauseを使用できます。
  • 通常、パッケージの平均損失は1.2%です。
    信頼性のある送信を行った場合でも、再試行が必要になった場合にクライアントが応答しなくなったり、切断されたり、ルームに参加しなくなったりするため、送信したものが送信先に到着する保証はありません。
  • これらの場合に送信されるメッセージは、クライアントが複数のフラグメントを送信するのに十分な時間がないため、1つのパッケージに収まるように比較的小さくする必要があります。

Time.timeScale == 0中にPUNを一時停止しないでください

Time.timeScaleがゼロまたは低い場合でも、受信したメッセージをPUNでディスパッチできるようにするには、 PhotonNetwork.MinimalTimeScaleToDispatchInFixedUpdateTime.timeScale以上の値に設定します。
デフォルトでは、-1に設定されます。これは、 Time.timeScaleが0に等しい場合、受信したイベント(RPCを含む)または操作のレスポンスが処理されないことを意味します(コールバックも操作も実行を終了できません)。

Back to top