EntityRef Hijacking
概述
實體參照 劫持 是一個術語,是在檢視中的預測——復原模型可能有的已知副作用的術語。
說明
有幾個移動部件在這之中發揮作用:
- 預測——復原;
- 實體建立;及,
- 實體檢視。
模擬不斷地預測接下來的幾幀。已預測幀 使用未經驗證的玩家輸入;當收到針對所有玩家的伺服器驗證輸入,Quantum就會模擬一個已驗證幀。
如果一個已預測幀需要 實體A 的建立,它會處理它並且接著指派一個「實體參照X」給它。如果與它關聯的EntityViewAsset
有它自己的Bind Behaviour
設定到 未驗證,在Unity中將在下一個OnUpdateView
回調建立檢視元素。
當從伺服器接收到已確認輸入,Quantum使用伺服器端已驗證資訊來重新模擬幀——這些是 已驗證 幀。這是有趣的地方。
如果在一個已預測幀還沒有的重新模擬幀中,在 實體A 之前已經建立另一個 實體B,則將重新指派「實體參照X」,因為實體參照是確定性的,並且按照順序給出。在這個情況下,實體A 被指派一個新的「實體參照Y」。
現在下列兩者之一將發生:
實體A 及 實體B 各自使用一個 不同的
EntityViewAsset
。針對 實體A 及其關聯的檢視,EntityViewUpdater
指令碼將偵測錯誤配對,銷毀它有的鏈結。當完成清除後,它接著將針對 實體A 及 實體B 建立一個新的檢視。實體A 及 實體B 使用 相同的
EntityViewAsset
。在下一個更新中EntityViewUpdater
指令碼將偵測錯誤對戰,破壞 實體A 及其檢視之間的鏈結,鏈接 實體B 到現有的檢視,並且針對 實體A 來具現化一個新的檢視。- 實體A 有一個新的檢視。該檢視使用正確的資料。
- 實體B 有一個先前與 實體A 關聯的檢視。該檢視以錯誤的資料被具現化,因此需要被更新。
實體檢視更新器注意事項:
EntityViewUpdater
指令碼透過快取一個實體參照及實體檢視資產鍵值對,來儲存在模擬及其檢視中的實體之間的鏈結。請參見EntityViewUpdater.cs
以取得更多資訊。
繫結行為注意事項:
如果一個實體檢視使用 已驗證 繫結行為,它只將在一個已驗證幀上被具現化,因此上述情形將永遠不會發生在其上。它是一個取捨,實體的「類型」決定了哪種行為更合適(請參見下述的 一般建議 章節)。
如何處理它
這種情況可以透過調整模擬或檢視來輕鬆解決。
在程式碼中
為了確保只在已驗證幀上建立實體,您可以包裝以下的條件敘述:
C#
if(f.IsVerified) {
// Do stuff
}
或是在未驗證(也就是已預測)幀上提前退出,方法是使用:
C#
if (f.IsPredicted == false)
return;
如果需要,也可以在OnPlayerDataSet
中使用API。
在Unity中
在檢視中,您可以選擇處理問題的方式有,修改初始化行為,或在檢視在它持有的資料中偵測到一個錯誤對戰時,讓檢視更新它自己。解決方案將取決於您是否設定了繫結行為到 已驗證 或 未驗證。
為了在Unity中更改 繫結行為,簡單地導航到位於與EntityViewAsset
關聯的預製件上的Entity View
指令碼,並且將其從 未驗證 切換到 已驗證。
繫結行為——已驗證
在這個情況下,從一開始就保證您有正確的資訊,並且您可以信任在Unity的Start()
方法時可用的資訊。也可以使用OnEntityInstantiated
實體檢視事件(請參見附加在預製件的實體檢視指令碼)。
繫結行為——未驗證
在這個情況下,在具現化時您可用的資訊可能是錯誤的。
為了保證檢視能夠反映這個更改,請確保檢視可以透過輪詢從Unity Update()
中設定自己。這樣的話,如果資料發生錯誤,它將能夠切換其資料。如果檢視完全獨立於模擬,並且已經持有了它需要的資訊,那麼就不需要採取這種預防措施,因為EntityViewUpdater
將已經透過銷毀及重新建立遊戲物件來糾正問題。
關於繫結行為的一般建議
兩個行為,已驗證 及 未驗證,有它們自己的優缺點。
Verified
:對於毫秒級準確具現化不是極端敏感的事情,比如玩家角色。Non Verified
:快速且玩家需要時間來做出反應的事情,比如拋射物。