[Tips] オブジェクト同期の送信量・頻度の軽減

目次

  概要
  Tips(1) : シーン内に存在する「MonobitView コンポーネント」を持つオブジェクトは極力減らす
  Tips(2) : シーン内の静的オブジェクトの中で「MonobitView コンポーネント」を持つオブジェクトは複数用意しない
  Tips(3) : 「MonobitTransformView」「MonobitAnimatorView」よりも「OnMonobitSerializeView()」 を使った方が得策


概要

オブジェクト同期に関するパフォーマンス改善方法について

  ここでは、オブジェクト同期の送受信処理にてパフォーマンスの低下が感じられる場合、
  MUN クライアント側で対処可能なテクニックについて紹介します。

  当然のことながら、オブジェクトの同期に関する送信データを削減すればパフォーマンスは向上します
  ここではそれ以外の、オブジェクト同期に伴うスパイク(大きな負荷)への対策として、効果的な手段を触れたいと思います。


Tips(1) : シーン内に存在する「MonobitView コンポーネント」を持つオブジェクトは極力減らす

MonobitView コンポーネントが付加されているだけで、オブジェクト同期通信自体が処理されてしまうので、それを避ける

  オブジェクト同期処理は「MonobitTransformView」または「MonobitAnimatorView」のコンポーネントを
  同時に追加することにより、位置・向き・アニメーションなどの『目に見える同期』を行ないます。

  が、実はこれらのコンポーネントが存在しない状態の、MonobitView コンポーネントさえ
  所有したオブジェクトについても、0バイトのオブジェクト同期データ通信を行なってしまいます。
    ※ 実際にはレコードのヘッダがありますので0バイトではありませんが、MUNで扱えるデータ実体としては0バイトです。

  そのため、オブジェクト同期で負荷が見られる場合、シーン内に存在する MonobitView コンポーネントを持つ
  オブジェクトの実数を減らすことがまず第一の目標です。
  MonobitView を無用に保持しないようにするだけで、パフォーマンス向上に繋がります。

  MonobitView コンポーネントを保持するオブジェクトが出来るだけ少なくなるように、シーンの静的オブジェクト、
  ならびに prefab の Inspector を精査してみてください。
【避けるべきこと】
  × 同期しない/同期する必要性のないオブジェクトに対し、「MonobitView コンポーネント」をアタッチすること
【推奨されるべきこと】
  〇 同期しない/同期する必要性のないオブジェクトに対し、「MonobitViewコンポーネント」を削除すること
  〇 1つのシーンに対し、「MonobitView コンポーネントを持つ静的オブジェクト」は1つだけにすること


Tips(2) : シーン内の静的オブジェクトの中で「MonobitView コンポーネント」を持つオブジェクトは複数用意しない

ルームホストに多大な負荷を掛けないようにする

  上述の Tips(1) にも記載しましたが、MonobitView コンポーネントを保持するだけで、そのオブジェクトの同期処理が実行されてしまいます。
  特にシーン内の静的オブジェクトで MonobitView を保持する場合、静的オブジェクトの所有権を持つルームホストにだけ、
  オブジェクト同期の負荷が掛かる状態になってしまいます。

  ルームホストはその特性上、ルーム内の諸々の制御(NPCやスコアなどの管理、衝突判定など)を含む場合が多々ありますので、
  できるだけルームホストに負荷を掛けないためにもMonobitView コンポーネントを持つシーン静的オブジェクト内は1つだけにすることが肝心です。
  複数の MonobitView コンポーネントを持つシーン静的オブジェクトを配置することは、パフォーマンス低下につながります。
【避けるべきこと】
  × 1つのシーンに対し、「MonobitView コンポーネントを持つ静的オブジェクト」を2つ以上作る
【推奨されるべきこと】
  〇 1つのシーンに対し、「MonobitView コンポーネントを持つ静的オブジェクト」を1つだけ作る


Tips(3) : 「MonobitTransformView」「MonobitAnimatorView」よりも「OnMonobitSerializeView()」 を使った方が得策

コンポーネントごとに処理を分離するよりも、単一の OnMonobitSerializeView() を実装して、独自の姿勢同期+補間を行なった方が良い

  MonobitTransformView コンポーネント、および MonobitAnimatorView コンポーネントにより、オブジェクトの位置・向き・アニメーションデータについて
  クライアント間で簡単に同期させることが出来ます。
  ですが、この2つのコンポーネントをアタッチして自動同期させるのは、以下の理由により、必ずしも効率の良い実装とは言い切れません。
・コンポーネントで固定のデータを送受信するので、データ量削減について柔軟な対応ができないこと
  (例えば、Transformの情報を送る場合、XZ座標のみ、XY座標のみ、Y軸回転量のみ、といったカスタマイズができない)
・補間処理について単純な線形補間しかないため、複雑な補間処理(スプライン補間など)が組み込めないこと
・2つ以上のコンポーネントを含める場合、別々のメソッドをコールすることになるので、若干ながらも効率が悪い。
  最も効果的なオブジェクト同期方法は、1つのスクリプト内で OnMonobitSerializeView() の接続コールバックメソッド を実装し、
  その中にMonobitTransformView や MonobitAnimatorView のコンポーネントの代替実装を行なうことです。
  それだけで、送受信データ量の最適化、メソッドコールの最速化、柔軟な姿勢同期+補間を実装することができます。

  ただし、独自実装ですので、ある程度のプログラミング技術が必要となります。
【避けるべきこと】
  × MonobitTransform , MonobitAnimatorView , MonobitPlayerMoveTemplete などのコンポーネントを活用したオブジェクト同期
【推奨されるべきこと】
  〇 単一の OnMonobitSerializeView() メソッドを使ったオブジェクト同期(相応の独自実装可能なプログラミングスキルが必要)