予測カリング
イントロダクション
SDKの最小バージョン: 1.2.3c
予測カリングを使うと、プレイヤーが持つゲームシーンが1パーシャルのみのゲームにおいて開発者はCPU時間の節約をすることができます。
Quantumの予測とロールバックには時間がかかります。そして実行されるのはローカルプレイヤーに対して表示される重要なエンティティにのみです。チックごとにに一度だけ、サーバーが入力を確認したらロールバックせずに、すぐシミュレーションするようエリアの外側に全てを置いておきます。
予測カリングの有効化は安全かつ簡単で、パフォーマンスはゲームによって大きく異なります。確認された入力の全てに対してコンスタントに10チックロールバックする30Hzのゲームを想像してみてください(プレイヤーが多くなると、予測因子は入力を見逃してしまいます)。この場合、ゲームシミュレーションは300Hzほどで稼働するのに十分軽量でなければなりません(ロールバックを考慮するため)。予測カリングを有効にしておくと、フレーム全体が常に期待される30Hzでシミュレーションされるようになります。それよりも少ない予測エリアは予測バッファ内で動作する唯一のものです。
予測カリングを設定する
予測カリングを有効にするには以下の設定を行います:


予測カリングを行うと、予測されたシミュレーションはフレームの最終結果として受け入れられなくなります。これは予測カリングがゲームステート全体を進めるわけではないからです。Expose Verified Status In Simulation
を有効にしておくことで、入力の確認がサーバーから届くとQuantumが検証されたフレームの再シミュレーションを(設定の表示を伴って)強制的に行うことが保証されます。
全てのUnityアップデートでSetPredictionArea()
を呼び出し、予測エリアをアップデートします:
C#
// center is either FPVector2 of FPVector3, radius is an FP.
QuantumRunner.Default.Game.SetPredictionArea(center, radius);
これで設定完了です。
予測カリングによる効果
物理とNavmeshエージェント
予測カリングが有効になっていると、物理エンジンンとNavMeshエージェントシステムの両方が影響を受けます。これらが考慮しアップデートするのは、未検証(予測)フレーム内の可視領域にあるエンティティのみです。
ローカルマシン上で、予測エリアの中心点プラス半径で定義されたインタレストのエリアの外にある、対応するコンポーネント(DynamicBody、NavMeshAgent)を使用したエンティティに対して物理ブロードフェーズ、ナローフェーズのコリジョンチェックまたはソルバー、コリジョン回避もしくはエージェントのアップデートが実行されないため、CPUサイクルの節約になります。
イテレータ
Transform2D
またはTransform3D
のどちらかを含むタイプのエンティティイテレータへのあらゆるコードが、ポジションに応じて自動的にカリングされるので、予測カリングによって自分のコードも得することになります。
本質的に予測フレームがどこで実行されていたとしても、GetAllXXX()
への呼び出しが返すのは 制限の範囲もしくは予測の半径内のエンティティのみです。一方で、同じ呼び出しでも検証済のフレームをシミュレーションする際はアクティブなインスタンスの全てが返されます(入力の確認が届いた後)。
手動カリングコントロールフラグ
新しく(EntityFlagsに)追加されたカリングフラグを使って 手動でエンティティのカリングをコントロールすることもできます(もちろん、予測されたフレームのみです):
C#
public enum EntityFlags : int {
Active = 1 << 0,
DestroyPending = 1 << 1,
Culled = 1 << 2,
NotCullable = 1 << 3
}
自動カリングを無効にするには、エンティティにNonCullable
フラグを設定します:
C#
myEntity->Flags |= EntityFlags.NotCullable;
手動でインスタンスを(手動のカリングに使用する一時的な条件を認識している、他の何よりも前に実行する単一のシステムから)Culled
に設定します。同じシステムの検証済みフレームで de-flag を忘れないでください。そうすると一貫性のあるステートが維持され、非同期化が行われません。
C#
// setting entity to be culled by systems after this one:
myEntity->Flags |= EntityFlags.Culled;
// setting entity to not be culled:
myEntity->Flags &= ~EntityFlags.Culled;
RNGの問題を回避する
(エンティティ間で)共有のRNGSessionインスタンスを使用する際は気を付けてください(Quantum _globals_
に保管されているデフォルトのインスタンス)。RNGセッションが使われているコードをカリングと一緒に使用する場合は、2つの(RNGに影響を受ける動きを持つ)エンティティで同じセッションを共有するときに問題が生じる可能性があります。
これが非同期化につながることはありません(なぜなら、検証されたフレームは予測であると保証されているからです)。ただし、検証済みのフレームがようやくシミュレーションされた後、予測されたエンティティに新しいRNG値による最終ポジション調整が入るため目に見えるジッタが発生する可能性があります。
この解決策としては、隔離したRNGSession structsをカリングするエンティティのサブジェクトに保管することです。シードを好きな方法でインジェクトすることができますが、隔離するとカリングが予測されたエンティティの最終ポジションを変更しないようにできます(ロールバックによる場合は別です):
chsarp
entitiy Actor[32] {
fields {
RNGSession MyRNG;
}
}
Back to top