【OpenHarmony/HarmonyOS】从本地排行到 AGC 云数据:玩家、匹配、房间与战绩模型设计

当前项目的正式数据链路以 Preferences 本地存储为主,同时已经准备了 PlayerStats、MatchRequest、GameRoom 和 BattleRecord 模型。本文给出一条从离线优先走向云同步与匹配服务的演进方案。☁️

⚠️ 说明:本文是基于工程预留模型的架构设计,不代表项目当前已经完成 AGC 云数据库和云排行榜接入。

一、为什么先做本地优先?

游戏的基本体验不应被网络阻断。本地优先具有明显优势:

  • 首次进入不等待远端请求;
  • 无网也能玩 PvE、解谜和限时模式;
  • 结算结果立即可见;
  • 云服务故障不会导致当局数据全部丢失;
  • 在账号和服务端未完成前,也能独立迭代核心玩法。

但本地存储无法提供跨设备同步、全服排行榜、在线匹配和可信战绩,因此需要在稳定本地模型之上逐步加云层。

二、四个核心云对象

1. PlayerStats

class PlayerStats {
  uid: string;
  level: number;
  exp: number;
  winRate: number;
  bestScore: number;
  updatedAt: number;
  userName: string;
  avatar: string;
}

它代表玩家聚合数据。uid 应来自正式认证服务,不应直接使用本地时间戳 ID。

2. MatchRequest

class MatchRequest {
  requestId: string;
  uid: string;
  status: string;
  roomId: string;
  createdAt: number;
}

玩家点击匹配时创建。状态可定义为 matchingmatchedcancelledexpired,并使用服务端时间判断超时。

3. GameRoom

class GameRoom {
  roomId: string;
  playerA: string;
  playerB: string;
  state: string;
  lastFrameData: string;
}

房间保存参与者与当前状态。把完整实时帧持续写云数据库并不适合高频动作游戏,lastFrameData 更适合作为断线恢复摘要、准备状态或低频快照。

4. BattleRecord

class BattleRecord {
  recordId: string;
  winnerId: string;
  loserId: string;
  duration: string;
  timestamp: string;
}

战绩用于历史、排行审计和统计。工程当前字段把时长与时间戳定义为字符串,后续建议改为明确数值/日期类型,避免排序和区间查询困难。

三、本地和云端不应互相直接覆盖

推荐在本地数据外加同步元数据:

interface SyncEnvelope<T> {
  schemaVersion: number;
  revision: number;
  updatedAt: number;
  dirty: boolean;
  deviceId: string;
  data: T;
}

本地每次结算先写入 Preferences,并标记 dirty。网络可用且已登录时,后台同步队列再提交云端;成功后清除 dirty 标记。

flowchart TD
    A[游戏结算] --> B[事务性写本地]
    B --> C[生成 Sync Job]
    C --> D{登录且联网}
    D --  --> E[保留队列]
    D --  --> F[提交云端]
    F --> G{成功}
    G --  --> H[清除 dirty]
    G --  --> I[指数退避重试]

四、冲突解决不能只比较分数

不同字段需要不同策略:

  • bestScore:取最大值;
  • totalGameswins:不能简单取最大,最好上传不可重复事件或增量;
  • 昵称、头像:最后修改优先或让用户选择;
  • 晶石余额:必须有服务端账本,不能客户端随意覆盖;
  • 升级等级:服务端校验购买交易后更新;
  • 设置项:通常设备本地,不一定需要上云。

一个统一“云端新就全覆盖本地”的策略会丢失离线期间的增量。

五、排行榜数据应该由谁可信? 🏆

本地 ScoreManager 接收客户端给出的任意分数。用于个人历史没有问题,用于全服排行榜就容易被修改。

云排行榜至少需要:

  • 已认证 UID;
  • 服务端或权威主机确认的比赛结果;
  • 合理的分数范围和时长校验;
  • 幂等的 recordId,防止重复提交;
  • 可追踪的模式、难度、客户端版本;
  • 异常分数审查或风控。

提交接口不应只有 uid + score,而应围绕一场不可重复的比赛记录设计。

六、匹配不能由两个客户端抢同一条记录

最简单的客户端匹配逻辑是查询另一个 matching 请求,然后双方更新为 matched。如果三个客户端同时读取,同一个玩家可能被重复匹配。

更可靠的方式是由云函数或服务端事务完成:

  1. createdAt 获取等待队列;
  2. 在事务/锁中选择两个仍为 matching 的请求;
  3. 创建唯一 roomId
  4. 原子更新两条请求;
  5. 客户端监听自己的请求变化;
  6. 超时或取消时使用条件更新。

客户端只提交和订阅,不参与权威配对。

七、云数据库不适合直接做 120Hz 帧同步

实时动作游戏每秒可能产生几十到上百次输入/状态。把每帧 JSON 写数据库会带来:

  • 写入延迟与抖动;
  • 成本和限流;
  • 数据库监听不是实时游戏协议;
  • 状态覆盖、乱序和冲突难以处理;
  • 大量无意义历史帧。

更合理的分工:

云数据库:账号、匹配、房间元数据、战绩、排行榜
云函数:匹配、结算校验、异步任务
SoftBus/UDP/专用实时通道:当局输入和快照
本地 Preferences:离线进度、缓存、待同步队列

八、模型字段需要加强

建议为所有云对象增加:

interface CloudMeta {
  schemaVersion: number;
  createdAt: number;
  updatedAt: number;
  revision: number;
}

房间还应包含:

  • hostUid、玩家列表与队伍;
  • 地图 seed 与规则版本;
  • 模式、难度、目标比分;
  • state 枚举而非任意字符串;
  • 最后心跳和过期时间;
  • 结算 ID 与签名。

地图 seed 很重要:双方用相同算法和 seed 生成地图,避免传输完整二维数组,但必须同时锁定生成器版本。

九、认证与本地游客迁移 🔐

玩家可能先以本地游客玩了很多局,之后才登录账号。此时要决定:

  • 把本地进度合并到新账号;
  • 保留云端已有进度;
  • 对晶石等敏感经济只允许有限迁移;
  • 一个本地档案是否只能绑定一次;
  • 退出账号后保留哪些缓存。

推荐把本地 userId 视为设备档案 ID,登录后另存认证 UID,并记录已完成迁移的标志,保证过程幂等。

十、同步队列设计

interface SyncJob {
  jobId: string;
  type: 'SAVE_STATS' | 'SUBMIT_RECORD' | 'UPDATE_PROFILE';
  payload: string;
  attempts: number;
  nextRetryAt: number;
  createdAt: number;
}

失败后采用指数退避,网络恢复时唤醒;达到最大次数后保留并记录可诊断错误。不要在游戏结束弹窗中阻塞等待上传。

十一、迁移路径建议 🚀

阶段 1:整理本地模型

修复字段类型,加入 schemaVersion,统一 Manager 接口和写入串行化。

阶段 2:只读云排行

保留本地个人记录,登录用户可以查看云榜,失败回退空态。

阶段 3:异步提交战绩

本地先成功,后台队列提交,服务端做幂等和范围校验。

阶段 4:用户资料同步

处理游客绑定、冲突和多设备。

阶段 5:云端匹配

云函数负责原子配对,房间只保存元数据,实时战斗走独立通道。

十二、测试重点 ✅

  • 断网结算后重启应用,任务是否仍在;
  • 同一 recordId 重试是否只记一次;
  • 两台设备同时修改资料如何解决;
  • 匹配取消与成功同时发生时的最终状态;
  • 房间过期是否清理;
  • 云数据 schema 升级;
  • 服务端时间与客户端时间不一致;
  • 登录过期、权限拒绝和账号切换;
  • 排行榜异常分数拦截;
  • 网络恢复时是否集中重试造成请求风暴。

十三、总结 ✨

从本地游戏演进到云端,不是把 Preferences.put() 换成一个远程 API。需要重新定义:

  • 哪些数据本地优先,哪些必须服务端权威;
  • 每个字段如何合并;
  • 提交如何幂等;
  • 匹配如何原子化;
  • 实时战斗与数据库如何分工;
  • 游客和正式账号如何迁移;
  • 失败任务如何持久重试。

先做稳健的离线层,再逐步叠加云能力,通常比一开始让每个页面直接访问云数据库更可靠。☁️


推荐标签: HarmonyOS OpenHarmony AGC 云数据库 离线优先 游戏匹配

img

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐