迁移指南

迁移指南:0.7 至 0.8

在迁移之前,请确保运行 rustup update

Bevy 严重依赖 Rust 语言和编译器的改进。因此,最低支持的 Rust 版本 (MSRV) 为 Rust 的“最新稳定版本”。

相机驱动渲染 #

这是一个非常复杂的更改,建议阅读链接的 PR 以获取更多详细信息

// old 3d perspective camera
commands.spawn_bundle(PerspectiveCameraBundle::default())

// new 3d perspective camera
commands.spawn_bundle(Camera3dBundle::default())
// old 2d orthographic camera
commands.spawn_bundle(OrthographicCameraBundle::new_2d())

// new 2d orthographic camera
commands.spawn_bundle(Camera2dBundle::default())
// old 3d orthographic camera
commands.spawn_bundle(OrthographicCameraBundle::new_3d())

// new 3d orthographic camera
commands.spawn_bundle(Camera3dBundle {
    projection: OrthographicProjection {
        scale: 3.0,
        scaling_mode: ScalingMode::FixedVertical(5.0),
        ..default()
    }.into(),
    ..default()
})

UI 不再需要专用的相机。UiCameraBundle 已被移除。Camera2dBundleCamera3dBundle 现在都默认将 UI 渲染为其自身渲染图的一部分。要禁用相机的 UI 渲染,请使用 UiCameraConfig 组件禁用它

commands
    .spawn_bundle(Camera3dBundle::default())
    .insert(UiCameraConfig {
        show_ui: false,
        ..default()
    })
// 0.7
camera.world_to_screen(transform, world_position);

// 0.8
camera.world_to_viewport(transform, world_position);

可见性继承、通用 ComputedVisibility 和 RenderLayers 支持 #

Visibility 现在以类似于 Transform 的方式传播到子元素中。层次结构的根元素现在必须包含 VisibilityComputedVisibility 才能使可见性传播起作用。

SpatialBundleVisibilityBundle 已被添加以方便使用。如果您之前使用的是 TransformBundle,现在您应该使用 SpatialBundle

如果您之前将 Visibility::is_visible 作为精灵或灯光等的“实际可见性”读取,请改用 ComputedVisibility::is_visible()

// 0.7
fn system(query: Query<&Visibility>) {
  for visibility in query.iter() {
    if visibility.is_visible {
       info!("found visible entity");
    }
  }
}

// 0.8
fn system(query: Query<&ComputedVisibility>) {
  for visibility in query.iter() {
    if visibility.is_visible() {
       info!("found visible entity");
    }
  }
}

使用 Affine3A 作为 GlobalTransform 以允许任何仿射变换 #

GlobalTransform 字段已更改

  • global_transform.translation() 替换 global_transform.translation(对于其他字段,请使用 compute_transform 方法)
  • GlobalTransform 不再支持非线性缩放,如果您觉得不方便,请告诉我们
  • 如果您需要 scalerotationtranslation 属性,您现在可以使用 global_transform.to_scale_rotation_translation()
// 0.7
let transform = Transform::from(*global_transform);
transform.scale
transform.rotation
transform.translation

// 0.8
let (scale, rotation, translation) = global_transform.to_scale_rotation_translation();

添加 SceneBundle 以生成场景 #

// 0.7
commands.spawn_scene(asset_server.load("models/FlightHelmet/FlightHelmet.gltf#Scene0"));

// 0.8
commands.spawn_bundle(SceneBundle {
    scene: asset_server.load("models/FlightHelmet/FlightHelmet.gltf#Scene0"),
    ..Default::default()
});

场景将作为具有 SceneBundle 的实体的子元素生成

使 ScalingMode 更灵活 #

添加了为 WindowSize 指定缩放系数的功能,为 FixedVerticalFixedHorizontal 指定固定轴的大小,以及一种新的 ScalingMode,它是 FixedVerticalFixedHorizontal 的混合。

允许在运行时关闭窗口 #

bevy::input::system::exit_on_esc_system 已被移除。改用 bevy::window::close_on_esc

CloseWindow 已被移除。改用 Window::close。Close 变体已添加到 WindowCommand 中。通过关闭相关窗口来处理它。

使 RunOnce 成为非手动系统实现 #

运行标准 RunOnce,它将使受控系统只运行一次,已被新的运行标准函数 ShouldRun::once 替换。将所有 RunOnce 实例替换为 ShouldRun::once

将 system_param 获取结构体移动到匿名作用域以避免命名冲突 #

对于使用系统参数获取结构体的代码,例如 EventReader 的 EventReaderState,现在可以通过 SystemParam 特性关联类型 Fetch 来识别获取结构体,例如对于 EventReader<T>,可以将其识别为 <EventReader<'static, 'static, T> as SystemParam>::Fetch

Task 不实现 Component #

如果您需要 Task 成为 Component,则应使用包装类型。

// 0.7
fn system(mut commands: Commands, thread_pool: Res<AsyncComputeTaskPool>) {
    let task = thread_pool.spawn(async move {
        // Complicated async work
        Vec2::ZERO
    });
    commands.spawn().insert(task);
}

// 0.8
#[derive(Component)]
struct ComputeVec2(Task<Vec2>);

fn system(mut commands: Commands) {
    let thread_pool = AsyncComputeTaskPool::get();
    let task = thread_pool.spawn(async move {
        // Complicated async work
        Vec2::ZERO
    });
    commands.spawn().insert(ComputeVec2(task));
}

将时间功能拆分为 bevy_time #

  • 与时间相关的类型(例如 TimeTimerStopwatchFixedTimestep 等)应从 bevy::time::* 而不是 bevy::core::* 中导入。
  • 如果您之前手动添加了 CorePlugin,您还需要从 bevy::time 添加 TimePlugin
  • bevy::core::CorePlugin::Time 系统标签已被 bevy::time::TimeSystem 替换。

将 float_ord 从 bevy_core 移动到 bevy_utils #

bevy::core::FloatOrd 的导入替换为 bevy::utils::FloatOrd

将 Rect 移动到 bevy_ui 并将其重命名为 UiRect #

Rect 类型已重命名为 UiRect

将 ElementState 重命名为 ButtonState #

ElementState 类型已重命名为 ButtonState

改进 RawWindowHandle 功能的文档和命名 #

HasRawWindowHandleWrapper 重命名为 ThreadLockedRawWindowHandleWrapper

从 crevice 迁移到 encase #

使用 ShaderType 而不是 AsStd140 和 AsStd430 #

// old
#[derive(AsStd140)]
struct Foo {
    a: Vec4,
    b: Mat4,
}

// new
#[derive(ShaderType)]
struct Foo {
    a: Vec4,
    b: Mat4,
}

StorageBuffer #

  • 移除 set_body()values()values_mut()clear()push()append()
  • 添加 set()get()get_mut()

UniformVec -> UniformBuffer #

  • uniform_buffer() 重命名为 buffer()
  • 移除 len()is_empty()capacity()push()reserve()clear()values()
  • 添加 set()get()

DynamicUniformVec -> DynamicUniformBuffer #

  • uniform_buffer() 重命名为 buffer()
  • 移除 capacity()reserve()

使暂停的计时器在 tick 时更新 just_finished #

Timer::times_finished 已被重命名为 Timer::times_finished_this_tick 以提高清晰度。

将默认的 Image FilterMode 更改为 Linear #

默认的 Image 过滤从 Nearest 更改为 Linear

// 0.7

// Nothing, nearest was the default

// 0.8
App::new()
    .insert_resource(ImageSettings::default_nearest())

Image.sampler_descriptor 已更改为使用 ImageSampler 而不是 SamplerDescriptor

// 0.7
texture.sampler_descriptor = SamplerDescriptor {
    address_mode_u: AddressMode::Repeat,
    address_mode_v: AddressMode::Repeat,
    ..default()
};

// 0.8
texture.sampler_descriptor = ImageSampler::Descriptor(SamplerDescriptor {
    address_mode_u: AddressMode::Repeat,
    address_mode_v: AddressMode::Repeat,
    ..default()
});

移除 .system() #

您不再可以使用 .system()。它在 0.7.0 中已被弃用。您可以直接移除方法调用。

如果您在测试中需要此功能,您可以改用 bevy_ecs::system::assert_is_system

将 gamepad.rs 元组更改为普通结构体 #

GamepadGamepadButtonGamepadAxisGamepadEventGamepadEventRaw 类型现在是普通结构体,而不是元组结构体,并且具有 new 函数。要进行迁移,请将所有实例化更改为使用 new() 函数,并使用相应的字段名称,而不是 .0 和 .1。

移除 EntityMut::get_unchecked #

将对 EntityMut::get_unchecked 的调用替换为对 EntityMut::get 的调用。

用 ReadOnlyWorldQuery 替换 ReadOnlyFetch #

ReadOnlyFetch 特性已被 ReadOnlyWorldQuery 替换,WorldQueryGats::ReadOnlyFetch 关联类型也被 <WorldQuery::ReadOnly as WorldQueryGats>::Fetch 替换

ReadOnlyFetch 特性已被 ReadOnlyWorldQuery 替换,WorldQueryGats::ReadOnlyFetch 关联类型也被 <WorldQuery::ReadOnly as WorldQueryGats>::Fetch 替换

  • 任何诸如 QueryFetch<Q>: ReadOnlyFetch 的 where 子句都应替换为 Q: ReadOnlyWorldQuery
  • 任何自定义世界查询实现都应实现 ReadOnlyWorldQuery,而不是 ReadOnlyFetch

函数 update_component_accessupdate_archetype_component_access 已从 FetchState 特性移动到 WorldQuery

  • 任何调用者现在应调用 Q::update_component_access(state 而不是 state.update_component_access(以及 update_archetype_component_access)。
  • 任何自定义世界查询实现都应该将函数从FetchState实现移到WorldQuery实现中。

WorldQuery已被设为unsafe traitFetchState已被设为安全的trait。(我认为这应该是它一直以来的方式,但无论如何,现在这两个函数已经移到WorldQuery中,这绝对是必要的。)

  • 如果您有自定义的FetchState实现,请将其设为普通的impl,而不是unsafe impl
  • 如果您有自定义的WorldQuery实现,请将其设为unsafe impl,如果您的代码之前是健全的,它将继续保持健全。

修复了使用Or/AnyOf/Option组件访问的健全性问题 #

已修复Or/AnyOf/Option的查询冲突,并使其更加严格,以避免未定义的行为。如果由于此更改导致新的查询冲突,则必须重构您的系统;考虑使用ParamSet

从par_for_each(_mut)中删除task_pool参数 #

Query(State)::par_for_each(_mut)task_pool参数已删除。从对这些函数的所有调用中删除这些参数。

// 0.7
fn parallel_system(
   task_pool: Res<ComputeTaskPool>,
   query: Query<&MyComponent>,
) {
   query.par_for_each(&task_pool, 32, |comp| {
        // ...
   });
}

// 0.8
fn parallel_system(query: Query<&MyComponent>) {
   query.par_for_each(32, |comp| {
        // ...
   });
}

如果在调度器运行的系统之外使用QueryQueryState,则可能需要在World中手动配置和初始化ComputeTaskPool作为资源。

在16位平台上无法编译 #

bevy_ecs现在将在16位平台上明确无法编译,因为它在这些平台上由于各种内部假设而无法正常工作。

目前没有替代方案,但我们欢迎添加支持。请提交问题以帮助详细说明您的用例。

强制使用Assets::get的类型安全用法 #

Assets::<T>::getAssets::<T>::get_mut现在要求传递的句柄是Handle<T>,从而提高了句柄的类型安全性。如果您之前传递的是

  • HandleId,请改用&Handle::weak(id)来创建弱句柄。您可能已经能够存储一个类型安全的Handle
  • HandleUntyped,请使用&handle_untyped.typed_weak()来创建指定类型的弱句柄。这在使用load_folder时最有可能有用。
  • &str或任何以前未提及的内容:assets.get(&assets.get_handle("asset/path.ron"))
  • Handle<U>的不同类型,请考虑这是否是要存储的正确句柄类型。如果是(即,同一个句柄 ID 用于多个不同的资产类型),请使用Handle::weak(handle.id)来转换为不同的类型。

允许使用高阶系统 #

SystemParamFunction已更改。它之前不是公共 API 的一部分,因此不提供迁移说明。(它现在已包含在公共 API 中,但您仍然不应该为自己的类型实现此特征)。

如果可能,任何自定义System实现都应该迁移到使用高阶系统,高阶系统要显著地更不容易出错。

需要研究才能让它适用于更多情况。

在TextureAtlas::from_grid_with_padding中添加了offset参数 #

TextureAtlas::from_grid_with_padding的调用应该修改为包含一个新参数,该参数可以设置为Vec2::ZERO以保留旧的行为。

// 0.7
from_grid_with_padding(texture, tile_size, columns, rows, padding)

// 0.8
from_grid_with_padding(texture, tile_size, columns, rows, padding, Vec2::ZERO)

拆分网格着色器文件 #

在用于 3D 网格的着色器中

  • #import bevy_pbr::mesh_view_bind_group -> #import bevy_pbr::mesh_view_bindings
  • #import bevy_pbr::mesh_struct -> #import bevy_pbr::mesh_types
    • 注意:如果您在绑定组索引 2 处使用网格绑定组,您可以在着色器中删除这些绑定语句,只需使用#import bevy_pbr::mesh_bindings,它本身会导入绑定所需的网格类型。

在用于 2D 网格的着色器中

  • #import bevy_sprite::mesh2d_view_bind_group -> #import bevy_sprite::mesh2d_view_bindings
  • #import bevy_sprite::mesh2d_struct -> #import bevy_sprite::mesh2d_types
    • 注意:如果您在绑定组索引 2 处使用 mesh2d 绑定组,您可以在着色器中删除这些绑定语句,只需使用#import bevy_sprite::mesh2d_bindings,它本身会导入绑定所需的 mesh2d 类型。

相机驱动的视口 #

Camera::projection_matrix不再是公共字段。请改用新的Camera::projection_matrix()方法。

// 0.7
let projection = camera.projection_matrix;

// 0.8
let projection = camera.projection_matrix();

诊断:当图节点的输入数量错误时,显示有意义的错误 #

RenderGraphRunnerError的穷尽匹配需要添加一个分支来处理新的MismatchedInputCount变体。

使Reflect安全地实现 #

  • Reflect推导不应该需要更改任何内容。
  • 手动反射实现需要删除unsafe关键字,添加any()实现,并将旧的anyany_mut重命名为as_anyas_mut_any
  • any/any_mut的调用必须更改为as_any/as_mut_any

将ECS存储下的可变API标记为pub(crate) #

如果您遇到此更改导致的任何问题,请创建一个问题,详细说明您使用这些 API 的方式。

为所有新类型化的TaskPools添加全局初始化和获取访问器 #

线程池不再需要存储在资源中,因为它们现在存储在全局范围内。您现在可以使用get()来访问它。

// 0.7
fn spawn_tasks(thread_pool: Res<AsyncComputeTaskPool>) {
    // Do something with thread_pool
}

// 0.8
fn spawn_tasks() {
    let thread_pool = AsyncComputeTaskPool::get();
    // Do something with thread_pool
}

简化*Labels的设计 #

  • 任何之前对Box<dyn SystemLabel>的使用都应该替换为SystemLabelId
  • AsSystemLabel特征已修改。
    • 不再有输出泛型。
    • 方法as_system_label现在返回SystemLabelId,删除了不必要的间接级别。
  • 如果您*需要*在运行时确定的标签,可以使用Box::leak。不建议这样做。

将get_short_name实用程序方法从bevy_reflect移到bevy_utils #

  • 添加了bevy_utils::get_short_name,它可以从类型名称中剥离路径,以方便显示。
  • 删除了TypeRegistry::get_short_name方法。请改用bevy_utils中的函数。

删除已死的SystemLabelMarker结构体 #

此结构体在内部没有使用、文档或可直观理解的外部使用。

它已被删除。

为资源添加反射 #

ReflectComponent::add_component重命名为ReflectComponent::insert_component

使reflect_partial_eq返回更准确的结果 #

之前,所有reflect_***_partial_eq帮助器方法在无法执行比较时返回Some(false),这具有误导性。它们现在在无法执行比较时返回None

使RenderStage::Extract在渲染世界中运行 #

ExtractRenderStage现在在渲染世界中运行(而不是像以前那样在主世界中运行)。您必须使用ExtractSystemParam才能在提取阶段访问主世界。Extract接受一个类型参数,该参数是任何系统参数(例如ResQuery等)。它将从主世界中提取此参数。请注意,CommandsExtract中不会正常工作 - 它目前会静默地不执行任何操作。

// 0.7
fn extract_clouds(mut commands: Commands, clouds: Query<Entity, With<Cloud>>) {
    for cloud in clouds.iter() {
        commands.get_or_spawn(cloud).insert(Cloud);
    }
}

// 0.8
fn extract_clouds(mut commands: Commands, mut clouds: Extract<Query<Entity, With<Cloud>>>) {
    for cloud in clouds.iter() {
        commands.get_or_spawn(cloud).insert(Cloud);
    }
}

您现在还可以使用正常的系统参数在Extract期间访问渲染世界的资源。

fn extract_assets(mut render_assets: ResMut<MyAssets>, source_assets: Extract<Res<MyAssets>>) {
     *render_assets = source_assets.clone();
}

由于提取现在在渲染世界中运行,因此主世界中的Res<RenderWorld>的使用应该替换为渲染世界中的Res<MainWorld>的使用。

请注意,所有现有的提取系统都需要更新以匹配这种新的样式;即使它们当前可以编译,它们也不会按预期运行。如果未满足此要求,则会尽力发出警告。

改进游戏手柄方向键按钮检测 #

方向键输入不再可以作为轴访问。请改用游戏手柄按钮来访问它们。

将窗口位置类型从元组更改为向量 #

更改了以下字段

  • WindowCommand::SetWindowMode.resolution(u32, u32)更改为UVec2
  • WindowCommand::SetResolution.logical_resolution(f32, f32)更改为Vec2

bevy_asset的完整文档 #

FileAssetIo::get_root_path重命名为FileAssetIo::get_base_path

FileAssetIo::root_path()root_path字段的获取器,而FileAssetIo::get_root_path返回资产根路径的父目录,该目录是可执行文件的目录,除非设置了CARGO_MANIFEST_DIR。此更改解决了这两个方法之间的歧义。

层次结构命令化 #

ParentChildren组件字段现在是私有的。

  • parent.0替换为parent.get()
  • children.0替换为*children
  • 您不能再构造ChildrenParent组件,您可以将其用作权宜之计,这可能会引入一帧延迟。
#[derive(Component)]
pub struct MakeChildOf(pub Entity);

fn add_parent(
    mut commands: Commands,
    orphans: Query<(Entity, &MakeChildOf)>,
) {
    for (child, MakeChildOf(parent)) in &orphans {
        commands.entity(*parent).add_child(child);
        commands.entity(child).remove::<MakeChildOf>();
    }
}

删除泛型类型上Reflect的通用Serialize + Deserialize要求 #

对于Option<T>Vec<T>HashMap<K, V>等泛型类型,.register_type将不再插入ReflectSerializeReflectDeserialize类型数据。相反,您需要像这样为具体的泛型类型单独注册它们

    .register_type::<Option<String>>()
    .register_type_data::<Option<String>, ReflectSerialize>()
    .register_type_data::<Option<String>, ReflectDeserialize>()

更轻量的无默认功能 #

在对bevy依赖项使用no-default-features时,bevy_assetbevy_scene不再启用。

  • 使用no-default-features的 Bevy 箱子如果依赖于这些功能,则需要手动添加这些功能。
bevy = { version = "0.8", default-features = false, features = [
    "bevy_asset",
    "bevy_scene",
] }

改进创建文本元素的可用性和减少样板代码 #

Text::with_section已重命名为Text::from_section,不再接受TextAlignment作为参数。请改用with_alignment来设置对齐方式。

添加QueryState::get_single_unchecked_manual及其家族 #

system::QuerySingleError更改为query::QuerySingleError

tracing-tracy 已从 0.8.0 更新至 0.10.0 #

使用 trace-tracy 功能时,现在需要 0.8.1 版本的 tracy。