物理パフォーマンスと最適化
イントロ
リアルタイムのインタラクションが発生するマルチプレイヤーゲームでは、プレイヤーに可能な限りスムーズな体験を提供するために、ゲームのパフォーマンスが非常に重要になります。
物理演算が常に原因というわけではありませんが、物理演算がボトルネックになることはよくあります。
プロファイリング
これ以上何かをする前に、問題が実際に物理システムに起因していることを確認したい。
Quantum Graph Profiler
Quantum Graph Profiler
は、グラフィックスやUnityスクリプトだけでなく、すべてのシステムのパフォーマンスをプロファイリングするツールです。これは主に、Unity関連の何かがパフォーマンスの問題を引き起こしているかどうかを判断するのに役立ちます。
タスクプロファイラ
このツールは、 Quantum Simulation の各システムの実行時間を評価するために使用します。
一般的に、これらのツールで物理に関連するものが検出されない場合、あなたが直面している問題はおそらく物理ではありません。
Quantumのプロファイリングの詳細については、以下を参照してください: Profiling
ブロードフェイズの最適化
物理エンジンは、システムセットアップでそれぞれのシステムによってスケジュールされた一連のタスクです。
各フレーム、これらのタスクは:
シミュレーション内の物理コンポーネントを持つエンティティの物理エントリを作成し、エントリを収集します。
ブロードフェーズ: 詳細な評価を行うために、重複する可能性のあるペアを検出します。このステップは、総当たり的な O(n2) 検出を回避するために重要です。
狭相: 前のブロードフェーズ候補を評価し、どれがオーバーラップするかを定義する。このステップは、ブロードフェーズでフィルタリングされた候補の数に比例する。このステップでは高価な計算を行います。
反復ソルバーを使って速度と位置の制約を解決します。
力と速度を統合し、スリーピングボディを検出し、以前のブロードフェーズクエリを解決します。
これらのタスクのほとんどは、エントリー数またはエントリー間の相互作用の量に比例してリニアにスケールします。
したがって、動的エントリーの量を減らす方法は、動かない動的コライダーを静的コライダーに変えることです。
Static Collidersに関する情報は以下を参照してください: 静的コライダー
もう一つの方法は、例えば物理レイヤーやクエリオプションを使って、ボディ間の相互作用を減らすことです。
Collision matrixの3Dと2DはUnityからインポートされ、Simulation Config
で利用できます。
ワールドとバケットサイズ
物理設定の詳細については、以下を参照してください: Settings
World Size
は MapData
コンポーネントによってベイクされる Map
アセットのフィールドです。物理エンジンでプレイ可能なエリアを定義します。
マップは Buckets
と呼ばれる一連のセクションに分割されます。これらは、広いフェーズと狭いフェーズのクエリを解決するために使用されます。
World Size
World Size
は効率的であるために、ゲームのプレイアブルエリアのサイズとできるだけ一致させるべきです。
最初の画像では、World Size
がゲームプレイで実際に使用される領域よりも大きい。バケットは等間隔に配置されておらず、無駄になっています。2番目の画像では、オブジェクトはワールドの領域に均等に広がっています。
重要なことは、必要以上にバケットを増やしても性能は上がりませんし、バケットが少なすぎると評価する項目が多くなりすぎるということです。最初のバケットや最後のバケットに多くのエントリがあると、パフォーマンスに大きく影響します。
Task Profiler
を参照してパフォーマンスを評価し、あなたのケースに最適な値を調整してください。
注意:ワールドサイズの制限から外れているものは、最初か最後のバケット(近い方)にあるとみなされます。
Bucket Subdivision
Bucket Subdivisionは、通常の物理クエリをより効率的にするために使われます。もしあなたのゲームが通常のクエリを使わない場合、例えばBroad-phase Queriesだけを使う場合、サブディビジョンカウントを0に設定することができます。
そうでない場合は、MapData
コンポーネントで提供されるデフォルト値で十分です。
バケット軸
ワールドサイズのサブディビジョンの軸は、ゲーム内のオブジェクトがどのように分布しているかによって、パフォーマンスを向上させることができます。
左の画像では、いくつかのバケットには5つのエントリーがありますが、右の他のバケットには3つしかありません。
そのため、この画像では Bucketing Axis
を水平に設定すべきです。なぜなら、物理体がバケットに均等に分散されるからです。
注意: この例では、数個のエントリーしかないので、変化は最小限です。ただし、数百、数千のエントリーにスケールアップした場合は、間違いなく重要になってきます。
Triangle Cell Size
注意:これは3Dゲームにのみ関係します。
Triangle Cell Size は、3D 静的コライダー三角形を分割するセルのサイズを定義します。
ダイナミックエンティティとスタティックメッシュの衝突は、対応するセルと隣接するセルのみで評価されます。
これを最適化するには:
- セルあたりのトライアングルの数が多すぎないようにする。
- セルの数が多すぎないようにする。
地形とメッシュのコライダは 物理エンジンのパフォーマンスに重要な役割を果たすので、適度な三角形の密度を維持する必要があります。このため、メッシュによっては、ビューに同じメッシュを使用するのではなく、コライダのために2つ目の簡略化されたメッシュを作成することをお勧めします。
これらを視覚化するには、QuantumEditorSettings
で関連するフィールドを有効にします。
シミュレーション実行の最適化
Quantumの物理エンジンは、多様な機能のために複数のスケジュールされたステップを実行します。しかし、ゲームによってはそのすべてが必要とは限りません。
SimulationConfig
アセットで、これらの機能を個別に無効にすることができます:
休息オブジェクト
ゲーム中に長時間動く必要のないオブジェクトがある場合、それらをスリープ状態にし、力、速度、積分、衝突判定をスキップします。このオプションは SimulationConfig
アセットで有効にできます:
ソルバーの反復回数
SimulationConfig
アセットのSolver Iterations
フィールドは、衝突や関節などの物理エンジンで使用される制約を解くために使用される反復回数を表します。
デフォルト値は4で、ほとんどの場合はこれで問題ありません。しかし、必要な精度に応じて増減させることができます。
レイキャストの最適化
各フレームで多くのレイキャストが発生する場合、それらが正しく最適化されていることを確認することをお勧めします。
例えば:
LayerMaskを追加して、重要でないオブジェクトとの不要な衝突評価を避ける。
レイキャストの距離をできるだけ小さくして、不要な衝突評価を避ける。
最初の衝突だけを気にする場合は
RaycastAll
の代わりにRaycast
を使う。Raycastメソッドで
QueryOptions
を使って、関係ないものにぶつからないようにします。
QueryOptions
の詳細については、以下を参照してください: Queries
ブロードフェーズクエリー
上述したように、broadphaseクエリはゲーム内のクエリを最適化するために使用することができます。詳しくは Broad-phase Queries を参照してください。
Back to top