物理パフォーマンスと最適化
はじめに
リアルタイムのインタラクションが発生するマルチプレイヤーゲームは、プレイヤーにできるだけスムーズな体験を与えるため、ゲームのパフォーマンスが非常に重要になります。
物理演算は、必ずしもパフォーマンス問題の原因になるわけではありませんが、様々な状況でボトルネックになりえます。
プロファイリング
作業を始める前に、問題が実際に物理システムで引き起こされているかどうかを確認してください。
Quantum Graph Profiler
Quantum Graph Profiler
は、すべてのシステムのパフォーマンス・グラフィックス・Unityスクリプトをプロファイリングするツールです。これは主に、Unity関連の要素がパフォーマンス問題を引き起こしているかどうかを特定するのに役立ちます。
Task Profiler
このツールは、Quantumシミュレーションの各システムの実行時間を評価するために使用されます。
一般的に、このツールで物理関連の問題を検知できない場合、直面している問題は物理関連ではないかもしれません。
Quantumでのプロファイリングの詳細は、プロファイリングをご覧ください。
ブロードフェーズの最適化
物理エンジンは、システム設定内の各システムによってスケジュールされる一連のタスクです。各フレームで、これらのタスクは次のように実行されます。
シミュレーション内の物理コンポーネントを持つエンティティについて、物理エントリを作成し、それらを収集します。
ブロードフェーズ:詳細な評価を必要とする潜在的に重なっているペアを検知します。このステップは、検知にO(n²)のブルートフォースを避けるために重要です。
ナローフェーズ:ブロードフェーズで検知した候補を評価し、実際に重なっているペアを特定します。このステップは、ブロードフェーズでフィルタリングされた潜在的な候補の数に比例して高負荷の数学計算が行われます。
反復法ソルバーを使用して、速度と位置の制約を解決します。
力と速度の積分・静止剛体を検知し、ブロードフェーズのクエリを解決します。
大半のタスクの負荷は、エントリ数やエントリ間のインタラクション量に比例します。
したがって、動的エントリ数を削減する方法は、動かない動的コライダーを静的コライダーに切り替えることです。
静的コライダーについての情報は、静的コライダーをご覧ください。
もう一つの方法は、剛体間のインタラクション量の削減で、物理レイヤーやクエリオプションを使用します。
2D/3Dの衝突マトリックスは、UnityからインポートされてSimulation Config
で利用できます。

ワールドとバケットサイズ
物理設定の詳細な情報は、設定をご覧ください。
World Size
は、QuantumMapData
コンポーネントでベイクされるMap
アセットのフィールドで、物理エンジンにおけるプレイ可能エリアを定義します。
マップはBuckets
と呼ばれるセクションに分割され、ブロードフェーズ・ナローフェーズのクエリ解決に使用されます。
World Size
World Size
は、ゲームのプレイ可能エリアサイズにできるだけ近い値に合わせることで、効率が向上します。

左の画像では、World Size
が実際のゲームプレイで使用されるエリアより大きいため、バケットが均等に配置されず無駄になっています。右の画像では、オブジェクトがワールドエリアに均等に分散されています。
注意点として、必要以上にバケットを追加してもパフォーマンスは向上せず、バケットが少なすぎると評価対象のエントリが多くなりすぎます。最初または最後のバケットにエントリが多すぎると、パフォーマンスに大きな影響を与えます。
パフォーマンスはTask Profiler
で測定し、最適な値に調整してください。
備考:ワールドサイズ外にあるものは、最初または最後のバケット(の近い方)に分類されます。
Bucket Subdivisions
Bucket Subdivisions
は、通常の物理クエリの効率化に使用されます。通常のクエリを使用せずに、ブロードフェーズクエリのみを使用するゲームの場合、分割数を0に設定できます。
そうでなければ、QuantumMapData
コンポーネントのデフォルト値が、大抵のケースで十分な値です。
Bucketing Axis
ワールドサイズの分割軸によって、ゲーム内オブジェクトの分布に応じてパフォーマンスを向上できます。

左側の画像では、5つのエントリがあるバケットがある一方、右側のバケットには3つのエントリしかありません。
そのためこの画像の場合、 Bucketing Axis
を水平に設定することで、剛体がバケット全体により均等に分散されます。
備考:この例のように、エントリ数が少ない場合は変更の影響は最小限ですが、エントリ数が数百~数千に増えた場合は大きな影響が生じます。
トライアングルのセルサイズ
備考:これは3Dゲームにのみ関連します。
トライアングルのセルサイズは、3D静的コライダーのトライアングルが分割されるセルサイズを定義します。動的エンティティと静的メッシュ間の衝突は、対応するセルと隣接セルでのみ評価されます。
これを最適化するには、
- セルごとのトライアングル数が過多にならないようにする。
- セル数が過多にならないようにする。
テレインやメッシュコライダーのトライアングル密度を適切に設定してください。これらは、物理エンジンのパフォーマンスに重要な役割を果たします。メッシュによっては、表示用と同じメッシュを使用するのではなく、コライダー用に簡略化した別のメッシュを作成することを検討しましょう。
これらを可視化するには、QuantumGameGizmosSettings
の関連フィールドを有効にしてください。

シミュレーション実行の最適化
Quantumの物理エンジンは、様々な機能のためにスケジュールされた複数のステップを実行しますが、ゲームによってはすべてのステップが必要になるわけではありません。
SimulationConfig
アセットで、これら機能を個別に無効にすることができます。

静止剛体
長時間動く必要がないオブジェクトがある場合、それらをスリープ状態にして、力・速度・積分・衝突判定をスキップできます。このオプションは、SimulationConfig
アセットで有効にできます。
ゲーム内に長時間動く必要がないオブジェクトがある場合、それらはスリープ状態にし、力、速度、統合、および衝突検出をスキップします。このオプションは、SimulationConfig
アセット内で有効にすることができます。

ソルバーの反復回数
SimulationConfig
アセットのSolver Iterations
フィールドは、物理エンジンの制約(衝突やジョイントなど)を解決するために使用される反復回数を表します。
デフォルト値は4で、通常は大抵のケースで問題ありません。必要な精度に応じて、値を増減することもできます。
レイキャストの最適化
毎フレーム多くのレイキャストを実行する場合、それらを適切に最適化することが重要です。
以下はその具体的な例です。
- レイヤーマスクを追加して、不要なオブジェクトとの衝突を避ける。
- レイキャスト距離をできるだけ小さくして、不要な衝突を避ける。
- 最初の衝突のみが重要な場合は、
RaycastAll
のかわりにRaycast
を使用する。 Raycast
メソッドでQueryOptions
を利用して、不要なものに衝突しないようにする。
QueryOptions
の詳細はクエリをご覧ください。
ブロードフェーズクエリ
前述の通り、ブロードフェーズクエリをクエリの最適化に使用できます。詳細はブロードフェーズクエリをご覧ください。
Back to top