Skip to content

Latest commit

 

History

History
514 lines (358 loc) · 22.4 KB

File metadata and controls

514 lines (358 loc) · 22.4 KB

+++ title = "0.7 to 0.8" weight = 4 sort_by = "weight" template = "book-section.html" page_template = "book-section.html" insert_anchor_links = "right" [extra] long_title = "Migration Guide: 0.7 to 0.8" +++

This is a very complicated change and it is recommended to read the linked PRs for more details

// 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,
        ..default()
    }.into(),
    ..default()
})

UI no longer requires a dedicated camera. UiCameraBundle has been removed. Camera2dBundle and Camera3dBundle now both default to rendering UI as part of their own render graphs. To disable UI rendering for a camera, disable it using the UiCameraConfig component:

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);

Visibility is now propagated into children in a similar way to Transform. Root elements of a hierarchy must now contain Visibility and ComputedVisiblity for visibility propagation to work.

SpatialBundle and VisibilityBundle have been added for convenience. If you were using a TransformBundle you should probably be using a SpatialBundle now.

If you were previously reading Visibility::is_visible as the "actual visibility" for sprites or lights, use ComputedVisibilty::is_visible() instead:

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

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

GlobalTransform fields have changed

  • Replace global_transform.translation by global_transform.translation() (For other fields, use the compute_transform method)
  • GlobalTransform do not support non-linear scales anymore, we'd like to hear from you if it is an inconvenience for you
  • If you need the scale, rotation or translation property you can now use 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();
// 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()
});

The scene will be spawned as a child of the entity with the SceneBundle

Adds ability to specify scaling factor for WindowSize, size of the fixed axis for FixedVertical and FixedHorizontal and a new ScalingMode that is a mix of FixedVertical and FixedHorizontal

bevy::input::system::exit_on_esc_system has been removed. Use bevy::window::close_on_esc instead.

CloseWindow has been removed. Use Window::close instead. The Close variant has been added to WindowCommand. Handle this by closing the relevant window.

The run criterion RunOnce, which would make the controlled systems run only once, has been replaced with a new run criterion function ShouldRun::once. Replace all instances of RunOnce with ShouldRun::once.

For code that was using a system param's fetch struct, such as EventReader's EventReaderState, the fetch struct can now be identified via the SystemParam trait associated type Fetch, e.g. for EventReader<T> it can be identified as <EventReader<'static, 'static, T> as SystemParam>::Fetch

If you need a Task to be a Component you should use a wrapper type.

// 0.7
fn system(mut commands: Commands) {
    let task = thread_pool.spawn(async move {
        let start_time = Instant::now();
        while Instant::now() - start_time < Duration::from_secs_f32(5.0) {
            // Spinning for 'duration', simulating doing hard
        }
        Vec2::ZERO
    });
    commands.spawn().insert(task);
}

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

fn system(mut commands: Commands) {
    let task = thread_pool.spawn(async move {
        let start_time = Instant::now();
        while Instant::now() - start_time < Duration::from_secs_f32(5.0) {
            // Spinning for 'duration', simulating doing hard
        }
        Vec2::ZERO
    });
    commands.spawn().insert(ComputeVec2(task));
}
  • Time related types (e.g. Time, Timer, Stopwatch, FixedTimestep, etc.) should be imported from bevy::time::* rather than bevy::core::*.
  • If you were adding CorePlugin manually, you'll also want to add TimePlugin from bevy::time.
  • The bevy::core::CorePlugin::Time system label is replaced with bevy::time::TimeSystem.

Replace imports of bevy::core::FloatOrd with bevy::utils::FloatOrd.

The Rect type has been renamed to UiRect.

The ElementState type has been renamed to ButtonState.

Renamed HasRawWindowHandleWrapper to ThreadLockedRawWindowHandleWrapper.

StorageBuffer

  • removed set_body(), values(), values_mut(), clear(), push(), append()
  • added set(), get(), get_mut()

UniformVec -> UniformBuffer

  • renamed uniform_buffer() to buffer()
  • removed len(), is_empty(), capacity(), push(), reserve(), clear(), values()
  • added set(), get()

DynamicUniformVec -> DynamicUniformBuffer

  • renamed uniform_buffer() to buffer()
  • removed capacity(), reserve()

Timer::times_finished has been renamed to Timer::times_finished_this_tick for clarity.

Default Image filtering changed from Nearest to Linear.

// 0.7

// Nothing, nearest was the default

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

You can no longer use .system(). It was deprecated in 0.7.0. You can just remove the method call.

If you needed this for tests purposes, you can use bevy_ecs::system::assert_is_system instead.

The Gamepad, GamepadButton, GamepadAxis, GamepadEvent and GamepadEventRaw types are now normal structs instead of tuple structs and have a new function. To migrate change every instantiation to use the new() function instead and use the appropriate field names instead of .0 and .1.

Replace calls to EntityMut::get_unchecked with calls to EntityMut::get.

The trait ReadOnlyFetch has been replaced with ReadOnlyWorldQuery along with the WorldQueryGats::ReadOnlyFetch assoc type which has been replaced with <WorldQuery::ReadOnly as WorldQueryGats>::Fetch

The trait ReadOnlyFetch has been replaced with ReadOnlyWorldQuery along with the WorldQueryGats::ReadOnlyFetch assoc type which has been replaced with <WorldQuery::ReadOnly as WorldQueryGats>::Fetch

  • Any where clauses such as QueryFetch<Q>: ReadOnlyFetch should be replaced with Q: ReadOnlyWorldQuery.
  • Any custom world query impls should implement ReadOnlyWorldQuery instead of ReadOnlyFetch

Functions update_component_access and update_archetype_component_access have been moved from the FetchState trait to WorldQuery

  • Any callers should now call Q::update_component_access(state instead of state.update_component_access (and update_archetype_component_access respectively)
  • Any custom world query impls should move the functions from the FetchState impl to WorldQuery impl

WorldQuery has been made an unsafe trait, FetchState has been made a safe trait. (I think this is how it should have always been, but regardless this is definitely necessary now that the two functions have been moved to WorldQuery)

  • If you have a custom FetchState impl make it a normal impl instead of unsafe impl
  • If you have a custom WorldQuery impl make it an unsafe impl, if your code was sound before it is going to still be sound

Query conflicts from Or/AnyOf/Option have been fixed, and made stricter to avoid undefined behaviour. If you have new query conflicts due to this you must refactor your systems; consider using ParamSet.

The task_pool parameter for Query(State)::par_for_each(_mut) has been removed. Remove these parameters from all calls to these functions.

Before:

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

After:

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

If using Query or QueryState outside of a system run by the scheduler, you may need to manually configure and initialize a ComputeTaskPool as a resource in the World.

bevy_ecs will now explicitly fail to compile on 16-bit platforms, because it is unsound on those platforms due to various internal assumptions.

There is currently no alternative, but we're open to adding support. Please file an issue (https://github.com/bevyengine/bevy/issues) to help detail your use case.

Assets::<T>::get and Assets::<T>::get_mut now require that the passed handles are Handle<T>, improving the type safety of handles. If you were previously passing in:

  • a HandleId, use &Handle::weak(id) instead, to create a weak handle. You may have been able to store a type safe Handle instead.
  • a HandleUntyped, use &handle_untyped.typed_weak() to create a weak handle of the specified type. This is most likely to be the useful when using load_folder
  • a Handle<U> of of a different type, consider whether this is the correct handle type to store. If it is (i.e. the same handle id is used for multiple different Asset types) use Handle::weak(handle.id) to cast to a different type.

SystemParamFunction has changed. It was not previously part of the public API, so no migration instructions are provided. (It is now included in the public API, although you still should not implement this trait for your own types).

If possible, any custom System implementations should be migrated to use higher order systems, which are significantly less error-prone.

Research is needed into allowing this to work for more cases.

Calls to TextureAtlas::from_grid_with_padding should be modified to include a new parameter, which can be set to Vec2::ZERO to retain old behaviour.

from_grid_with_padding(texture, tile_size, columns, rows, padding)
                                  |
                                  V
from_grid_with_padding(texture, tile_size, columns, rows, padding, Vec2::ZERO)
  • In shaders for 3D meshes:
    • #import bevy_pbr::mesh_view_bind_group -> #import bevy_pbr::mesh_view_bindings
    • #import bevy_pbr::mesh_struct -> #import bevy_pbr::mesh_types
      • NOTE: If you are using the mesh bind group at bind group index 2, you can remove those binding statements in your shader and just use #import bevy_pbr::mesh_bindings which itself imports the mesh types needed for the bindings.
  • In shaders for 2D meshes:
    • #import bevy_sprite::mesh2d_view_bind_group -> #import bevy_sprite::mesh2d_view_bindings
    • #import bevy_sprite::mesh2d_struct -> #import bevy_sprite::mesh2d_types
      • NOTE: If you are using the mesh2d bind group at bind group index 2, you can remove those binding statements in your shader and just use #import bevy_sprite::mesh2d_bindings which itself imports the mesh2d types needed for the bindings.

Camera::projection_matrix is no longer a public field. Use the new Camera::projection_matrix() method instead:

// 0.7
let projection = camera.projection_matrix;

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

Exhaustive matches on RenderGraphRunnerError will need to add a branch to handle the new MismatchedInputCount variant.

  • Reflect derives should not have to change anything
  • Manual reflect impls will need to remove the unsafe keyword, add any() implementations, and rename the old any and any_mut to as_any and as_mut_any.
  • Calls to any/any_mut must be changed to as_any/as_mut_any

If you experienced any problems caused by this change, please create an issue explaining in detail what you were doing with those apis.

Thread pools don't need to be stored in a resource anymore since they are now stored globally. You can now use get() to access it.

// 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
}
  • Any previous use of Box<dyn SystemLabel> should be replaced with SystemLabelId.
  • AsSystemLabel trait has been modified.
    • No more output generics.
    • Method as_system_label now returns SystemLabelId, removing an unnecessary level of indirection.
  • If you need a label that is determined at runtime, you can use Box::leak. Not recommended.
  • added bevy_utils::get_short_name, which strips the path from a type name for convenient display.
  • removed the TypeRegistry::get_short_name method. Use the function in bevy_utils instead.

This struct had no internal use, docs, or intuitable external use.

It has been removed.

Rename ReflectComponent::add_component into ReflectComponent::insert_component.

Updated struct_trait, tuple_struct, tuple, array, list and map to return None when comparison couldn't be performed.

The Extract RenderStage now runs on the render world (instead of the main world as before). You must use the Extract SystemParam to access the main world during the extract phase. Extract takes a single type parameter, which is any system parameter (such as Res, Query etc.). It will extract this from the main world. Note that Commands will not work correctly in Extract - it will currently silently do nothing.

// 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);
    }
}

You can now also access resources from the render world using the normal system parameters during Extract:

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

Please note that all existing extract systems need to be updated to match this new style; even if they currently compile they will not run as expected. A warning will be emitted on a best-effort basis if this is not met.

D-pad inputs can no longer be accessed as axes. Access them as gamepad buttons instead.

Changed the following fields

  • WindowCommand::SetWindowMode.resolution from (u32, u32) to UVec2
  • WindowCommand::SetResolution.logical_resolution from (f32, f32) to Vec2
  • Rename FileAssetIo::get_root_path uses to FileAssetIo::get_base_path

    FileAssetIo::root_path() is a getter for the root_path field, while FileAssetIo::get_root_path returned the parent directory of the asset root path, which was the executable's directory unless CARGO_MANIFEST_DIR was set. This change solves the ambiguity between the two methods.

The Parent and Children component fields are now private.

  • Replace parent.0 by parent.get()
  • Replace children.0 with *children
  • You can't construct Children or Parent component anymore, you can use this as a stopgap measure, which may introduce a single frame delay
#[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>();
    }
}
  • .register_type for generic types like Option<T>, Vec<T>, HashMap<K, V> will no longer insert ReflectSerialize and ReflectDeserialize type data. Instead you need to register it separately for concrete generic types like so:
    .register_type::<Option<String>>()
    .register_type_data::<Option<String>, ReflectSerialize>()
    .register_type_data::<Option<String>, ReflectDeserialize>()