迁移指南:0.5 到 0.6

现在需要 Rust 2021 #

Bevy 已更新为使用 Rust 2021。这意味着我们可以默认情况下利用新的 Cargo 特性解析器(Bevy 和新版本的 wgpu 都需要)。确保将你的包更新到 Rust 2021,否则你需要在你的 Cargo.toml 中手动启用新的特性解析器,方法是使用 `resolver = "2"`。

[package]
name = "your_app"
version = "0.1.0"
edition = "2021"

请注意,"虚拟 Cargo 工作区" 仍然需要手动定义 `resolver = "2"`,即使在 Rust 2021 中也是如此。 查看 Rust 2021 文档 了解详细信息。

[workspace]
resolver = "2" # Important! wgpu/Bevy needs this!
members = [ "my_crate1", "my_crate2" ]

"AppBuilder" 已合并到 "App" #

AppBuilder 的所有函数都已合并到 App 中。

实际上,这意味着你可以通过调用 App::new 来开始构建 App,而不是 App::build,并且 Plugin::build 接受 App 而不是 AppBuilder

// 0.5
fn main() {
    App::build()
        .add_plugin(SomePlugin)
        .run();
}

impl Plugin for SomePlugin {
    fn build(&self, app: &mut AppBuilder) {

    }
}

// 0.6
fn main() {
    App::new()
        .add_plugin(SomePlugin)
        .run();
}

impl Plugin for SomePlugin {
    fn build(&self, app: &mut App) {

    }
}

现在需要派生 "Component" 特性 #

Bevy 不再对 Component 特性提供泛型实现。相反,你需要为每个需要它的类型派生(或手动实现)特性。

// 0.5
struct MyComponent;

// 0.6
#[derive(Component)]
struct MyComponent;

为了将外部类型用作组件,请使用新类型模式将它们包装起来。

#[derive(Component)]
struct Cooldown(std::time::Duration);

现在在 "Component" 特性中设置组件存储 #

对派生 Component 的更改允许在编译时而不是运行时设置组件存储。

// 0.5
appbuilder
    .world
    .register_component(ComponentDescriptor::new::<MyComponent>(
        StorageType::SparseSet,
    ))
    .unwrap();

// 0.6
#[derive(Component)]
#[component(storage = "SparseSet")]
struct MyComponent;

现在在系统上调用 ".system()" 是可选的 #

向 Bevy 添加系统时,不再需要事先调用 .system()

// 0.5
fn main() {
    App::new()
        .add_system(first_system.system())
        .add_system(second_system.system())
        .run();
}

// 0.6
fn main() {
    App::new()
        .add_system(first_system)
        .add_system(second_system.system())
        .run();
}

系统配置函数(如 .label().config())现在也可以直接在系统上调用。

// 0.5
fn main() {
    App::new()
        .add_system(first_system.system().label("FirstSystem"))
        .add_system(second_system.system().after("FirstSystem"))
        .run();
}

// 0.6
fn main() {
    App::new()
        .add_system(first_system.label("FirstSystem"))
        .add_system(second_system.after("FirstSystem"))
        .run();
}

".single()" 和 ".single_mut()" 现在是无误的 #

函数 Query::single()Query::single_mut() 不再返回 Result,而是如果只找到一个实体,则会抛出异常。

如果你需要旧的行为,可以使用 fallible [Query::get_single()] 和 [Query_get_single_mut()] 代替。

// 0.5
fn player_system(query: Query<&Transform, With<Player>>) {
    let player_position = query.single().unwrap();
    // do something with player_position
}

// 0.6
fn player_system_infallible(query: Query<&Transform, With<Player>>) {
    let player_position = query.single();
    // do something with player_position
}

fn player_system_fallible(query: Query<&Transform, With<Player>>) {
    let player_position = query.get_single().unwrap();
    // do something with player_position
}

"Light" 和 "LightBundle" 现在是 "PointLight" 和 "PointLightBundle" #

// 0.5
commands.spawn_bundle(LightBundle {
    light: Light {
        color: Color::rgb(1.0, 1.0, 1.0),
        depth: 0.1..50.0,
        fov: f32::to_radians(60.0),
        intensity: 200.0,
        range: 20.0,
    },
    ..Default::default()
});

// 0.6
commands.spawn_bundle(PointLightBundle {
    light: PointLight {
        color: Color::rgb(1.0, 1.0, 1.0),
        intensity: 200.0,
        range: 20.0,
    },
    ..Default::default()
});

LightLightBundle 类型已重命名为 PointLightPointLightBundle,以便更清楚地传达光源的行为。同时,fovdepth 字段已从 PointLight 中删除,因为它们没有被使用。

系统参数生命周期拆分 #

SystemParam 的生命周期已拆分为两个不同的生命周期。

// 0.5
type SystemParamAlias<'a> = (Res<'a, AssetServer>, Query<'a, &'static Transform>, Local<'a, i32>);

#[derive(SystemParam)]
struct SystemParamDerive<'a> {
    res: Res<'a, AssetServer>,
    query: Query<'a, &Transform>,
    local: Local<'a, i32>,
}

// 0.6
type SystemParamAlias<'w, 's> = (Res<'w, AssetServer>, Query<'w, 's, &'static Transform>, Local<'s, i32>);

#[derive(SystemParam)]
struct SystemParamDerive<'w, 's> {
    res: Res<'w, AssetServer>,
    query: Query<'w, 's, &'static Transform>,
    local: Local<'s, i32>,
}

QuerySet 声明 "QueryState" 而不是 "Query" #

由于 系统参数生命周期拆分QuerySet 系统参数现在需要使用 QueryState 而不是 Query 来指定它们的查询。

// 0.5
fn query_set(mut queries: QuerySet<(Query<&mut Transform>, Query<&Transform>)>) {

}

// 0.6
fn query_set(mut queries: QuerySet<(QueryState<&mut Transform>, QueryState<&Transform>)>) {

}

"Input<T>.update()" 重命名为 "Input<T>.clear()" #

Input::update 函数已重命名为 Input::clear

"SystemState" 现在是 "SystemMeta" #

以前称为 SystemState 的结构,它存储系统的元数据,已重命名为 SystemMeta

这样做是为了适应新的 SystemState,它允许更容易地缓存访问 SystemParam,而不是在常规系统之外。

向量转换函数现在被命名为匹配返回类型 #

IVec2DVec2UVec2Vec2 的转换函数已从以其内部元素的转换目标命名更改为整个 "Vec" 被转换成的内容。这会影响数学向量的所有不同维度(即 Vec2Vec3Vec4)。

// 0.5
let xyz: Vec3 = Vec3::new(0.0, 0.0, 0.0);
let xyz: IVec3 = xyz.as_i32();

// 0.6
let xyz: Vec3 = Vec3::new(0.0, 0.0, 0.0);
let xyz: IVec3 = xyz.as_ivec3();

StandardMaterial 的 "roughness" 重命名为 "perceptual_roughness" #

StandardMaterial 字段 roughness 已重命名为 perceptual_roughness

SpriteBundle 和 Sprite #

SpriteBundle 包类型现在使用 texture 句柄而不是 material。材料的 color 字段现在直接在 Sprite 结构中可用,该结构还将其 resize_mode 字段替换为 custom_size。以下示例展示了如何在特定大小处生成一个带色调的精灵。对于更简单的情况,请查看更新的 精灵矩形 示例。

// 0.5
SpriteBundle {
    sprite: Sprite {
        size: Vec2::new(256.0, 256.0),
        resize_mode: SpriteResizeMode::Manual,
        ..Default::default()
    },
    material: materials.add(ColorMaterial {
        color: Color::RED,
        texture: Some(asset_server.load("branding/icon.png")),
    }),
    ..Default::default()
}

// 0.6
SpriteBundle {
    sprite: Sprite {
        custom_size: Some(Vec2::new(256.0, 256.0)),
        color: Color::RED,
        ..Default::default()
    },
    texture: asset_server.load("branding/icon.png"),
    ..Default::default()
}

Visible 现在是 Visibility #

Visible 结构,它用于许多组件中以设置可见性,已重命名为 Visibility。此外,is_transparent 字段已从结构中删除。对于 3D,可以使用材料上的 alpha_mode 字段设置透明度。现在,2D 中的所有对象都自动启用透明度。

// 0.5
let material_handle = materials.add(StandardMaterial {
    base_color_texture: Some(texture.clone()),
    ..Default::default()
});

commands.spawn_bundle(PbrBundle {
    material: material_handle,
    visible: Visible {
        is_visible: true,
        is_transparent: true,
    },
    ..Default::default()
});

// 0.6
let material_handle = materials.add(StandardMaterial {
    base_color_texture: Some(texture.clone()),
    alpha_mode: AlphaMode::Blend,
    ..Default::default()
});

commands.spawn_bundle(PbrBundle {
    material: material_handle,
    visibility: Visibility {
        is_visible: true,
    },
    ..Default::default()
});