Files
dc-docs/output/feishu-docs/L6K3wxI54iLqBEkyD5zcWNxFn1g.md
T
2026-06-23 14:43:31 +08:00

12 KiB
Raw Blame History

L6K3wxI54iLqBEkyD5zcWNxFn1g

Source: https://dianchukeji.feishu.cn/wiki/L6K3wxI54iLqBEkyD5zcWNxFn1g

一.工作内容概述

  • 接入腾讯云 CloudBase,作为当前阶段的云存储方案,用于推进账号存档、资源同步和真机联调。
  • 对 save service 进行了重构,支持 memory / douyin / cloudbase 多种存储后端切换,并补充 CloudBase 字段映射、环境配置、接口校验和 session TTL 清理等能力。
  • 对关卡 Session 机制进行了异步化调整,将普通关、每日挑战、生存模式改为先展示棋盘、后台启动 session,减少网络请求对进入关卡体验的影响。
  • 对体力、金币、广告奖励、生存模式结算等资源变动路径进行了审查和修复,尽量让云端模式下的关键资源变化统一走服务端处理,减少客户端直接修改资源带来的风险。

二.云存档服务重构与 CloudBase 接入

由于抖音云存储仍处于审核阶段,当前项目暂时无法直接使用抖音官方云存储能力。为了不影响后续云端存档、账号资源同步和真机联调,本次先接入腾讯云 CloudBase,作为当前阶段可用的云存储方案。 本次接入不只是替换一个存储接口,还整理了存储后端结构,包括账号存档读写、字段映射统一、环境配置、存储后端切换,以及 session 过期清理能力。

存储后端改为可插拔结构

本次重构新增了 cloudbaseStore.js,并将存储层整理为多后端结构。目前支持三种存储方式:

  • memory:用于本地开发调试,服务重启后数据会丢失;
  • douyin:预留给抖音官方云存储能力;
  • cloudbase:当前阶段实际使用的云存储方案。 后端通过 STORAGE_BACKEND 环境变量选择实际使用哪一种存储实现。这样业务逻辑不需要关心底层具体使用哪个存储平台,只需要通过统一的 store 接口读写存档。 这种结构的好处是比较明显的。当前阶段可以先使用 CloudBase 推进开发和验证;后续如果抖音云存储审核通过,可以再接入 douyin 存储;如果 CloudBase 使用稳定,也可以继续作为正式存储方案保留。整体上不会把项目存档逻辑强绑定到某一个平台。

CloudBase 配置与字段映射修复

为了让 CloudBase 能够在生产环境中使用,本次在 config.js 中补充了 CloudBase 相关环境变量配置,并在 store/index.js 中按环境动态选择存储后端。 同时修复了 CloudBase 存档读取时的字段映射问题。之前存在字段名不一致的情况,可能导致“写入成功,但读取时取不到正确数据”。例如同一类字段在不同存储后端中命名不统一,就会让读取逻辑需要额外做转换,后续也更容易出错。 本次将 CloudBase 存储字段统一为 openId、saveKey、revision 等格式,尽量与原有 douyin 存储保持一致。这样后续维护时,不需要在不同存储后端之间写大量额外适配逻辑,也能降低读取、回写、同步时出现字段不一致问题的概率。

存档接口加固

除了接入 CloudBase,本次也对 save service 的接口做了一些加固处理,包括统一错误处理、参数校验等。 云端存档一旦接入正式流程,就不只是简单的数据读写,还会影响体力、金币、道具、皮肤等账号资源。因此接口层需要尽量避免参数缺失、异常未捕获、字段不统一等问题。 同时,原先部分逻辑拆得比较散,本次也对相关结构做了整理,让存档服务的入口、配置和实际存储实现之间的关系更清晰。

Session 过期清理接入 CloudBase TTL

除了账号存档外,本次也将 session 过期清理放到 CloudBase 接入方案中一并处理。 当前 session 机制用于记录玩家每一局游戏的开始状态和结算凭证。普通关、双鸡、每日挑战、生存模式都会创建对应 session。由于这些 session 只在短时间内有效,如果长期保留在数据库中,会造成无意义的数据堆积,也会增加后续排查和维护成本。 本次方案使用 CloudBase 的 TTL 能力来清理过期 session。服务端创建 session 时会写入 deleteAt 字段,CloudBase 控制台中已经确认 level-session 集合存在对应的 deleteAt_ttl 索引。后续每个 session 都会根据自身的过期时间,由 CloudBase 自动清理。 不过,TTL 删除通常不是实时执行的,因此服务端仍然保留业务层面的过期判断。即使某条过期 session 还没有被数据库自动删除,只要它已经超过业务允许时间,服务端也不会继续认为它有效。 这样处理的好处是:

  • 不需要额外写定时清理任务;
  • 数据库层面可以自动清理旧 session;
  • 服务端业务层仍然保留安全兜底;
  • session 表不会因为长期运行而持续堆积无效数据。 当前每个 session 暂定保留半小时,后续可以根据实际玩法时长、网络重试策略和反作弊需求再调整。

三.关卡 Session 机制重构与异步化

Session 的作用主要是保留服务端反作弊和结算凭证。也就是说,玩家开始一局游戏时,服务端会创建一个 session;玩家结算时,再通过这个 session 判断本局游戏是否合法、是否应该发放奖励或更新进度。 但之前的流程有一个明显问题:进入关卡时必须等待 session start 请求返回。 如果网络状态不好,玩家点击进入关卡后,可能会先看到一段空白等待。这对小游戏体验影响比较明显,尤其是关卡频繁切换、失败重开、每日挑战和生存模式这类入口,都会被网络请求拖慢。因此本次主要从“不要让 session 阻塞玩家进入关卡”这个方向进行调整。

进入关卡改为先展示棋盘

本次将普通关、每日挑战、生存模式的 session 启动流程都改为后台异步执行。 调整后的流程是: 这样玩家不会因为 session 请求而卡在进入页面。即使网络稍慢,也能先看到棋盘内容,整体体验会更流畅。 这次调整的核心原则是: 保留云端校验,但不要让云端请求阻塞玩家操作。 这里需要注意的是,session 仍然是必要的。它并没有被取消,只是不再作为进入关卡的前置阻塞条件。后续玩家完成关卡时,服务端仍然会根据 session 判断这局游戏是否有效,并决定是否允许结算、发放奖励或更新进度。

complete 结算兜底

除了 start 异步化,本次也确认了 complete 的处理方式。 玩家过关后,可以先展示结算面板,后台再请求服务端 complete。也就是说,结算界面不会因为网络请求而完全卡住。这样玩家过关后可以更快看到反馈,不会因为接口请求慢而觉得游戏卡顿。 但为了避免 complete 没成功时玩家继续推进流程,当前方案是:

  • 如果 complete 还没有成功返回,玩家点击下一关时,只弹出提示:网络错误,请稍后再试;
  • complete 最多重试 3 次;
  • 如果 3 次仍然失败,不再无限重试,只定时提示:网络错误,请重启游戏。 这样既能让结算面板先展示出来,又能避免服务端结算失败时,玩家继续进入下一关导致进度和资源状态不一致。 后续可以结合结算表现继续优化这部分体验。例如制作结算弹窗动画,在播放动画的过程中后台等待 complete 返回。如果请求正常完成,玩家几乎感知不到等待;如果请求失败,再通过提示阻止继续进入下一关。这样比直接让界面停住会更自然。

各玩法 Session 接口拆分

之前多个玩法共用旧的 start_level / complete_level 接口。早期玩法少时还能接受,但随着普通关、双鸡、每日挑战、生存模式逐步接入,每种模式的参数、次数消耗、奖励规则和校验逻辑都不同,继续共用接口会导致服务端堆很多条件判断。 本次确认后,将 Session 链路按玩法彻底拆分:

  • 普通关:普通关 start / complete;
  • 双鸡模式:双鸡 start / complete;
  • 每日挑战:每日 start / complete;
  • 生存模式:生存 start / complete。 拆分后的好处是每个模式都可以独立维护自己的规则。例如每日挑战要处理每日次数和新纪录,生存模式要处理波次、分数和体力奖励,普通关要处理关卡进度和体力消耗。如果继续放在同一个接口里,后续维护成本会越来越高。

四.云端资源变动路径审查与生存模式结算修复

随着云存档和 Session 机制逐步接入,金币、体力这类账号资源就不能再完全依赖客户端本地修改。否则玩家在云端模式下可能通过本地逻辑绕过服务端校验,导致服务端和客户端数据不一致。 因此今天对涉及体力、金币变动的路径做了一轮审查和修复。

生存模式结算体力发放修复

生存模式结算时会发放基础体力奖励。之前这部分在云端模式下不够完整,可能出现结算面板显示有体力奖励,但实际账号资源没有正确同步的问题。 本次在服务端 completeSurvival 中新增了体力发放逻辑,通过 grantAccountReward(player, { stamina: vitalBonus }) 自动发放基础体力。 同时,本地模式下也在客户端增加了兜底处理,直接执行 addStamina(vitalBonus),保证本地调试时也能看到正确效果。 结算面板文案也改成了:体力: +N(已发放) 这个文案比单纯显示 +N 更明确,可以告诉玩家这部分奖励已经到账,而不是还需要额外点击领取。

广告获取体力和金币改为服务端发放

修复了两个比较典型的资源漏洞。 第一个是看广告恢复体力:之前 StaminaRecoverPopupCtrl.ts 中存在直接 addStamina(60) 的逻辑。这个逻辑在纯本地阶段没问题,但在云端模式下就会绕过服务端。 第二个是胜利结算后看广告获得额外金币:之前 ResultPanelWinCtrl.ts 中也存在直接 addCoin(extraCoin) 的逻辑,同样会导致云端资源校验失效。 本次修复后,这两类逻辑都会先判断 CloudGameService.isAvailable():

  • 云端服务可用时,走服务端 grantReward;
  • 本地调试或离线模式下,才走本地直接加资源。 同时服务端补充了几个新的奖励来源:
  • stamina_recover_ad:看广告恢复体力;
  • win_ad_extra_coin:胜利后看广告额外金币;
  • survival_ad_extra_vital:生存模式看广告额外体力。 这样每一类奖励都有明确 source,服务端可以根据 source 做统一配置、校验和发放,后续排查问题也更方便。 这部分调整的核心是:云端模式下,客户端不再直接决定关键账号资源的变化。客户端可以发起请求、展示结果,但真正的金币、体力变动应该由服务端根据规则发放,然后再同步回客户端。

资源同步与 applyCloudSave 调整

在修复资源变动时,还处理了一个 save 同步被跳过的问题。 之前 applyCloudSave 会受到 isRunValid 检查影响。如果当前 run 状态异常,可能导致服务端 save 没有同步到客户端。 这类问题不一定会立刻报错,但可能造成一个更麻烦的后果:服务端资源已经变化了,但客户端没有及时刷新,玩家看到的金币、体力和真实云端数据不一致。 本次将 applyCloudSave 移到 isRunValid 检查之前。因为 save 同步主要是把服务端返回的最新存档覆盖到本地状态,即使重复执行几次,一般也只是重复同步同一份结果,不会像“金币 +100”这种操作一样造成资源叠加。但如果这一步被跳过,就会造成客户端状态和服务端状态不同步。

五.后续计划

  • 继续测试服务端相关改动,重点确认 CloudBase 存档读写、session 创建与清理、各模式 start / complete 链路、reward source 和生存体力发放是否正常生效。
  • 继续实测普通关、双鸡模式、每日挑战、生存模式的完整流程,重点关注进入关卡、体力消耗、完成结算、奖励发放、存档同步、下一关推进等环节。
  • 对测试过程中发现的 bug 和体验问题进行修复,优先处理影响关卡进入、资源同步、结算反馈的问题。