迁移指南

迁移指南:0.8 到 0.9

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

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

使 Resource 特性选择加入,需要 #[derive(Resource)] V2 #

在所有用作资源的类型中添加 #[derive(Resource)]

如果您使用第三方类型作为资源,请将其包装在元组结构中以绕过孤儿规则。考虑推导出 DerefDerefMut 以提高人体工程学。

ClearColor 不再实现 Component。在 0.8 中使用 ClearColor 作为组件不会有任何作用。请改为在 Camera3dCamera2d 组件中使用 ClearColorConfig

插件拥有自己的设置。重新设计 PluginGroup 特性。 #

WindowDescriptor 设置已从资源移动到 WindowPlugin::window

// Old (Bevy 0.8)
app
  .insert_resource(WindowDescriptor {
    width: 400.0,
    ..default()
  })
  .add_plugins(DefaultPlugins)

// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.set(WindowPlugin {
  window: WindowDescriptor {
    width: 400.0,
    ..default()
  },
  ..default()
}))

AssetServerSettings 资源已被删除,转而使用直接 AssetPlugin 配置

// Old (Bevy 0.8)
app
  .insert_resource(AssetServerSettings {
    watch_for_changes: true,
    ..default()
  })
  .add_plugins(DefaultPlugins)

// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.set(AssetPlugin {
  watch_for_changes: true,
  ..default()
}))

add_plugins_with 已被 add_plugins 结合构建器模式所取代

// Old (Bevy 0.8)
app.add_plugins_with(DefaultPlugins, |group| group.disable::<AssetPlugin>());

// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.build().disable::<AssetPlugin>());

PluginGroupBuilderPluginGroup 特性也已重新设计。

// Old (Bevy 0.8)
impl PluginGroup for HelloWorldPlugins {
    fn build(&mut self, group: &mut PluginGroupBuilder) {
        group.add(PrintHelloPlugin).add(PrintWorldPlugin);
    }
}

// New (Bevy 0.9)
impl PluginGroup for HelloWorldPlugins {
    fn build(self) -> PluginGroupBuilder {
        PluginGroupBuilder::start::<Self>()
            .add(PrintHelloPlugin)
            .add(PrintWorldPlugin)
    }
}

在设置时使用插件设置仅在设置时使用的资源 #

LogSettings 设置已从资源移动到 LogPlugin 配置

// Old (Bevy 0.8)
app
  .insert_resource(LogSettings {
    level: Level::DEBUG,
    filter: "wgpu=error,bevy_render=info,bevy_ecs=trace".to_string(),
  })
  .add_plugins(DefaultPlugins)

// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.set(LogPlugin {
    level: Level::DEBUG,
    filter: "wgpu=error,bevy_render=info,bevy_ecs=trace".to_string(),
}))

ImageSettings 设置已从资源移动到 ImagePlugin 配置

// Old (Bevy 0.8)
app
  .insert_resource(ImageSettings::default_nearest())
  .add_plugins(DefaultPlugins)

// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest()))

DefaultTaskPoolOptions 设置已从资源移动到 CorePlugin::task_pool_options

// Old (Bevy 0.8)
app
  .insert_resource(DefaultTaskPoolOptions::with_num_threads(4))
  .add_plugins(DefaultPlugins)

// New (Bevy 0.9)
app.add_plugins(DefaultPlugins.set(CorePlugin {
  task_pool_options: TaskPoolOptions::with_num_threads(4),
}))

删除 AssetServer::watch_for_changes() #

AssetServer::watch_for_changes() 已被删除。请改为直接在 AssetPlugin 上设置它。

app
  .add_plugin(DefaultPlugins.set(AssetPlugin {
    watch_for_changes: true,
    ..default()
  }))

Spawn 现在采用 Bundle #

// Old (0.8):
commands
  .spawn()
  .insert_bundle((A, B, C));
// New (0.9)
commands.spawn((A, B, C));

// Old (0.8):
commands.spawn_bundle((A, B, C));
// New (0.9)
commands.spawn((A, B, C));

// Old (0.8):
let entity = commands.spawn().id();
// New (0.9)
let entity = commands.spawn_empty().id();

// Old (0.8)
let entity = world.spawn().id();
// New (0.9)
let entity = world.spawn_empty().id();

接受 Bundle 用于插入和删除。弃用 insert/remove_bundle #

insert_bundle 替换为 insert

// Old (0.8)
commands.spawn().insert_bundle(SomeBundle::default());
// New (0.9)
commands.spawn_empty().insert(SomeBundle::default());

remove_bundle 替换为 remove

// Old (0.8)
commands.entity(some_entity).remove_bundle::<SomeBundle>();
// New (0.9)
commands.entity(some_entity).remove::<SomeBundle>();

remove_bundle_intersection 替换为 remove_intersection

// Old (0.8)
world.entity_mut(some_entity).remove_bundle_intersection::<SomeBundle>();
// New (0.9)
world.entity_mut(some_entity).remove_intersection::<SomeBundle>();

考虑尽可能多地合并操作以提高人体工程学并减少原型移动

// Old (0.8)
commands.spawn()
  .insert_bundle(SomeBundle::default())
  .insert(SomeComponent);

// New (0.9) - Option 1
commands.spawn_empty().insert((
  SomeBundle::default(),
  SomeComponent,
))

// New (0.9) - Option 2
commands.spawn((
  SomeBundle::default(),
  SomeComponent,
))

Component 实现 Bundle。使用 Bundle 元组进行插入 #

当为嵌套捆绑包推导出 Bundle 时,不再需要 #[bundle] 属性。

#[derive(Bundle)]
struct PlayerBundle {
    #[bundle] // Remove this line
    sprite_bundle: SpriteBundle,
    collider: Collider,
}

用 TimerMode 替换 Timer 的 bool 参数 #

  • Timer::new(duration, false) 替换为 Timer::new(duration, TimerMode::Once)
  • Timer::new(duration, true) 替换为 Timer::new(duration, TimerMode::Repeating)
  • Timer::from_seconds(seconds, false) 替换为 Timer::from_seconds(seconds, TimerMode::Once)
  • Timer::from_seconds(seconds, true) 替换为 Timer::from_seconds(seconds, TimerMode::Repeating)
  • timer.repeating() 更改为 timer.mode() == TimerMode::Repeating

添加全局时间缩放 #

一些 Time 方法已重命名以保持一致性。

大多数方法返回的值现在已按使用 set_relative_speed 设置的可选值进行缩放。大多数系统应继续使用这些缩放值。如果您需要未缩放的时间,请使用以 raw_ 为前缀的新方法。

// Old (Bevy 0.8)
let dur: Duration = time.time_since_startup();
let secs: f32 = time.time_since_startup().as_secs_f32();
let secs: f64 = time.seconds_since_startup();

// New (Bevy 0.9)
let dur: Duration = time.elapsed();
let secs: f32 = time.elapsed_seconds();
let secs: f64 = time.elapsed_seconds_f64();

更改 UI 坐标系,使原点位于左上角 #

所有 flex 布局都应反转(ColumnReverse => Column、FlexStart => FlexEnd、WrapReverse => Wrap)处理光标位置的系统应更改为考虑光标位置基于左上角而不是左下角

UiColor 重命名为 BackgroundColor #

UiColor 已重命名为 BackgroundColor。此更改影响 NodeBundleButtonBundleImageBundle。此外,ExtractedUiNode 上的相应字段已重命名为 background_color 以保持一致性。

使 NodeBundle 的默认背景颜色透明 #

如果您想要具有白色背景的 NodeBundle,则必须显式指定它

// Old (Bevy 0.8)
let node = NodeBundle {
    ..default()
}

// New (Bevy 0.9)
let node = NodeBundle {
    background_color: Color::WHITE.into(),
    ..default()
}

阐明 bevy::ui::Node 字段和文档 #

所有对旧 size 名称的引用都已更改,要访问 bevy::ui::Node size 字段,请使用 calculated_size

删除 SizeUiRect 泛型 #

SizeUiRect 的泛型 T 已被删除,它们现在始终使用 Val。如果您使用的是 Size<f32>,请考虑将其替换为 Vec2,后者功能更强大。

删除 margins.rs #

Margins 类型已删除。要迁移,您只需将所有 Margins 更改为 UiRect

Size 移动到 bevy_ui #

Size 类型已从 bevy::math 移动到 bevy::ui。要迁移,您只需导入 bevy::ui::Size 而不是 bevy::math::Math,或者使用 bevy::prelude

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

Rect 类型已重命名为 UiRect。要迁移,您只需将所有 Rect 更改为 UiRect

sprite::Rect 移动到 bevy_math #

bevy::sprite::Rect 类型已移至数学实用程序 crate 作为 bevy::math::Rect。您应将导入项从 use bevy::sprite::Rect 更改为 use bevy::math::Rect

独占系统现在实现 System。灵活的独占系统参数 #

不再需要(也不支持)为将独占系统函数转换为独占系统调用 .exclusive_system()

// Old (0.8)
app.add_system(some_exclusive_system.exclusive_system());
// New (0.9)
app.add_system(some_exclusive_system);

通过调用独占排序 API 来将“普通”并行系统转换为独占系统

// Old (0.8)
app.add_system(some_system.exclusive_system().at_end());
// New (0.9)
app.add_system(some_system.at_end());

独占系统中的查询状态现在可以通过 ExclusiveSystemParams 进行缓存,出于清晰度和性能原因,应优先考虑此方法

// Old (0.8)
fn some_system(world: &mut World) {
  let mut transforms = world.query::<&Transform>();
  for transform in transforms.iter(world) {
  }
}
// New (0.9)
fn some_system(world: &mut World, transforms: &mut QueryState<&Transform>) {
  for transform in transforms.iter(world) {
  }
}

IntoExclusiveSystem 特性已删除。请改为使用 IntoSystem

ExclusiveSystemDescriptorCoercion 特性已删除。您可以删除任何对它的导入。

通过选项参数将 TextureAtlas::from_grid_with_padding 合并到 TextureAtlas::from_grid 中 #

TextureAtlas::from_grid_with_padding 已合并到 from_grid 中,后者接受两个用于填充和偏移的额外参数。

// 0.8
TextureAtlas::from_grid(texture_handle, Vec2::new(24.0, 24.0), 7, 1);
// 0.9
TextureAtlas::from_grid(texture_handle, Vec2::new(24.0, 24.0), 7, 1, None, None)

// 0.8
TextureAtlas::from_grid_with_padding(texture_handle, Vec2::new(24.0, 24.0), 7, 1, Vec2::new(4.0, 4.0));
// 0.9
TextureAtlas::from_grid(texture_handle, Vec2::new(24.0, 24.0), 7, 1, Some(Vec2::new(4.0, 4.0)), None)

play 重命名为 start 并添加一个新的 play 方法,该方法不会覆盖已在播放的动画 #

如果您之前使用 play 重新启动正在播放的动画,该功能已移至 start。现在,如果请求的动画正在播放,play 将不起作用。

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

GamepadGamepadButtonGamepadAxisGamepadEventGamepadEventRaw 类型现在是普通结构体,而不是元组结构体,并且具有 new() 函数。为了迁移,请将每个实例化改为使用 new() 函数,并使用相应的字段名称,而不是 .0.1

InputAxisButtonSettings 添加 getter 和 setter #

AxisSettings 现在具有 new(),它可能会返回 AxisSettingsErrorAxisSettings 字段已变为私有;现在必须通过 getter 和 setter 访问。有一个死区,从 .deadzone_upperbound().deadzone_lowerbound(),以及一个活动区,从 .deadzone_upperbound().livezone_upperbound() 以及从 .deadzone_lowerbound().livezone_lowerbound()AxisSettings setter 不会再引起 panic。ButtonSettings 字段已变为私有;现在必须通过 getter 和 setter 访问。ButtonSettings 现在具有 new(),它可能会返回 ButtonSettingsError

添加 GamepadInfo,公开游戏手柄名称 #

  • 针对 GamepadEventType::Connected 的模式匹配需要更新,因为变体的形式已更改。
  • 需要 GamepadEventGamepadEventRawGamepadEventTypeCopy 的代码需要更新。

Gamepad 类型为 Copy;在 Gamepads API 中不要求/返回对它的引用 #

  • Gamepads::iter 现在返回 Gamepad 的迭代器,而不是 &Gamepad 的迭代器。
  • Gamepads::contains 现在接受 Gamepad,而不是 &Gamepad

wgpu 更新至 0.14.0,将 naga 更新至 0.10.0,将 winit 更新至 0.27.4,将 raw-window-handle 更新至 0.5.0,将 ndk 更新至 0.7 #

调整 bevy_window::WindowDescriptorcursor_lockedcursor_grab_mode 的使用,并将其类型从 bool 调整为 bevy_window::CursorGrabMode

支持所有窗口模式的显示器选择。 #

MonitorSelection 已从 WindowPosition::Centered 中移出,并移入 WindowDescriptorMonitorSelection::Number 已重命名为 MonitorSelection::Index

// Before
.insert_resource(WindowDescriptor {
    position: WindowPosition::Centered(MonitorSelection::Number(1)),
    ..default()
})
// After
.add_plugins(DefaultPlugins.set(WindowPlugin {
    window: WindowDescriptor {
        monitor: MonitorSelection::Index(1),
        position: WindowPosition::Centered,
        ..default()
    },
    ..default()
}))

Window::set_position 现在接受 MonitorSelection 作为参数。

window.set_position(MonitorSelection::Current, position);

将系统链接重命名为系统管道 #

系统上的 .chain(handler_system) 方法现在是 .pipe(handler_system)IntoChainSystem 特性现在是 IntoPipeSystemChainSystem 结构体现在是 PipeSystem

Transform 及其朋友添加关联常量 IDENTITY #

TransformGlobalTransformTransformBundle 上的 identity() 方法已删除。请改为使用关联常量 IDENTITY

Transform::mul_vec3 重命名为 transform_point 并改进文档 #

Transform::mul_vec3 已重命名为 transform_point

删除 Transform::apply_non_uniform_scale #

Transform::apply_non_uniform_scale 已删除。它可以用以下代码片段替换

transform.scale *= scale_factor;

删除 face_toward.rs #

FaceToward 特性已删除。要迁移,您只需将所有 Mat4::face_toward 更改为 Mat4::look_at_rh 即可。

用实际的 gats 替换 WorldQueryGats 特性 #

WorldQuery 特性上的实际 gats 替换 WorldQueryGats 关联类型的使用。

添加用于访问 Table 宽度的方法 #

任何使用 Table::len 的地方现在都应改为 Table::entity_count。任何使用 Table::capacity 的地方现在都应改为 Table::entity_capacity

Handle::<T> 字段 id 设置为私有,并用 getter 替换 #

如果您之前访问 handle.id 的值,现在可以使用 handle.id() 来访问。

添加 TimeUpdateStrategy 资源,用于手动更新 Time #

更改启动时 time.delta() 报告的值。

之前它将是 [0, 0, correct],此 PR 将其更改为 [0, "大约是 time_system 和 present_frame 之间的时间",correct]

添加用于消除系统顺序歧义警告的方法 #

歧义集已被更简单的 API 替换。

// These systems technically conflict, but we don't care which order they run in.
fn jump_on_click(mouse: Res<Input<MouseButton>>, mut transforms: Query<&mut Transform>) { ... }
fn jump_on_spacebar(keys: Res<Input<KeyCode>>, mut transforms: Query<&mut Transform>) { ... }

// Old (Bevy 0.8)
#[derive(AmbiguitySetLabel)]
struct JumpSystems;

app
  .add_system(jump_on_click.in_ambiguity_set(JumpSystems))
  .add_system(jump_on_spacebar.in_ambiguity_set(JumpSystems));

// New (Bevy 0.9)
app
  .add_system(jump_on_click.ambiguous_with(jump_on_spacebar))
  .add_system(jump_on_spacebar);

删除未使用的 DepthCalculation 枚举 #

删除对 bevy_render::camera::DepthCalculation 的引用,例如 use bevy_render::camera::DepthCalculation。从 Projections 中删除 depth_calculation 字段。

WindowExtractedWindow 中的 raw_window_handle 字段设为 Option #

Window::raw_window_handle() 现在返回 Option<RawWindowHandleWrapper>

修复不一致的子级删除行为 #

  • 使用 Changed<Children> 的查询将不再匹配使用 remove_children 删除所有子级的实体。
  • RemovedComponents<Children> 现在将包含使用 remove_children 删除所有子级的实体。

Entity 的“ID”应改为命名为“index” #

Entity::id() 方法已重命名为 Entity::index()

QueryCombinationIter 中删除 ExactSizeIterator #

QueryCombinationIter 不再实现 len。您可以使用 size_hint().0 获取相同的值,但请注意,超过 usize::MAX 的值将返回为 usize::MAX

Query 过滤器类型必须是 ReadOnlyWorldQuery #

查询过滤器 (F) 泛型现在由 ReadOnlyWorldQuery 绑定,而不是 WorldQuery。如果您出于某种原因请求了 Query<&A, &mut B>,请改为使用 Query<&A, With<B>>

List 特性添加 pop 方法。 #

任何实现 List 特性的自定义类型现在都需要实现 pop 方法。

删除对 impl Trait 的过时解决方法 #

Schedule::get_stageget_stage_mut 方法现在接受 impl StageLabel,而不是 &dyn StageLabel

添加更改检测旁路和对更改滴答的 manuell 控制 #

为任何您已为其实现 DetectChanges 的类型添加 Inner 关联类型和新方法。

将内部结构体 ShaderData 设为非 pub #

从公共 API 中删除了 ShaderData,它仅在内部使用。没有公共函数使用它,因此不需要进行任何迁移操作。

Children 构造函数设为 pub(crate) #

Children::with() 现在已重命名为 Children::from_entities(),现在是 pub(crate)

将 Handle::as_weak() 重命名为 cast_weak() #

  • Handle::as_weak 用法重命名为 Handle::cast_weak

该方法现在会正确设置关联类型 uuid(如果句柄是直接引用,例如,不是对 AssetPath 的引用),因此如果您依赖于之前的行为,请相应地调整您的代码。

Local 中删除 Sync 绑定 #

任何依赖于 Local<T> 具有 T: Resource 的代码可能需要更改,但这不太可能。

Local<T> 中添加 FromWorld 绑定到 T #

没有 T: FromWorldLocal 的引用可能存在,但这些引用应该非常罕见,并且可能是死代码。如果遇到其中一个,最简单的解决方法是删除代码或将内部 T 包裹在 Option 中,以允许它默认构造为 None

这可能还会带来其他较小的影响(例如 Debug 表示),但序列化可能是最突出的影响。

std::thread::available_parallelism 替换 num_cpus #

bevy_tasks::logical_core_countbevy_tasks::physical_core_count 已删除。logical_core_count 已被 bevy_tasks::available_parallelism 替换,工作方式相同。如果需要 bevy_tasks::physical_core_count,则可以直接使用 num_cpus crate,因为这两个只是 num_cpus API 的别名。

将诊断从秒更改为毫秒 #

诊断值现在以毫秒为单位。如果您需要秒,只需将其除以 1000.0 即可;

将指数移动平均值添加到诊断中 #

LogDiagnosticsPlugin 现在记录的是平滑后的值,而不是原始值。

  • 对于记录频率低于每 0.1 秒一次的诊断,此更改对默认值不会有任何明显影响。
  • 对于不希望进行此平滑的离散诊断,请将平滑因子设置为 0 以禁用平滑。
  • 最近历史记录的平均值在可用时仍然会显示。

作用域上的嵌套生成 #

如果您之前使用的是显式生命周期和传递作用域,现在您需要指定两个生命周期。

// 0.8
fn scoped_function<'scope>(scope: &mut Scope<'scope, ()>) {}

// 0.9
fn scoped_function<'scope>(scope: &Scope<'_, 'scope, ()>) {}

scope.spawn_local 已更改为 scope.spawn_on_scope,这应该涵盖您需要在本地线程上运行任务的情况,但不涵盖生成 Nonsend Futures 的情况。不再支持在作用域上生成 NonSend Futures。

将资源提取到它们自己的专用存储区 #

资源已移至 World 中的 Storages 下的 Resources。所有依赖于 Archetype::unique_components(_mut) 的代码都应改为通过 world.storages().resources() 访问它。

所有访问单个资源原始数据(可变*和*只读)的 API 已经被移除,因为这些 API 允许不安全的代码。所有使用这些 API 的地方应该改为使用 World::{get, insert, remove}_resource

清理 Fetch 代码 #

更改:Fetch::table_fetchFetch::archetype_fetch 已合并为单个 Fetch::fetch 函数。

ElementState 重命名为 ButtonState #

ElementState 类型已重命名,现在称为 ButtonState。要迁移,您只需将所有 ElementState 替换为 ButtonState

修复不正确且不必要的法线贴图代码 #

bevy_pbr::pbr_functions 着色器导入中的 prepare_normal 已重新设计。

之前

    pbr_input.world_normal = in.world_normal;

    pbr_input.N = prepare_normal(
        pbr_input.material.flags,
        in.world_normal,
#ifdef VERTEX_TANGENTS
#ifdef STANDARDMATERIAL_NORMAL_MAP
        in.world_tangent,
#endif
#endif
        in.uv,
        in.is_front,
    );

之后

    pbr_input.world_normal = prepare_world_normal(
        in.world_normal,
        (material.flags & STANDARD_MATERIAL_FLAGS_DOUBLE_SIDED_BIT) != 0u,
        in.is_front,
    );

    pbr_input.N = apply_normal_mapping(
        pbr_input.material.flags,
        pbr_input.world_normal,
#ifdef VERTEX_TANGENTS
#ifdef STANDARDMATERIAL_NORMAL_MAP
        in.world_tangent,
#endif
#endif
        in.uv,
    );

来自 #6354#6345#5723 的场景序列化格式改进 #

  • 场景的根现在是一个结构体,而不是列表
  • 组件现在是按类型名称作为键的映射,而不是列表
  • 类型信息现在在可能的情况下被省略,使场景更加紧凑

使用 Bevy 0.8 序列化的场景需要重新创建,但可以手动编辑场景以匹配新格式。

以下是在旧格式和新格式中示例场景

// Old (Bevy 0.8)
[
  (
    entity: 0,
    components: [
      {
        "type": "bevy_transform::components::transform::Transform",
        "struct": {
          "translation": {
            "type": "glam::vec3::Vec3",
            "value": (0.0, 0.0, 0.0),
          },
          "rotation": {
            "type": "glam::quat::Quat",
            "value": (0.0, 0.0, 0.0, 1.0),
          },
          "scale": {
            "type": "glam::vec3::Vec3",
            "value": (1.0, 1.0, 1.0),
          },
        },
      },
      {
        "type": "scene::ComponentB",
        "struct": {
          "value": {
            "type": "alloc::string::String",
            "value": "hello",
          },
        },
      },
      {
        "type": "scene::ComponentA",
        "struct": {
          "x": {
            "type": "f32",
            "value": 1.0,
          },
          "y": {
            "type": "f32",
            "value": 2.0,
          },
        },
      },
    ],
  ),
  (
    entity: 1,
    components: [
      {
        "type": "scene::ComponentA",
        "struct": {
          "x": {
            "type": "f32",
            "value": 3.0,
          },
          "y": {
            "type": "f32",
            "value": 4.0,
          },
        },
      },
    ],
  ),
]

// New (Bevy 0.9)
(
  entities: {
    0: (
      components: {
        "bevy_transform::components::transform::Transform": (
          translation: (
            x: 0.0,
            y: 0.0,
            z: 0.0
          ),
          rotation: (0.0, 0.0, 0.0, 1.0),
          scale: (
            x: 1.0,
            y: 1.0,
            z: 1.0
          ),
        ),
        "scene::ComponentB": (
          value: "hello",
        ),
        "scene::ComponentA": (
          x: 1.0,
          y: 2.0,
        ),
      },
    ),
    1: (
      components: {
        "scene::ComponentA": (
          x: 3.0,
          y: 4.0,
        ),
      },
    ),
  }
)

为输入类型派生 Reflect + FromReflect #

  • Input<T> 现在通过 #[reflect] 而不是 #[reflect_value] 实现 Reflect。这意味着它现在通过 Reflect 特性公开其私有字段,而不是被视为值类型。对于依赖 Input<T> 结构体被反射视为值类型的代码,仍然可以使用包装结构体包装 Input<T> 类型,并对其应用 #[reflect_value]
  • 提醒一下,通过反射公开的私有字段不受任何稳定性保证。

放宽对 Option<T> 的限制 #

如果使用 Bevy 的反射 API 使用 Option<T>T 现在需要实现 FromReflect,而不仅仅是 Clone。这可以通过简单地派生 FromReflect 来轻松实现


// OLD
#[derive(Reflect, Clone)]
struct Foo;

let reflected: Box<dyn Reflect> = Box::new(Some(Foo));

// NEW
#[derive(Reflect, FromReflect)]
struct Foo;

let reflected: Box<dyn Reflect> = Box::new(Some(Foo));

注意:您仍然可以派生 Clone,但它不是编译所必需的。

删除 ReflectMut,改为使用 Mut<dyn Reflect> #

  • 放宽 Mut<T> 中的 T: ?Sized 限制
  • 将所有 ReflectMut 实例替换为 Mut<dyn Reflect>

删除泛型类型上 ReflectSerialize + Deserialize 要求 #

.register_type 对于 Option<T>Vec<T>HashMap<K, V> 等泛型类型将不再插入 ReflectSerializeReflectDeserialize 类型数据。相反,您需要为具体的泛型类型分别注册它,如下所示

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

Val 的实用方法 #

现在无法再使用 ++=--= 运算符与 ValSize

改为使用新的 try_addtry_sub 方法,并分别对 Sizeheightwidth 字段进行操作。

允许将 glam 向量类型作为顶点属性传递 #

VertexAttributeValuesFrom<Vec<[u16; 4]>>From<Vec<[u8; 4]>> 实现已被移除。如果您将 Vec<[u16; 4]>Vec<[u8; 4]> 传递到 Mesh::insert_attribute,现在需要用正确的 VertexAttributeValues 枚举变体将其包装起来。