《游戲編程模式》筆記——臟標志模式
意圖
將工作延期至需要其結(jié)果時才去執(zhí)行,避免不要的工作。
模式
一組原始數(shù)據(jù)隨著時間變化而改變。使用昂貴的過程退定一組導出數(shù)據(jù)。一個“臟”標志追蹤導出數(shù)據(jù)是否與原始數(shù)據(jù)保持一致。它在原始數(shù)據(jù)改變時被設置。如果導出數(shù)據(jù)被請求時,該標識被設置了,那么重新計算并清除標識,否則使用之前緩存的導出數(shù)據(jù),
何時使用
臟標識主要應用在“計算”和“同步”兩個任務中。
應用場景:
原始數(shù)據(jù)的變化速度遠高于導出數(shù)據(jù)的使用速度。
增量更新十分困難。
設計決策
什么時候情況臟標識?
當結(jié)果被請求時:
如果不需要結(jié)果,可以避免計算。如果原始數(shù)據(jù)變化的速度比推到數(shù)據(jù)獲取的速度快的多,使用臟標識模式效果明顯。
如果計算消耗大量時間,會造成可察覺的卡頓。將工作推遲到玩家想要結(jié)果的時候會嚴重影響游戲體驗。
在精心設計的檢查點處:
有時,某個時間點或在游戲過程中很自然的需要推遲處理。如果同步點不是游戲機制,我們可以將這些工作隱藏在加載畫面或者過場動畫中。
這種工作不會影響到玩家體驗。
但是也喪失了控制權(quán),我們不能保證玩家真的到了檢查點或者滿足了定義的條件。
在后臺處理:
可以使用固定時長的的計時器來處理。
通過調(diào)節(jié)計時器可以控制工作的頻率。
如果原始狀態(tài)在兩個處理的間隔之間只改變了很少的部分,最終大部分處理的都是沒有改變的數(shù)據(jù),造成冗余工作。
后臺處理意味著玩家同時可以正常游玩,意味著我們需要線程或其他并行支持,也要考慮并行修改的安全性。
臟追蹤的粒度有多細?
假設我們有一個房間,為每個地板磚都加上一個臟標識。
如果粒度更細:
我們只需要處理真正改變的數(shù)據(jù),只需要將修改的數(shù)據(jù)發(fā)送到服務器。
擺十張桌子就需要修改十份數(shù)據(jù)。
如果粒度更粗:
我們?yōu)榉块g都增加一個臟標識,改變房間里的任何東西都會讓房間變臟。
最終需要處理沒有變化的數(shù)據(jù),在房間擺放一個桌子就需要發(fā)送整個房間的數(shù)據(jù)到服務器。
但臟標識使用的內(nèi)存更少,即使擺上二十張桌子也只需要一個臟標識。
參加
Angular的瀏覽器方向框架中可以見到這種模式,使用臟標識追蹤哪個數(shù)據(jù)在瀏覽器中被改變了,需要將其推向服務器。
物理引擎追蹤哪些對象在休息哪些對象在移動。由于休息的骨骼直到有力施加在上面才會移動,才需要處理,“正在移動”就是一個臟標識,標注哪個對象有力被施加并需要物理解析。
參考
《游戲編程模式》