[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() メソッドを使ったオブジェクト同期(相応の独自実装可能なプログラミングスキルが必要)