Prediction Culling
簡介
預測剔除(Prediction Culling) 用於玩家在任何時候只能看到遊戲世界部分視圖的遊戲中。它使用安全且易於啟用。
預測剔除 可以在 Quantum 的預測和回滾階段節省 CPU 時間。啟用它後,預測器將僅針對本地玩家可見的重要實體運行,而視圖之外的任何內容僅在伺服器確認輸入後每幀模擬一次,從而盡可能避免回滾。
儘管不同遊戲的性能收益有所不同,但收益可能相當可觀;這一點在遊戲支持的玩家數量越多時尤為重要,因為預測器最終至少會對其中一個玩家的預測出現偏差。
例如,一個以 30Hz 模擬速率運行的遊戲。如果該遊戲每個確認的輸入平均需要十次回滾,這意味著遊戲模擬必須足夠輕量級,才能接近 300Hz 運行(包括回滾)。使用 預測剔除,完整幀將始終以預期的 30/60Hz 進行模擬,並且剔除將應用於在預測緩衝區內運行的預測區域。
設置預測剔除
因此,使用 預測剔除 意味著預測的模擬永遠不能作為一幀的最終結果,因為部分內容已被剔除,因此它不會推進整個遊戲狀態的模擬。
設置預測剔除分兩步:一步在 Quantum 中,一步在 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);
預期效果
物理和導航網格代理(Navmesh Agents)
物理引擎和與導航網格相關的系統會受到 預測剔除 的影響。
當 預測剔除 啟用時,它們在非驗證幀(即預測幀)上將只考慮和更新可見區域內的實體。
CPU 週期得以節省,因為物理和導航網格相關代理會跳過對任何具有相關組件 (PhysicsCollider, PhysicsBody, NavMeshPathFinder, NavMeshSteeringAgent, NavMeshAvoidanceAgent)且在本地機器上由預測區域中心點和半徑定義的關注區域外的實體的更新。
迭代器(Iterators)
遊戲代碼也可以從 預測剔除 中受益。任何包含Transform2D或Transform3D的過濾器都會根據其位置進行剔除。
本質上,當運行預測幀時,調用以下任何方法都只會返回在預測半徑範圍內的實體,而在輸入確認到達後模擬驗證幀時,相同的調用將返回所有活動實例。
f.Filter()f.Unsafe.FilterStruct()
注意: 雖然 過濾器 受益於 預測剔除,但 組件迭代器 卻 不能。
f.GetComponentIterator()f.Unsafe.GetComponentBlockIterator()
手動剔除控制標誌
也可以通過 Frame 提供的 API 在手動 標記 實體以在預測幀上進行剔除。
| 方法 | 描述 | |
|---|---|---|
| SetCullable(EntityRef entityRef, bool cullable) | 設置實體是否可被剔除。如果實體不存在(包括無效的實體引用),則不執行任何操作。 | |
| IsCulled(EntityRef entityRef) | 實體當前是否從模擬中被剔除,無論幀狀態(預測或驗證)如何。
如果實體被剔除(例如,不在預測區域內)或不存在,則返回 True。 否則返回 False(如果實體存在且未被剔除)。 |
|
| Culled(EntiyRef entityRef) | 實體是否被預測剔除。
如果幀處於預測狀態且實體 IsCulled,則返回 True。 否則返回 False(如果幀處於驗證狀態或實體未被剔除)。 |
|
| Cull(EntiyRef entityRef) | 在本幀手動將可被剔除且存在的實體標記為已剔除。 | 如果實體不存在或不可被剔除,則不執行任何操作。 |
| ClearCulledState() | 重置該幀上所有實體的剔除狀態。 | 在每幀模擬開始時自動調用。 |
為了保持一致的狀態並避免不同步,請在最初標記實體的相同系統中,在驗證幀上對已剔除的實體進行 取消標記,以保持一致的狀態並避免不同步。
避免RNG問題
將 RNGSession 實例與 預測剔除 一起使用是完全安全的,並且可以保證確定性。但是,當兩個實體共享一個 RNGSession 時(例如 Quantum 的_globals_中存儲的默認實例),它們的組合使用可能會導致一些視覺抖動。這是因為在模擬 驗證 幀後,會為 預測 實體生成新的 RNG 值,從而改變實體的最終位置。
解決方案是在每個可能被剔除的實體中存儲一個獨立的 RNGSession 結構。這種隔離保證了除非實際需要回滾,否則剔除不會影響預測實體的最終位置。
chsarp
struct SomeStruct {
RNGSession MyRNG;
}
你可以以任何你想要的方式為每個 RNGSession 注入種子。
Back to top