17次发布
| 0.3.2 | 2024年4月21日 |
|---|---|
| 0.3.1 | 2024年4月18日 |
| 0.2.3 | 2024年4月15日 |
| 0.1.11 | 2024年4月2日 |
| 0.1.6 | 2024年3月18日 |
#852 in 编码
每月下载量57次
用于 bevy_stat_query
96KB
2K SLoC
bevy_serde_project
bevy引擎的具有状态、结构化和可读性的序列化包。
功能
- 具有世界访问权限的状态序列化和反序列化。
- 将
Entity、其Component和子项视为单个 serde 对象。 - 序列化
Handle并提供通用数据合并接口。 - 像智能指针一样序列化存储的
Entity。 - 将 trait 对象(如
Box<dyn T>)反序列化为序列化,作为typetag的替代方案。 - 极其轻量级且模块化。无系统,无插件。
- 支持几乎所有 serde 格式*
* 人体工程学可能取决于 Serializer、Deserializer 和 DeserializeSeed 特性支持
入门
序列化具有一些组件和子项的 Entity 角色,假设所有组件都是 Serialize 和 DeserializeOwned
bind_object!(Character as "Character" {
#[serde(flatten)]
character: Character,
position: Position,
#[serde(default, skip_serializing_if="Option::is_none")]
weapon: Maybe<Weapon>,
shield: Maybe<Shield>,
#[serde(default, skip_serializing_if="Vec::is_empty")]
potions: ChildVec<Potion>,
})
然后调用 save 在 World 上,其中 serializer 是类似 serde_json::Serializer 的东西。
// Save
world.save::<Character>(serializer)
// Load
world.load::<Character>(deserializer)
// Delete
world.despawn_bound_objects::<Character>()
这将保存角色列表作为数组
[
{ .. },
{ .. },
..
]
要批量保存多种类型的对象,使用 batch! 宏创建批量序列化类型。
type SaveFile = batch!(
Character, Monster, Terrain,
// Use `BindResource` to serialize a resource.
BindResource<MyResource>,
);
world.save::<SaveFile>(serializer)
world.load::<SaveFile>(serializer)
world.despawn_bound_objects::<SaveFile>()
这将按映射条目保存每个类型
{
"Character": [
{ .. },
{ .. },
..
],
"Monster": [ .. ],
"Terrain": [ .. ],
"MyResource": ..
}
常见问题解答
- 如果我的类型不是
Serialize和DeserializeOwned呢?
我们可以使用 SerdeProject 派生或实现以将它们转换为 serde 类型。
- 我不拥有该类型
使用 Convert 和 SerdeProject 宏将类型转换为所有权的 newtype。
- 我有一个 ID 并且我想序列化其内容
SerdeProject 允许你在序列化过程中从世界中获取资源。
- 我有一个
Box<dyn T>
如果你在一个非Wasm平台上,你可以尝试 typetag 包。如果不是,或者你想要更多控制,请查看此包中的 typetagged 模块。
特性和它们的作用
Serialize和DeserializeOwned
任何 Serialize 和 DeserializeOwned 类型都自动是 SerdeProject,而任何这样的 Component 都自动是 BevyObject。
这的缺点是我们不能由于孤儿规则而在任何外部类型上实现 SerdeProject。这就是 Convert 和 SerdeProject 宏发挥作用的地方。
SerdeProject
SerdeProject 将非serde类型投影到具有世界访问权限的serde类型。
SerdeProject 宏在所有字段都实现 SerdeProject 或通过 Convert 特征转换为 SerdeProject 新类型的类型上实现了 SerdeProject。
示例
将 Handle 序列化为它的路径,存储在 AssetServer 中。
#[derive(SerdeProject)]
struct MySprite {
// implements serde, therefore is `SerdeProject`.
pub name: String,
// Calls `Convert` and `PathHandle<Image>` is `SerdeProject`.
#[serde_project("PathHandle<Image>")]
pub handle: Handle<Image>
}
Convert
Convert 允许你将不可序列化的类型 RefCast 为实现 SerdeProject 的新类型。
例如,PathHandle<Handle<T>> 将 Handle 序列化为 String,而 UniqueHandle<Handle<T>> 将 Handle 序列化为 T。这种零成本的转换可以通过 ref_cast 包来完成。
BevyObject
BevyObject 允许将 Entity 序列化。这可以是只是一个组件,或者组件的组合,子组件,子组件上的组件等。
所有 SerdeProject 组件都是 BevyObject。
BindBevyObject
BindBevyObject 是一个 QueryFilter,通常是一个键组件,它确定序列化和反序列化的入口点。
任何具有 QueryFilter 但不满足绑定 BevyObject 布局的实体将导致错误。
使用 bind_object! 宏创建序列化条目。
Named
为资源提供序列化名称。
SaveLoad
表示批序列化类型,或单个保存文件的内容。
TypeTag
typetag 包允许你序列化像 Box<dyn T> 这样的特质对象,但使用 typetag 总是会拉入与你的构建相关联的所有实现,并且不适用于WASM。为了解决这些限制,此包允许你在bevy World 中手动注册反序列化器,并使用 TypeTagged 新类型进行序列化。
world.register_typetag::<Box<dyn Animal>, Cat>()
然后
#[derive(SerdeProject)]
struct MyComponent {
#[serde_project("TypeTagged<Box<dyn Weapon>>")]
weapon: Box<dyn Weapon>
}
为了拥有用户友好的配置文件,您可以使用 register_deserialize_any 和 AnyTagged 允许 deserialize_any,即使用 42 而不是在自描述格式中使用 {"int": 42}。请注意,在非自描述格式(如 postcard)中使用 AnyTagged 总会返回错误,因为这是 serde 规范的限制。
world.register_deserialize_any(|s: &str|
Ok(Box::new(s.parse::<Cat>()
.map_err(|e| e.to_string())?
) as Box<dyn Animal>)
)
版本
| bevy | bevy-serde-project |
|---|---|
| 0.13 | 最新版 |
许可证
许可协议为以下之一
- Apache License,版本 2.0(LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT 许可证(LICENSE-MIT 或 https://open-source.org.cn/licenses/MIT)
由您选择。
贡献
除非您明确说明,否则任何有意提交以包含在您的工作中的贡献(根据 Apache-2.0 许可证定义),均应如上双许可,无需附加条款或条件。
依赖项
~18–53MB
~866K SLoC