Lua开发手记(一)

引言:2015年11月从上上家公司离职后,开始了独立开发的历程。引擎改用了流行的unity,但是语言还是选择了最喜欢的lua,使用的Slua,没有使用luajit,而是选择了原生Lua(5.3.4),中途历经各种坎坷,17年还中断了一年,现在游戏终于是快要上线了,打算写一些开发手记,记录下这段时间对Lua使用的一些提升。

数据持久化

游戏是款单机游戏,当玩家选择存档或者游戏自动存盘时,需要将整个游戏的进程信息全部保存下来,如果每一个模块都要全部手写一遍代码就会让整个过程变得很繁琐。为了简单的搞定这个功能,于是想到了通过将数据与操作严格的进行分离,然后将存储功能简单的变为将存储数据的表做一个持久化,而读取功能就变成了,将存储的的数据表读出来直接覆盖掉当前的数据表即可。

简单画个图表示:

通过机制保证数据的分离

lua本身是脚本语言,是弱类型的,没有办法保证这点,所以需要建立一套机制来保证这点(以下API的名字都是自定义的,全凭个人喜好)。

控制操作API。所有需要持久化的模块必须从一个基础模块继承(

简单使用Lua实现类的继承

)而来,基础模块里实现了Get(key)和Set(key, value)这两个接口, 所有需要持久化的数据必须使用这2个接口来进行操作(否则会直接写入表本身,无法被持久化),并可以考虑在Set接口里做显性类型检查(避免写入userdata,function等无法持久化类型的变量)。

基础模块部分使用一个表来存储所有数据,这样存储的时候仅需要将这个表做持久化就OK了,并将这个表进行隐藏(Lua实现简单封装),避免平常操作时误修改数据区域数据。(使用GetData() 和 SeData(data)这两个接口来获取完整的数据区域的数据和实现数据覆盖)。

最后为了能尽量方便使用,可以通过设置metatable的__index,在用户试图使用XX.XX的方式访问数据且找不到同名变量时,调用Get函数,使访问数据使用起来与原生数据一致。

用个简单的图来表示下:

表格序列化

最后这个就简单了,用pairs遍历表格,然后根据类型将其以字符串形式格式化输出并保存即可。

PS:注意针对string类型的变量,使用string.format的话,要用%q。

完成上述功能后,一个典型的Save/Load功能就变成了以下样式:

Save:

通过GetData获取存盘数据。

将获取到的table序列化获得生成字符串。

将字符串保存。

Load:

读取保存的字符串

将字符串反序列化(使用lua的load系列函数)获得一个table

通过SetData将这个table设置覆盖。

最后的最后,采用这个方法,在模块的开发代码里,需要持久化的代码一定要通过指定接口来设置,否则就会出现部分数据丢失了= =

下一篇:Lua热更新(应部分朋友要求)

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180619G06ADO00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券