转载请注明出处 何文西
前言
我们项目是一款45度俯视角的沙盒游戏,场景要求非常大,场景尺寸一般在1024X1024或者2048X2048。在技术上这么大规模的场景一次性加载必定带来效率问题,所以需要考虑到场景切割。项目需求里还要有天气系统,实时的昼夜系统。
综上所述会涉及到多个技术要点:
1 地形切割
有很多插件支持Mesh切割和Terrain切割。
如果自己要写切割代码,那么要注意切割后边缘顶点的法线和切线,还有地块之间的接缝问题。
2 地表分组
按照地形块分组,可以使用四叉树组织数据。
基于场景编辑器,每个地表元素对应我们resource资源表里的一个ID,例如一棵树,一块石头,一个物件等。
这样只需保存一个资源ID,位置,朝向,缩放,layer等信息。如果使用了光照贴图,还需要保存一下该位置地表元素的光照数据(光照索引和UV)。
地表数据可以保存在XML文件里或者自定义格式的二进制文件里。
考虑到加载效率优先保存为二进制文件。
3 光照贴图
使用一张Lightmap显然不合适,一般有2种方法,拆分地形后重新烘培或者切分烘培好的光照图。
注意如果切分光照图,那么场景里物件的光照图索引和UV都需要更新。
4 实时光照
这种方式最省心,当然效果不如光照图模式,而且会增加场景里的顶点数和Drawcall。
但是实现实时的昼夜系统最便捷,我们游戏的场景复杂度不是很高,且风格偏卡通,面数自然也不高,相机也是锁视角。
这种方式会优先考虑。
5 地块加载
采用九宫格加载最合适,一些3A级的游戏也有采用六边形地块加载模式,这种方式的优点是只需加载周边6个地块。
还可以采取一些缓存优化策略,缓存一定数量的地块,每次加载的地块做一个权重加成,位置也会影响权重加成,需要卸载的时候选择权重最低的。
光照探针是不支持动态加载的。
6 地表加载
如果使用了光照贴图,对于动态生成的物件代码里需要指定光照索引和UV。
7 动态批处理
如果地块分割尺寸特别大,那么地块区域内的地表元素会非常多,动批时很可能会造成严重的卡顿,而且我们场景里的部分树和石头是可以采集的。