下载 App

存档设计经验总结

精华03/18457 浏览开发交流
适用于 UrhoX + serverCloud 的联网游戏项目。
---

一、核心思路:三层分离

存档系统最重要的设计决策是把"运行时状态"、"序列化格式"和"持久化通道"拆成三层,彼此独立演进。
运行时状态(GameState)是一个内存中的全局单例,所有游戏系统只读写它,不直接接触存档。好处是游戏逻辑完全不关心"数据怎么存、存在哪",降低了耦合度。
序列化模块负责在 GameState 和紧凑格式之间做翻译。每个业务领域一个模块(工会、成员、探索、日志……),各自维护字段映射,互不干扰。
持久化通道(ServerSave / ServerSaveLoad)负责跟云端通信。防抖、合并、重试、容错都封在这一层里。
```
游戏系统 ──→ GameState(内存单例) ←──→ 序列化模块 ←──→ ServerSave(防抖) ←──→ serverCloud
```
这样做的实际收益:中间换过一次云端存储方案,GameState 和所有游戏系统一行没改,只动了 ServerSave 里的几个调用。
---

二、分槽存储

不要把所有数据塞进一个大 JSON。按业务领域切成独立的"存档槽",每个槽有自己的 key、序列化函数和反序列化函数。
为什么分槽:
1.改了成员数据只重写成员槽,工会配置纹丝不动,减少写入量
2.每个槽体积可控,不容易撞上云端单条 ~13KB 的限制
3.某个槽损坏时不会连带其他数据一起挂
槽的注册方式: 在一个统一的注册表(SLOT_DEFS)里声明每个槽的 key、序列化函数、反序列化函数。新增槽位只需要往注册表加一行,加载和保存逻辑自动覆盖,不用到处改代码。
---

三、大集合分片

成员列表这类"会随游戏进程增长"的数据必须分片。本项目 30 人上限,按每 15 人一个槽切成 members_1 和 members_2。
分片粒度取决于单条配额。先算单个成员序列化后的平均体积,反推每个分片能放多少条,再留 20%~30% 余量应对装备等可选字段膨胀。
日志这类无限增长的数据除了分片还要加 FIFO 上限(本项目 50 条),老条目自动丢弃。
---

四、短键名 + 默认值兜底

序列化用短键名:运行时 `guildName` 存档时写 `gn`,`guildLevel` 写 `gl`。30 个成员的存档光键名就能省 30%~40% 体积,在 13KB 限制下很关键。
**反序列化必须给默认值:** 每个字段都写成 `GameState.guildName = data.gn or "无名工会"` 的形式,没有例外。这样老存档在新版本上加载时,缺失的新字段自动用默认值填充,天然具备向前兼容能力,绝大多数版本迭代不需要写迁移脚本。
只有在数据结构发生破坏性变更时(字段类型变了、嵌套层级改了),才需要引入版本号做显式迁移。项目中成员数据的 `v < 2` 迁移就是这种情况——早期没有 status 字段,升级时自动补 `st = "idle"`。
---

五、防抖写入

每次数据变更不立即写入云端,而是标记对应的槽为"脏"。定时器每 5 秒触发一次,把所有脏槽合并成一次 BatchSet 请求。
```
玩家 5 秒内点了 3 次升级 → guild_core 标脏 3 次(实际只标 1 次)
                         → 5 秒后合并成 1 次网络请求写出
```
**inflight + pending 双缓冲:** 如果上一次 BatchSet 还没返回,新的脏标记存到 pending 队列。inflight 完成后再把 pending 发出去。任意时刻最多两次网络调用在路上,既不丢数据,也不乱序。
**generation 计数器:** 每次 flush 递增 generation,旧的 inflight 回调发现 generation 不匹配时自动失效,防止过期回调干扰新状态。
---

六、断线快照

防抖有一个盲区:玩家在定时器触发之前断线,脏数据就丢了。
检测到断线或关闭时立即执行一次 flush——先拍当前状态的快照(序列化),再以最高优先级排队写入。快照用的是断线那一刻的状态,不等 inflight 回来,确保数据是最新的。
---

七、容错加载

加载时每个槽的反序列化都包在 pcall 里。某个槽解析失败就打日志、用默认值填充、继续加载其他槽。日志槽坏了不影响角色数据,不会让整个游戏无法启动。
加载顺序有依赖关系的要先加载被依赖方。所有槽加载完成后统一执行"加载后逻辑"(跨日检测、过期清理等),不在单个槽的反序列化里各自处理。
---

八、货币和配额走专用通道

金币(Money)和门票(Quota)不走 Score 槽位,走云端提供的专用原子操作接口。
原因是这类数值型资源需要原子性的加减操作(防止并发导致余额错乱),云端的 Money:Add / Money:Cost 和 Quota:Add 自带原子保证和负数校验,比自己在 JSON 里存一个数字再手动加减安全得多。
操作时注意:修改金币后不需要标脏(因为不走 Score 槽),而是直接调用 Money/Quota 的云端接口。但 GameState 里的缓存值要同步更新,保持运行时状态的一致性。
---

九、新增字段的标准流程

给现有槽加字段只需要 4 步,不需要写迁移逻辑:
1. GameState 加字段和默认值
2. resetAll() 加重置
3. 对应模块的 serialize() 加序列化(用短键名)
4. 对应模块的 deserialize() 加反序列化(带 `or 默认值`)
新增一个全新槽位需要多改几处:创建序列化模块、注册到 SLOT_DEFS、在 Shared 里加 key 常量、在 ServerSaveLoad 的 BatchGet 里加一行、GameState 里加字段。但整体流程是机械的,不容易出错。
---

十、端到端验证

存档 bug 往往滞后暴露。写一组自动化测试覆盖完整的往返流程:
1. 填充已知数据到 GameState
2. 序列化 → 写入云端
3. 清空 GameState
4. 从云端读取 → 反序列化
5. 逐字段 deepEqual 比对
准备多组测试数据:新手空档、中期半满、满编极端、故意缺字段的旧版模拟。每次改动序列化逻辑后跑一遍,防止回归。
---
  • ## 设计检查清单
  • - 运行时状态和持久化是否分层(GameState vs ServerSave)
  • - 是否按业务领域分槽,单槽体积是否在配额内
  • - 大集合是否分片,是否有增长上限
  • - 序列化是否用短键名,反序列化是否每个字段都有默认值
  • - 写入是否防抖合并,是否有 inflight/pending 双缓冲
  • - 断线时是否有快照 flush
  • - 加载是否 pcall 容错,单槽失败不影响全局
  • - 货币/配额是否走专用原子接口
  • - 是否有端到端往返测试
猜你想搜
taptap 制造存档设计经验
别再烧积分了!从每次 2000 到每次 50 的血泪经验截图
别再烧积分了!从每次 2000 到每次 50 的血泪经验
适用场景:所有在用 TapTap Code 开发游戏的小白 难度:★☆☆☆☆ 背景最近群里总有人"炫耀"一次操作花了几千积分,说实话这不是值得高兴的事——这是在告诉所有人你的开发方式有根本性问题。我也走过这条弯路,所以来说说怎么改。 积分消耗的本质是什么积分 = AI 处理的 token 数量 = 你发给 AI 的内容 + AI 回给你的内容所以烧积分的本质只有两种: 你让 AI 做了大量无效/重
精华
82 赞
23 回复
如何提升你游戏中的UI美术水平截图
如何提升你游戏中的UI美术水平
一、请为你的游戏挑选一款合适的字体 很多开发者没有注意到其实UI界面中最重要的元素是字体,一款合适的字体能给整个游戏的界面感官带来蜕变。 请看案例 那么如何挑选适合自己的字体呢? 我总结出了一些小经验可供参考: 黑体:通用 宋体:古风、武侠、修仙 楷体:古风、武侠、修仙 圆体:卡通、动漫、Q版 科技:科幻、未来、电子 顺手分享一个免费可商用字体网站: 当然 如果你不知道自己的游戏适合什么风格
精华
126 赞
44 回复
永恒虚空持续开发日记1——关于游戏中的新名词:场频截图
永恒虚空持续开发日记1——关于游戏中的新名词:场频
写在前边:首先感谢TapTap制造版主大大@汪崽 对于作品潜力的肯定,给与了我积分计划二的权限[表情_不好意思]。这边也在加紧开发改进各种功能中,期望尽快给大家带来成熟的版本。[表情_猫咪举手] 大家好,我是永恒虚空的制作人黑猫不详,大家叫我黑猫就好。从今天开始我将以后置开发日记的形式给大家分享我在TapTap制造中制作的游戏永恒虚空的开发过程,新人希望大家多多关照! 今天先给大家介绍我作品中最重
投票
3 赞
【UI教程】如何将已有的效果图应用为实际的UI界面截图
【UI教程】如何将已有的效果图应用为实际的UI界面
在经过了一些折腾和比较折磨的尝试后,我总算是摸清楚了嗒啦啦怎么把UI效果图转换为实际游戏中的UI组件,今天就给大家带来这部分的经验分享。 tips:1.本篇教程需要各位掌握最基本的ps使用,具体的操作部分我会大致讲解,但仍需各位自行学习ps的基本操作,部分可以由ai代劳的环节我会注明。 2.本篇教程需要在以我前两篇教程作为前置环节,请在阅读这两篇前置教程后再进行本篇教程内容的学习 在按照前
12 赞
5 回复
本地部署 AI 对接 TapMaker 指南 —— 以 CodeBuddy 为例V1.1截图
本地部署 AI 对接 TapMaker 指南 —— 以 CodeBuddy 为例V1.1
写在前面 大家好,我是橘猫,和你一样也是TapMaker的萌新玩家。在"全能神"天哥的悉心指导下,我顺利完成了本地开发环境的部署。经过这段时间的实战测试,已经成功打通了「本地开发 → 同步至TapMaker」的完整流程。 以下内容全部来自我的个人实操经验,旨在为同样在探索本地部署的朋友提供一个参考。每个人的电脑环境、网络情况、AI工具版本都不尽相同,文中的步骤仅供交流学习。如果你照着操作后遇到问题
37 赞
21 回复
浅记《阿方的旅程》开发历程截图
浅记《阿方的旅程》开发历程
预计阅读时长10分钟,欢迎您先品鉴游戏,再回来看这篇“流水账” 这是我第一次实际接触“用自然语言制作游戏”,也是我第一次接触游戏开发工作,所以一切都是从零开始,跌跌撞撞,懵懵懂懂。[表情_豹哭] 我是通过获得的本次开发资格,6月22日晚,在微信公众号收到了测试资格的消息,最开始公布主题“跳跃”的时候,脑子里最先想到的就是几款非常经典的游戏「马里奥」「Flappy Bird」「Doodle Jump
10 赞
1 回复
01:29
官方阅,申请积分计划2,希望官方继续支持我完成这款游戏,截图
官方阅,申请积分计划2,希望官方继续支持我完成这款游戏,
视频内容只是一部分, 本游戏耗时3个月,目前完成进度百分之80, 是生存游戏,进入修仙界,走剧情找到宗门加入, 这时游戏才是真正开始, 提升实力境界后就可以变强,获取功法法术法宝, @视频内是游戏里挑战妖族入侵一种主流玩法,游戏就是围绕着这个来进行, 还有很多地方可以战斗,获得资源修炼变强,比如去藏书阁学习功法, 去法宝楼抽法宝,每一个宗门数十个法宝抽取 去修仙界探索,获得各自的资源,可能遇见妖兽
1 赞
3 回复
关于制作出质量很高的横版战斗角色的方法截图
关于制作出质量很高的横版战斗角色的方法
其实全篇就一句话,角色为啥做起来这么好看,因为我一帧一帧K的。 在做角色之前,我们需要一个角色的设计稿,这个东西很简单,你把人设写好剩下的交给AI就行了,所有图片,序列帧都可以让AI绘制和处理,学会绘图是你要制作高质量游戏的第一课。 这里拿我在做的角色举例,他的参考图是这样: 当你拥有了一个角色以后,就要想办法让她动起来了。 那么如何让她动起来,答案是序列帧。 在此之前你需要知道,最容易出现一个误
42 赞
12 回复
开发日志(day2)坚持去做就是好的开始截图
开发日志(day2)坚持去做就是好的开始
今天主要是修复了一下昨天遇到的很多问题,闪帧;装备的等级没有随怪物等级参考;再次进入地下城,怪物状态竟然显示(已倒下);不会自动更换目标,导致会反复鞭尸;等很多的问题,不过通过昨天的经验,有效的向ai提出问题并且发送截图发给ai调试,也是把这些问题成功排除,甚至还有多余的free额度来生成新的内容。 新增的内容有返回城镇;返回主界面;中途退出地下城保留进入前的状态;完成地下城的面板结算;当然最有感
1 赞
1 回复
2D 等轴测视角:完整理论截图
2D 等轴测视角:完整理论
2D 等轴测视角:完整理论 一、视角的本质 什么是等轴测 人站在高处斜着往下看地面,地面上的方格子不再是正方形,而变成了菱形。这就是等轴测的视觉本质。 俯视(正上方看下去): 等轴测(斜上方看下去): ┌──┬──┬──┐ ◇ ├──┼──┼──┤ ◇ ◇ ├──┼──┼──┤ ◇ ◇ ◇ └──┴──┴──┘ ◇ ◇ ◇ 正方形网格经过旋转 + 压缩,变成了菱形网格。 为什么是 2:1
6 赞