2.2.1 内存优化

预计算的视场遮罩是内存占用大的主要因素,假设整个场景大小为120m×120m,网格边长为1m,单位视野半径为12m,那么单个视场遮罩需要25×25个网格,可算得整个视场遮罩将消耗内存为120×120×25×25字节(B),约8.6MB内存。但考虑到视场遮罩中的数据只需标识网格是否可见,仅有两种状态,因此可以按位进行压缩存储。按位连续压缩后,整个场景的视场遮罩内存占用约为原来的1/8。

离线流程对整个场景网格进行了信息编辑,这些信息需要在运行时使用。如果信息内容较多并且将这部分信息直接保存在每一个网格上会产生冗余。从整个场景来看,没有任何信息的空属性网格数量占比最多,具有特殊属性的网格是以区域整体出现的,并且同一个区域内属性相同,因此可以做一个映射使场景网格仅保存简单的区域ID(AreaID),一般8比特长度即可,将具体区域信息保存至另一Map数据结构中,如图2.15所示。这样可以节省部分内存,优化收益受场景复杂度与信息复杂度影响。

图2.15 映射优化

视场遮罩是内存占用的最主要部分,它限制了网格精度的提升及视野范围的扩大。分析可得出,如果网格精度变为原来的倍,即网格尺寸减小为原来的。场景覆盖的网格数量会上升至原来的倍,单个网格视场遮罩尺寸也会上升至原来的倍,占用内存变为原来的倍。假设在前面提到的场景中,如果精度变为原来的2倍,即边长变为0.5m,即使经过按位压缩,也需占用约17MB内存,这样的消耗对于低内存移动端机型是有压力的。可以发现,对于多个网格在其视野范围内无视野阻挡的区域,非草丛网格的视场遮罩其实是相似的,可以进行合并,如图2.16所示。对于视野范围在这片区域中的非草丛网格,其视场遮罩数据等价于从图中截取相应部分数据,因此能够把大量的非草丛网格视场遮罩合并成一张图,在极端情况即整个游戏场景没有视野阻挡的情况下,这张图就是整个场景的二值图。

图2.16 视场遮罩合并

上述从合并图中提取视场遮罩图与离线预处理的视场遮罩图有些许差异,主要是由于离线预处理为了处理效率往往会考虑视野范围,仅对视野范围内的网格进行视线检测,而认为视野范围外的边缘区域是不可见区域。直接从合并图中提取出的视场遮罩边缘并没有根据视野范围进行处理,不过这并不会对最终结果产生影响,因为在运行时求探索源最终可见视野范围时会使用视野范围图与视场遮罩做与运算。

以上文中提到的项目为例,由于在项目、玩法中应用了无墙体阻挡视野机制,因此优化收益可以达到最大。离线视场遮罩内存占用优化前后的对比如图2.17的左图所示,由于实际项目内还有一些缓存辅助数据,因此会比理论计算出的高一些。可以看出,随着精度的增加,优化收益也会进一步上升,具体趋势见图2.17的右图,在此优化的加持下,高精度网格与大视野范围成为可能。

图2.17 内存占用对比