《游戏编程模式》笔记——脏标志模式
意图
将工作延期至需要其结果时才去执行,避免不要的工作。
模式
一组原始数据随着时间变化而改变。使用昂贵的过程退定一组导出数据。一个“脏”标志追踪导出数据是否与原始数据保持一致。它在原始数据改变时被设置。如果导出数据被请求时,该标识被设置了,那么重新计算并清除标识,否则使用之前缓存的导出数据,
何时使用
脏标识主要应用在“计算”和“同步”两个任务中。
应用场景:
原始数据的变化速度远高于导出数据的使用速度。
增量更新十分困难。
设计决策
什么时候情况脏标识?
当结果被请求时:
如果不需要结果,可以避免计算。如果原始数据变化的速度比推到数据获取的速度快的多,使用脏标识模式效果明显。
如果计算消耗大量时间,会造成可察觉的卡顿。将工作推迟到玩家想要结果的时候会严重影响游戏体验。
在精心设计的检查点处:
有时,某个时间点或在游戏过程中很自然的需要推迟处理。如果同步点不是游戏机制,我们可以将这些工作隐藏在加载画面或者过场动画中。
这种工作不会影响到玩家体验。
但是也丧失了控制权,我们不能保证玩家真的到了检查点或者满足了定义的条件。
在后台处理:
可以使用固定时长的的计时器来处理。
通过调节计时器可以控制工作的频率。
如果原始状态在两个处理的间隔之间只改变了很少的部分,最终大部分处理的都是没有改变的数据,造成冗余工作。
后台处理意味着玩家同时可以正常游玩,意味着我们需要线程或其他并行支持,也要考虑并行修改的安全性。
脏追踪的粒度有多细?
假设我们有一个房间,为每个地板砖都加上一个脏标识。
如果粒度更细:
我们只需要处理真正改变的数据,只需要将修改的数据发送到服务器。
摆十张桌子就需要修改十份数据。
如果粒度更粗:
我们为房间都增加一个脏标识,改变房间里的任何东西都会让房间变脏。
最终需要处理没有变化的数据,在房间摆放一个桌子就需要发送整个房间的数据到服务器。
但脏标识使用的内存更少,即使摆上二十张桌子也只需要一个脏标识。
参加
Angular的浏览器方向框架中可以见到这种模式,使用脏标识追踪哪个数据在浏览器中被改变了,需要将其推向服务器。
物理引擎追踪哪些对象在休息哪些对象在移动。由于休息的骨骼直到有力施加在上面才会移动,才需要处理,“正在移动”就是一个脏标识,标注哪个对象有力被施加并需要物理解析。
参考
《游戏编程模式》