关于 bevy-save-load
面向 Bevy 0.19 游戏开发者的存档与读档设计指南,强调用独立、版本化的数据模型而非运行时 ECS 结构持久化。内容涵盖迁移、稳定 ID、校验、恢复及原生与浏览器存储。
主要功能
- 01设计独立且版本化的存档模型
- 02使用稳定 ID 并分两阶段加载
- 03执行显式版本迁移与数据校验
- 04处理原生文件和浏览器存储
- 05规划快照、增量与故障恢复
适用场景
- 01让存档兼容 ECS 或内容重构
- 02为大型世界管理快照与增量
- 03为原生和浏览器版本实现异步存档
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ chrisgliddon/ bevy-skills --skill bevy-save-load安装后在 Claude Code 中输入/bevy-save-load确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/native-and-browser-io.mdschema-migrations-and-ids.mdsnapshots-deltas-and-world-serialization.md详细介绍
Bevy 0.19 — 保存与加载
何时使用此技能
- 游戏状态必须能够在 ECS、内容或代码重构后继续加载。
- 大型世界需要基础快照、稀疏增量、压缩和恢复。
- 原生和浏览器构建需要采用统一的异步保存服务契约。
- 正在考虑将反射式世界序列化用作持久化存档格式。
存档文件是长期存在的产品 API。应序列化显式、带版本的数据模型,并将其与实时 ECS 相互转换。运行时 Entity 值、密集调色板索引、查询顺序、Rust 枚举判别值和反射组件布局都不是稳定的持久化标识。
规范模式
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[serde(transparent)]
struct SaveId(String);
#[derive(Debug, Deserialize, Serialize)]
struct SaveV3 {
world_seed: u64,
player: SaveId,
actors: Vec<ActorV3>,
}
#[derive(Debug, Deserialize, Serialize)]
struct ActorV3 {
id: SaveId,
archetype: String,
position: [f32; 3],
}
live Bevy World
-> validate/capture one logical revision
-> current Save DTO with stable IDs
-> encode + checksum envelope
-> platform storage transaction
platform bytes
-> size/magic/checksum validation
-> decode declared old DTO
-> migrate one version at a time
-> validate current DTO
-> allocate entities, then resolve stable-ID references
-> rebuild derived/runtime-only state
字节仍在解码或迁移时,绝不要部分修改活动世界。应先加载到暂存区并进行验证,然后再提交或替换游戏世界。
为封套和负载添加版本
将编码后的负载字节封装起来,包含魔数、格式版本、架构/内容版本、负载长度、编解码/压缩标识符以及校验和。校验和可以检测意外损坏,但不能防止恶意篡改。如果需求涉及信任,请使用身份验证或签名。
将迁移保留为显式的 V1 -> V2 -> V3 纯函数。测试每个受支持版本的黄金样本,包括损坏、截断、重复 ID、未知 ID 和未来版本的文件。绝不要将旧版本直接反序列化到当前结构体中,并指望 Serde 默认值能还原旧语义。
稳定 ID 和两阶段加载
为已保存对象、内容、任务、物品和体素方块类型使用不可变的领域 ID。加载时:
- 验证 ID 的唯一性以及所有大小/数量限制;
- 生成/分配对象,并构建
SaveId -> Entity或稳定 ID -> 密集调色板的映射; - 在第二阶段解析关系;
- 根据策略拒绝未知内容,或明确予以保留;
- 重建缓存、句柄、物理状态、任务、诊断信息和呈现内容。
存储因平台而异
原生写入应在目标目录中使用临时文件,按需刷新并同步,然后以原子方式替换/重命名已提交的存档槽。需要恢复能力时,应保留经过验证的备份,或采用双槽代次机制。在 IoTaskPool 上执行阻塞式文件 I/O,并将结果发送回主世界。
浏览器没有常规的存档文件路径。使用 IndexedDB 保存游戏存档和二进制数据;小型偏好设置可以使用本地存储。应处理异步完成、配额、驱逐、隐私模式、标签页竞争、导出/导入以及页面终止等情况。只有在确认存储已提交后,UI 才能显示“保存完成”。
Bevy 0.19 的 SettingsPlugin 面向使用原生/本地存储后端的用户设置,并非通用的战役/世界存档架构。
注意事项:世界序列化边界
bevy_world_serialization 和 DynamicWorldBuilder 可以通过组件/资源允许或拒绝过滤器,提取反射实体和资源。这适用于创作型世界资产、编辑器工具、受控快照和短期内部格式。但它不会自动提供稳定的游戏 ID、架构迁移、损坏恢复、事务式存储,也无法保证组件重构后的兼容性。
持久化玩家存档应使用显式 DTO。如果该格式中嵌套了经过过滤的 DynamicWorld,则应对外围契约进行版本管理和迁移,并有意审查每种反射类型。
选择相关的深入指南
| 问题 | 阅读 |
|---|---|
| DTO 版本、迁移、稳定 ID、验证和黄金样本 | 架构、迁移和 ID |
| 原子原生写入、浏览器存储、异步状态和恢复 | 原生和浏览器 I/O |
| 完整快照、稀疏增量、压缩、世界序列化边界 | 快照、增量和世界序列化 |
审查清单
- 存档架构类型与实时 ECS/运行时组件彼此分离。
- 每个持久化引用都使用有文档记录的稳定 ID。
- 旧版本按顺序迁移,并提供已提交的测试固件。
- 解码器会在分配或解压缩前限制不可信的长度和计数。
- 原生平台的断电故障以及浏览器的配额或终止故障都能保留可恢复的存档槽。
- 只有在平台提交完成后才报告成功。
- 快照和增量数据的代次不会意外混用。
- 遇到未知的未来版本时会安全失败,不会覆盖原始数据。
另请参阅
bevy-voxel-data— 稳定区块 ID 与密集运行时调色板的区别。bevy-testing— 确定性迁移和故障路径测试。bevy-assets— 稳定的资源路径/标签和资源就绪状态。- Bevy 世界序列化
DynamicWorldBuilder