随着游戏的开发,项目的配置表数据越来越多,占用的内存越来越;配置表占用太大就会影响游戏加载速度,游戏流畅度的每一毫秒都是我们的必争之路。
[1] = {DungeonID=10000, Dungeon= "王进打高俅", NextDungeonID=10100, BattleID= {10001, }, BattleTime=0, Quality=0, BackMusic= "BGM_Fight", },[2] = {DungeonID=10100, Dungeon= "鲁提辖,拳打镇关西", NextDungeonID=10200, BattleID= {10101, 10102, }, BattleTime=0, Quality=0, BackMusic= "BGM_Fight", },[3] = {DungeonID=10200, Dungeon= "五台山,僧与俗的较量", NextDungeonID=10300, BattleID= {10201, 10202, 10203, 10204, 10205, 10206, 10207, 10208, }, BattleTime=0, Quality=0, BackMusic= "BGM_Fight", },
我们项目采用的配置表存储方式是Lua表格,策划配表用excel配置,然后使用网上的开源工具excel2lua导出lua表格,业务逻辑使用的时候直接import表就好了。在观察了导出的lua表格后,我们整理出一堆待优化的问题:
1. 没有意义的空值(比如0,[]等)
2. 重复数据
3. 默认值
4. 字段名优化
5. 客户端、服务端表格分离
搞清楚了数据冗余的原因,我们就可以制定优化方案:
没有意义的空值(比如0,[]等)
空的table:我们建了一张全局表GlobelEmptyTable = {},然后把这些空table都指向这个GlobelEmptyTable
重复数据
对于重复数据,我们在lua表新建一张duplication表,用来存放重复数据,然后把重复的数据,都指向这张表里面相应的重复的数据。
默认值
通过观察可以发现其中有部分字段很容易重复,如:BattleTime、Quality等, 这些字段通常为枚举或者有固定的分类,只有几个不同的值,然而配置表中每个item
都需要为这些内容创建一个字段。
我们的优化方案是,利用lua的特性--原表(metatable),建一张defaultValues表,在导出的时候,选取出现次数最多的值作为每个字段的原表,存到defaultValues,然后剔除每行中与默认值相同的字段,从而节省内存。
local defaultValues = {Dungeon = "",Describe = "",PlayerLevel = 0,Name = "",NeedStar = 0,BackMusic = "BGM_Fight",PrizeInfo = 0,Crime = "",Num = 1,Place = "",BattleID = gConstEmptyTable,BackGround = "",NextDungeonID = 0,DungeonID = 0,ID = 0,
}dolocal base = {__index = defaultValues, --基类,默认值存取__newindex = function()--禁止写入新的键值error("Attempt to modify read-only table")end}for k, v in pairs(DUNGEON_LIST) dosetmetatable(v, base)endbase.__metatable = false --不让外面获取到元表,防止被无意修改
end
字段名优化
热心网友给我提出这种优化,但是这种类似CSV存储格式,可想而知,内存肯定可以降低很多,我简单实现了一下,比对了一下内存,差别还是很大的!!!但是这种存储格式和默认值方案冲突,只能取舍,现在项目已经做完了,下个项目可以试一下这种方案。
local KeyMap = {costRes = 1,costTime = 2,troopsCount = 3,power = 4,model = 5,
}local BUILD101 = {[1] = {{}, 0, 2, 69, "castle1", },[2] = {{ 1001, 1782, 1002, 2430, 1003, 2430, 1004, 1458, }, 295, 2, 166, "castle1", },[3] = {{ 1001, 2673, 1002, 3645, 1003, 3645, 1004, 2187, }, 1080, 2, 302, "castle1", },
}dolocal base = {__index = function(table,key)local keyIndex = KeyMap[key]if not keyIndex thenprint("key not found: ",key)return nilendreturn table[keyIndex]end, --基类,默认值存取__newindex = function()--禁止写入新的键值error("Attempt to modify read-only table")end}for k, v in pairs(BUILD101) dosetmetatable(v, base)endbase.__metatable = false --不让外面获取到元表,防止被无意修改
end
客户端、服务端表格分离
服务器对于这么点内存,根本不会在意,但是客户端大不一样,是个精打细算的好媳妇,每一KB都要计较的,所以,我们设计一个参数来控制配置表导出对象,C:客户端、S:服务端,在和策划设计表的时候,告知哪些是客户端需要的参数,导出的时候,按C、S导出2张表。
本文中使用的配置表优化工具源码已经放在github,需要的朋友可以自取:)https://github.com/Aver58/Tools
使用元表优化 Lua 配置文件www.orztu.comLua配置表存储优化方案 - UWA Blogblog.uwa4d.com