下载 App

游戏存档压缩的常用手段

07/02100 浏览开发交流
游戏存档通常会随着玩家进度、背包、装备、任务、活动和日志数据增长而变大。存档过大会带来云同步慢、保存耗时长、网络失败率上升、加载卡顿和设备存储占用增加等问题。
下面整理一套通用的存档压缩思路,适用于本地存档、云存档、JSON 存档、二进制存档等场景。
1.只保存必要状态 最重要的原则是:能通过配置、公式或运行时重建的数据,不要保存。
常见可省略字段:
道具名称、描述、图标路径
品质名称、颜色、排序权重
技能文本、词条显示文本
默认值字段,例如 level = 1、locked = false、star = 0 空数组、空表、空字符串
可由 ID 查配置表恢复的静态字段
示例:
不推荐 { "id": "sword_001", "name": "铁剑", "icon": "sword.png", "quality": "common", "level": 1, "locked": false }
推荐 { "id": "sword_001" } 读取存档后,再通过配置表恢复显示信息。
2.使用短字段名
JSON 存档中字段名会重复出现。背包、装备、符文、宠物等大量列表数据里,长字段名会显著增加体积。
可以在保存层做字段映射:
运行时结构 { "itemId": 123, "qualityId": "red", "level": 50, "experience": 12000 }
存档结构 { "i": 123, "q": "red", "l": 50, "e": 12000 } 注意:
运行时代码不一定要使用短字段名。
推荐只在序列化/反序列化层转换,避免降低业务代码可读性。 需要保留版本兼容,旧字段和新字段都能读取。
3. 省略默认值
如果某个字段等于默认值,保存时可以直接省略。
常见默认值:
false 0 1 空字符串 空数组 空表 初始容量 初始等级 示例:
不推荐 { "level": 1, "star": 0, "locked": false, "equipped": false }
推荐 {} 反序列化时统一补默认值:
level = saved.level or 1 star = saved.star or 0 locked = saved.locked == true
4. 列表用数组代替对象
如果字段顺序固定,可以用数组压缩对象。
对象形式 { "id": "atk_pct", "value": 0.08, "locked": true }
数组形式 ["atk_pct", 0.08, 1] 优点:体积更小。 缺点:可读性差,字段变更时更容易出错。
建议:
数据规模很大时再使用数组形式。 保留清晰的编码/解码函数。 在代码中集中定义字段顺序。
5. 拆分存档分组
不要把所有数据都放进一个巨大的存档对象。可以按变更频率和功能拆分。
常见分组:
核心进度:等级、关卡、解锁状态
货币资源:金币、钻石、材料
装备背包:装备、符文、道具
活动数据:限时活动、签到、任务
设置数据:音量、画质、偏好 好处:
只上传变化的分组。 降低单次保存体积。 某个分组损坏时不一定影响全部数据。 高频变化数据可以单独节流保存。
6. 脏标记与延迟保存
不是每次数据变化都立刻完整保存。
推荐做法:
数据变化时只标记 dirty。
定时合并保存,例如每 10~30 秒保存一次。
关键操作立即保存,例如付费购买、抽卡、消耗稀有资源。
普通操作延迟保存,例如 UI 排序、临时选择、普通战斗进度。 这样可以减少云存档请求次数和重复写入。
7.避免保存临时运行时状态
很多状态只在当前会话有意义,不应该进入长期存档。
常见不应保存的字段:
UI 当前选中项
滚动条位置
动画计时器
战斗中的临时
buff 计时 粒子、飘字、特效状态
缓存字段
已格式化文本
临时排序结果
调试信息
如果必须保存中途战斗进度,也应单独设计一个轻量的战斗快照,而不是把完整运行时对象直接落盘。
8.对重复结构做模板化
大量对象如果结构相似,可以保存模板 ID + 差异。
示例:
不推荐:每个怪物保存完整属性 { "id": "goblin", "hp": 100, "atk": 20, "speed": 1.2, "drop": "coin" }
推荐:保存模板 ID 和必要差异 { "id": "goblin", "lv": 12, "hpRate": 0.7 } 配置表负责提供基础属性,存档只保存玩家造成的差异状态。
9.数值量化与精度控制
很多小数没有必要保存完整精度。
例如:
百分比保留 4 位小数
坐标保留 2 位小数
时间戳用整数秒,不用毫秒
战斗统计只保存整数 json
不推荐 { "critRate": 0.123456789 }
推荐 { "critRate": 0.1235 } 注意不要压缩会影响公平性的核心数值,尤其是竞技、排行榜、付费相关数据。
10.使用位集或数字编码布尔状态
大量布尔值可以用 bitset 压缩。
适用场景:
成就是否领取
关卡是否通关
图鉴是否解锁
每日奖励是否领取 json
不推荐 { "claimed1": true, "claimed2": false, "claimed3": true }
可选 { "claimedBits": 5 } 5 的二进制是 101,表示第 1 和第 3 项已领取。
缺点是可读性下降,建议只用于数量较大的布尔集合。
11.使用增量记录替代完整快照
某些系统可以只保存变更记录,而不是保存完整状态。
例如:
已领取奖励 ID 列表
已购买商品 ID 和次数
已解锁图鉴 ID
已完成任务 ID
如果完整状态能从配置表 + 变更记录推导出来,就不需要保存完整状态。
12.定期清理过期数据
活动、邮件、临时兑换、历史战报等数据容易长期残留。
建议:
活动结束后清理活动临时货币和进度。
过期邮件只保留摘要或直接删除。
战报只保留最近 N 条。
日志不进入玩家存档。
临时补偿标记在确认无用后迁移清理。
13. 使用压缩算法
如果存档后端允许,可以对 JSON 做压缩,例如:
gzip zlib lz4 zstd
优点:
对重复字段名和大量 JSON 文本非常有效。
缺点:
增加 CPU 开销。
调试不方便。
需要后端和客户端都支持。
小存档压缩收益有限。
通常建议先做结构压缩,再考虑通用压缩算法。
14.二进制存档
二进制格式比 JSON 更紧凑,例如:
protobuf flatbuffers msgpack
自定义二进制格式
优点:体积小,解析快。
缺点:开发和维护成本更高,排查线上问题不如 JSON 方便。
适合数据量大、结构稳定、对性能要求高的项目。
15.版本迁移机制
所有压缩都必须配合版本迁移。
建议存档包含:
{ "saveVersion": 3 }
读取时:
判断版本。
旧格式转新格式。
补默认字段。
修复非法值。
再交给业务逻辑使用。
兼容策略:
新读取器尽量同时支持旧字段和新字段。
不要一次性删除旧格式支持。
高风险迁移前保留备份或灰度。
16. 保存前校验和裁剪
保存前可以做一次 sanitize:
删除 nil、非法类型、函数、userdata。
限制数组最大长度。
限制字符串最大长度。
修正 NaN、Infinity。
裁剪超过上限的缓存数据。
这可以避免异常数据把云存档撑爆或导致 JSON 编码失败。
17.常见优先级建议 如果要快速降低存档体积,建议按以下顺序做:
删除不该保存的运行时状态。
省略默认值和空字段。
删除可由配置恢复的静态字段。
大列表字段名缩短。
拆分存档分组,只保存 dirty 分组。
清理过期活动和历史记录。
对超大列表使用数组编码或 bitset。
最后再考虑 gzip/protobuf 等底层格式。
18. 风险控制清单 上线存档压缩前,应检查:
新存档能否正常读写。
旧存档能否正常迁移。
断网、保存失败、云端返回空表时是否保护本地数据。
压缩后关键字段是否丢失。
付费、抽卡、排行榜相关数据是否保持准确。
是否有回滚方案。 是否有日志记录迁移异常。
总结
存档压缩的核心不是简单地把文件 gzip,而是区分“必须保存的玩家状态”和“可以从配置或运行时恢复的数据”。
优先做结构级优化:
少存字段
短字段名
省略默认值
拆分分组
清理过期数据
延迟保存
这些方式通常风险低、收益稳定,也更容易调试和维护。
猜你想搜
taptap 制造存档压缩
03:06
为了不被斩杀,我只能做到这些了截图
为了不被斩杀,我只能做到这些了
之前一直申请不到计划3,之前说太花哨,后面说体量完成度不足,在我一番小作文下,编辑终于给了我解答,什么原生质感,玩家开局体验啥的。 本来计划2也够用,准备以后再优化了,结果计划2赠送的积分要砍半了,学生党实在消费不起,于是只能再冲一波计划3了 从周六中午到现在一天半时间,优化了一遍角色卡,战斗卡,还有抽卡界面,优化了新手教程,该说不说确实比之前要舒服些。 前半部分为新版,后半部分为旧版。 明天再次
40 赞
6 回复
如何提升你游戏中的UI美术水平截图
如何提升你游戏中的UI美术水平
一、请为你的游戏挑选一款合适的字体 很多开发者没有注意到其实UI界面中最重要的元素是字体,一款合适的字体能给整个游戏的界面感官带来蜕变。 请看案例 那么如何挑选适合自己的字体呢? 我总结出了一些小经验可供参考: 黑体:通用 宋体:古风、武侠、修仙 楷体:古风、武侠、修仙 圆体:卡通、动漫、Q版 科技:科幻、未来、电子 顺手分享一个免费可商用字体网站: 当然 如果你不知道自己的游戏适合什么风格
精华
123 赞
44 回复
【新游上线】末日100天截图
【新游上线】末日100天
大家好,我们是《末日100天》的开发者Paul~ 这是一款围绕「生存-经营-轮回」展开的废土策略小游戏:白天分配 3 点行动力经营据点,夜里迎接十天一循环的尸潮,每张地图第 100 天还有一场首领战等着你。五张地图、五大区域机制、可继承的轮回遗产,以及钻石商城里的抽奖机——我们希望每次重开都有一点点新意。 以下是游戏简单介绍: 1.游戏背景 废土历元年,未知病毒席卷全球,城市化为死地。幸存者们退守
9 赞
6 回复
别再烧积分了!从每次 2000 到每次 50 的血泪经验截图
别再烧积分了!从每次 2000 到每次 50 的血泪经验
适用场景:所有在用 TapTap Code 开发游戏的小白 难度:★☆☆☆☆ 背景最近群里总有人"炫耀"一次操作花了几千积分,说实话这不是值得高兴的事——这是在告诉所有人你的开发方式有根本性问题。我也走过这条弯路,所以来说说怎么改。 积分消耗的本质是什么积分 = AI 处理的 token 数量 = 你发给 AI 的内容 + AI 回给你的内容所以烧积分的本质只有两种: 你让 AI 做了大量无效/重
精华
68 赞
21 回复
本地部署 AI 对接 TapMaker 指南 —— 以 CodeBuddy 为例V1.1截图
本地部署 AI 对接 TapMaker 指南 —— 以 CodeBuddy 为例V1.1
写在前面 大家好,我是橘猫,和你一样也是TapMaker的萌新玩家。在"全能神"天哥的悉心指导下,我顺利完成了本地开发环境的部署。经过这段时间的实战测试,已经成功打通了「本地开发 → 同步至TapMaker」的完整流程。 以下内容全部来自我的个人实操经验,旨在为同样在探索本地部署的朋友提供一个参考。每个人的电脑环境、网络情况、AI工具版本都不尽相同,文中的步骤仅供交流学习。如果你照着操作后遇到问题
36 赞
16 回复
开发心得-界面布局心得截图
开发心得-界面布局心得
大家好,我正在用 TapTap 制造制作一款2D 治愈林间徒步旅行游戏《徒步荒野》。 我分享一下我的开发心得,希望能有用,下面是一些界面布局的心得。 第一步:定版式、操作 先确定游戏是横版还是竖版、需要哪些操作按钮,敲定整体玩法思路。 我的玩法灵感参考《边境之旅》,主打散步看风景、沿途触发随机事件。 原版是 3D,考虑到自己是新手,选择2D 横版街机式来做,制作更简单、好上手。 第二步:敲定全局美
6 赞
3 回复
【游戏上新】商业帝国大亨截图
【游戏上新】商业帝国大亨
无名小卒还是名扬天下。 从临时工到称霸宇宙。 只需点击屏幕,就能获得财富,利用财富购置产业,获取更多财富。
6 赞
4 回复
【UI教程】如何将已有的效果图应用为实际的UI界面截图
【UI教程】如何将已有的效果图应用为实际的UI界面
在经过了一些折腾和比较折磨的尝试后,我总算是摸清楚了嗒啦啦怎么把UI效果图转换为实际游戏中的UI组件,今天就给大家带来这部分的经验分享。 tips:1.本篇教程需要各位掌握最基本的ps使用,具体的操作部分我会大致讲解,但仍需各位自行学习ps的基本操作,部分可以由ai代劳的环节我会注明。 2.本篇教程需要在以我前两篇教程作为前置环节,请在阅读这两篇前置教程后再进行本篇教程内容的学习 在按照前
10 赞
4 回复
2D 等轴测视角:完整理论截图
2D 等轴测视角:完整理论
2D 等轴测视角:完整理论 一、视角的本质 什么是等轴测 人站在高处斜着往下看地面,地面上的方格子不再是正方形,而变成了菱形。这就是等轴测的视觉本质。 俯视(正上方看下去): 等轴测(斜上方看下去): ┌──┬──┬──┐ ◇ ├──┼──┼──┤ ◇ ◇ ├──┼──┼──┤ ◇ ◇ ◇ └──┴──┴──┘ ◇ ◇ ◇ 正方形网格经过旋转 + 压缩,变成了菱形网格。 为什么是 2:1
6 赞
01:12
《翡翠矿场》游戏上新截图
《翡翠矿场》游戏上新
《翡翠矿场》全新版本正式上线!从一座小小矿洞开始,招募矿工、开采原石,亲手鉴定每一块石头的价值。是普通砂石,还是难得一见的极品翡翠?升级矿洞、培养工人、加工饰品、经营店铺,在一次次判断与经营中积累财富,打造属于你的翡翠帝国。现在进入游戏,开启寻宝之旅!
4 回复