予測カリング
はじめに
予測カリング は、プレイヤーが常にゲーム世界の一部しか視認できないゲームで使用されます。安全に使用でき、簡単にアクティブにすることができます。
予測カリング は、量子予測およびロールバックフェーズ中にCPU時間を節約することを可能にします。これを有効にすると、予測者はローカルプレイヤーにとって重要かつ視認可能なエンティティのみを対象に専任して実行され、視界外のエンティティはサーバーによって入力が確認された後に1ティックごとに一度だけシミュレーションされるため、可能な限りロールバックを回避することができます。
ゲームごとにパフォーマンス向上の効果は異なりますが、その効果は非常に大きくなることがあります。これは、ゲームがサポートするプレイヤー数が増えるほど重要であり、最終的には予測者が少なくとも1人のプレイヤーを見逃すことになるためです。
例えば、30Hzのシミュレーションレートで動作しているゲームを考えてみてください。ゲームが確認された入力ごとに平均10ティックのロールバックを必要とする場合、ゲームのシミュレーションはロールバックを含めて300Hz近くで動作できるほど軽量である必要があります。予測カリング を使用すると、全フレームは常に期待される30/60Hzでシミュレーションされ、カリングは予測バッファ内で動作している予測エリアに適用されます。
予測カリングの設定
その結果、予測カリング を使用すると、予測されたシミュレーションはフレームの最終結果として決して受け入れられません。なぜなら、その一部がカリングされたため、ゲーム全体の状態のシミュレーションが進まなかったからです。
予測カリングを設定するには、2つのステップがあります。1つはQuantumで、もう1つはUnityで行います。
Quantumでの設定
デフォルトでは、予測カリングシステムは、Assets/Photon/Quantum/Samples/SampleScenes/Resources
にあるサンプルシステム設定アセットで既に有効になっています。

Unityでの設定
Unityでは、予測エリアを設定する必要があります。これは、どのエンティティを予測からカリングするかを決定するために使用されます。
毎回のUnityの更新で SetPredictionArea()
を呼び出して予測エリアを更新します。
C#
// center is either FPVector2 or FPVector3
// radius is an FP
QuantumRunner.Default.Game.SetPredictionArea(center, radius);
期待されること
物理エンジンとナビメッシュエージェント
物理エンジンおよびナビメッシュ関連システムは、予測カリング の影響を受けます。
予測カリング が有効な場合、これらは非検証(すなわち予測)フレームにおいて、可視エリア内のエンティティのみを考慮し、更新します。
物理およびナビメッシュ関連エージェントは、関連コンポーネント(PhysicsCollider、PhysicsBody、NavMeshPathFinder、NavMeshSteeringAgent、NavMeshAvoidanceAgent)を持ちながら、ローカルマシン上の予測エリアの中心点と半径で定義された興味の領域の外にあるエンティティについての更新をスキップするため、CPUサイクルが節約されます。
イテレーター
ゲームコードも 予測カリング の恩恵を受けます。Transform2D
または Transform3D
を含む任意のフィルターは、その位置に基づいてカリングの影響を受けます。
実際、予測フレームが実行されているときに、以下のメソッドのいずれかを呼び出すと、予測半径の範囲内にあるエンティティのみが返され、一方、入力確認後に検証されたフレームをシミュレーションする際には、同じ呼び出しがすべてのアクティブインスタンスを返します。
f.Filter()
f.Unsafe.FilterStruct()
注意: フィルター は 予測カリング の恩恵を受けますが、コンポーネントイテレーター は受けません。
f.GetComponentIterator()
f.Unsafe.GetComponentBlockIterator()
手動カリング制御フラグ
APIを介して予測フレーム上でエンティティをカリングするために手動でフラグを設定することも可能です。
メソッド | 説明 | |
---|---|---|
SetCullable(EntityRef entityRef, bool cullable) | エンティティがカリング可能かどうかを設定します。エンティティが存在しない場合(無効なエンティティ参照を含む)には何もしません。 | |
IsCulled(EntityRef entityRef) | エンティティが現在シミュレーションからカリングされているかどうかを確認します。フレームの状態(予測されたものか検証されたものかに関わらず)。
エンティティがカリングされている場合(例えば、予測エリア内に存在しない場合)は True になります。また、存在しない場合も True です。 それ以外の場合(エンティティが存在し、カリングされていない場合)は False です。 |
|
Culled(EntityRef entityRef) | エンティティが予測カリングされているかどうかを確認します。
フレームが予測されたものであり、かつエンティティがカリングされている場合は True になります。 それ以外の場合(フレームが検証されたものであるか、エンティティがカリングされていない場合)は False です。 |
|
Cull(EntityRef entityRef) | カリング可能で存在しているエンティティをこのティックのために手動でカリングとしてマークします。 | エンティティが存在しないか、カリング可能でない場合には何もしません。 |
ClearCulledState() | そのフレーム上のすべてのエンティティのカリング状態をリセットします。 | 自動的に毎フレームのシミュレーション開始時に呼び出されます。 |
一貫した状態を保ち、非同期の問題を避けるために、検証されたフレーム上でカリングされたエンティティのフラグを元々フラグを立てた同じシステム内で解除してください。これにより、一貫した状態を保ち、非同期問題を回避できます。
RNGの問題を避ける
予測カリング と共に RNGSession インスタンスを使用することは完全に安全であり、決定論が保証されます。しかし、2つのエンティティがQuantumの_globals_
に保存されているデフォルトのRNGSessionを共有する場合、視覚的なジッターが発生することがあります。これは、検証済み フレームのシミュレーション後に 予測された エンティティに新しいRNG値が生成され、エンティティの最終位置が変更または修正されるためです。
解決策として、カリング対象の各エンティティに孤立したRNGSession構造体を格納することです。この孤立により、ロールバックが実際に必要でない限り、カリングは予測されたエンティティの最終位置に影響を与えないことが保証されます。
C#
struct SomeStruct {
RNGSession MyRNG;
}
各RNGSessionには、任意の方法でシードを注入できます。
Back to top