Game Save 冲突与原子单元
概述
当你在多台设备上修改同一份游戏数据时,就会发生存档冲突。系统需要决定保留哪个版本。要设计存档数据结构,你需要理解系统如何检测和解决冲突。冲突发生的时机
只有在以下条件全部满足时,同步操作(PFGameSaveFilesAddUserWithUiAsync)期间才会发生冲突:
- 存在本地更改:自上次同步以来,你在本地修改了文件。
- 存在云端更改:自上次同步以来,另一台设备上传了更新的数据。
- 同一原子单元:两项更改都位于同一个根级文件夹内。
冲突检测矩阵
什么是原子单元?
一些文件同步系统按文件为单位处理冲突。如果同一个文件需要同时上传和下载,就会产生冲突。在 Game Saves 中,每个根级子文件夹被视为一个原子单元。每个根级子文件夹都是一个原子单元。
- 保持数据完整性:相互依赖的文件保持一致
- 提供隔离性:位于不同文件夹的独立数据同步时不会互相冲突
- 最小化冲突:不同设备上对不同原子单元的更改会自动合并
存档结构示例
冲突场景
根级文件:特殊情况
存档根目录下的所有文件共享一个原子单元。 系统会将你直接放在存档根目录(未放入任何子文件夹)下的所有文件归为一个原子单元。如果你在本地修改了一个根级文件,而另一台设备修改了另一个根级文件,这种差异会触发冲突。用户选项
发生冲突时,玩家在以下选项中做出选择:- 使用本地数据(保留本地):保留设备当前的存档数据。
- 使用云端数据(保留云端):下载并使用云端存档数据。
关键:解决方式为全有或全无
⚠️ 重要提示:虽然原子单元决定了何时检测到冲突,但用户对冲突的解决选择会应用于整个存档,而不是按原子单元分别应用。
示例:混合冲突场景
为什么这很重要
- 保留本地会丢失仅存在于云端的更改:如果因为 SlotA 中的冲突而选择”保留本地”,你将不会获得另一台设备对 SlotC 所做的云端更新。
- 保留云端会丢失仅存在于本地的更改:如果选择”保留云端”,云端状态将覆盖你对 SlotB 和 SlotD 的本地更改。
- 可用于回滚:两种选择都会保留被舍弃的分支,以备将来回滚。
设计小结
这种全有或全无的方式简化了玩家体验。尽管从技术上讲按原子单元解决冲突可以保持数据一致性(因为原子单元定义了一致性边界),但会带来用户体验方面的问题:
- 玩家需要理解原子单元与文件夹边界的概念。
- 混合结果(有些文件夹来自本地,有些来自云端)可能让玩家对最终状态感到困惑。
- 分别对每个冲突的原子单元进行提示,会让冲突解决过程令人不知所措。
不发生冲突的情况
双端均删除
如果两台设备都删除了同一个文件(或同一原子单元中的文件),不会发生冲突。系统识别到两台设备都同意应该移除该文件。不同原子单元中的更改
如果设备 A 修改SlotA/ 中的文件、设备 B 修改 SlotB/ 中的文件,就不会发生冲突。同步会自动合并两项更改。
最佳实践
1. 谨慎设计文件夹结构
为独立的存档单元使用子文件夹:- 共享参考数据:将任何存档槽位都可能使用的数据(如已解锁内容或成就)存储在其自己的子文件夹中,使其独立于各存档槽位进行同步。
- 大型资源集合:如果你的游戏存储的大量文件是独立更新的(例如已下载的内容包或用户创建的关卡),可以考虑将它们拆分到多个根级子文件夹,这样一个集合的更新不会与另一个集合的更新冲突。
