- 0.9 到 0.10
- 将引擎迁移到 Schedule v3(无阶段)
- 将窗口作为实体
- 使 SystemParam 派生宏更灵活
- 用于并行查询迭代的基本自适应批处理
- 枚举可见性组件
- bevy_reflect:预解析路径
- 移除 App::add_sub_app
- 将 HandleUntyped::id 设置为私有
- 将 CorePlugin 拆分为 TaskPoolPlugin、TypeRegistrationPlugin、FrameCountPlugin。
- 用于元数据存储的不可变稀疏集
- 拆分组件计时
- 记录和锁定 bevy_ecs::archetype 中的类型
- 锁定对实体的访问
- 在 EventReader::clear 中借用而不是使用
- Newtype ArchetypeRow 和 TableRow
- 完善无类型 API
- 使用 TableId 和 TableRow 扩展 EntityLocation
- 移除 ExclusiveSystemParam::apply
- 移除 SystemParamState 特征以及 ResState 等类型
- 在非原始线程中丢弃 NonSend 时出现恐慌。
- 记录 Ptr、PtrMut 和 OwningPtr 的对齐要求
- 添加 resource_id 并将 init_resource 和 init_non_send_resource 更改为返回 ComponentId
- 使用 Events<Entity> 替换 RemovedComponents<T> 支持
- 移除事件迭代器上的已损坏的 DoubleEndedIterator 实现
- 将 Tick::is_older_than 重命名为 Tick::is_newer_than
- 清理称为标签的系统集
- 简化 SystemParamFunction 特征的泛型
- 弃用 ChangeTrackers<T>,改为使用 Ref<T>
- EntityMut:将 remove_intersection 重命名为 remove,并将 remove 更改为接受参数
- bevy_ecs:没有 World 的 ReflectComponentFns
- 允许使用 EntityRef 遍历整个 World
- 移除 WorldChildBuilder 的 BuildWorldChildren 实现
- 重命名动态特征
- bevy_reflect:将 insert 和 remove 方法添加到 List
- bevy_reflect:将 List 和 Array 特征解耦
- bevy_reflect:从大多数 glam 类型中移除 ReflectSerialize 和 ReflectDeserialize 注册
- 在 ScalingMode::AutoMin 旁边添加 AutoMax
- 将 From<Icosphere> 更改为 TryFrom<Icosphere>
- 将 try_* 添加到 add_slot_edge、add_node_edge
- 着色器定义现在可以具有值
- 从 wgpu 获取像素大小
- 在渲染世界中运行清除跟踪器
- 将相机“优先级”重命名为“顺序”
- 减少 TrackedRenderPass 中的分支
- 使 PipelineCache 在内部可变。
- 将 Msaa 更改为枚举
- 支持在 RenderContext 中记录多个 CommandBuffer
- 改进正交相机的一致性和可用性
- 将 &mut PipelineCache 更改为 &PipelineCache
- 引入 detailed_trace 宏,在 TrackedRenderPass 中使用
- 将细分添加到 shape::Plane
- 更改标准材质默认值并更新文档
- 移除 #7784 之后的死代码
- 直接将关节提取到 SkinnedMeshJoints
- 将 glTF 颜色解释为线性而不是 sRGB
- 将发射颜色作为线性而不是 sRGB 发送到制服
- update_frame_count 系统应放在 CorePlugin 中
- 流水线渲染
- 移除 ImageMode
- 重命名 `ExtractedUiNode` 的 `background_color`
- 移除 GlobalTransform::translation_mut 方法
- 翻转 UI 图像
- 移除 TextError::ExceedMaxTextAtlases(usize) 变体
- 将默认 FocusPolicy 更改为 Pass
- 从 TextAlignment 中移除 VerticalAlign
- 移除 QueuedText
- 将 Size 的默认宽度和高度更改为 Val::Auto
- 修复使用错误默认值的 Size 辅助函数并改进 UI 示例
- CalculatedSize 的 size 字段不应该是 Size
- 将 winit 更新到 0.28
迁移指南:0.9 到 0.10
Bevy 严重依赖于 Rust 语言和编译器的改进。因此,最低支持的 Rust 版本 (MSRV) 是 Rust 的“最新稳定版本”。
将引擎迁移到 Schedule v3(无阶段) #
调用
.label(MyLabel)应替换为.in_set(MySet)SystemLabel派生应替换为SystemSet。您还需要添加Debug、PartialEq、Eq和Hash特征以满足新的特征边界。阶段已被移除。将这些替换为系统集,然后在需要的地方使用
apply_system_buffers专属系统添加命令刷新。CoreStage、StartupStage、RenderStage和AssetStage枚举已被替换为CoreSet、StartupSet、RenderSet和AssetSet。已保留相同的调度保证。with_run_criteria已重命名为run_if。为了清楚起见,运行标准已重命名为运行条件,现在应简单地返回bool而不是schedule::ShouldRun。循环运行标准和状态堆栈已被移除。如果您需要这种级别的对系统控制流的控制,请使用运行调度的专属系统。
App::add_state现在接受 0 个参数:根据Default实现设置起始状态。不要为在阶段中运行的系统创建
SystemSet容器,而是使用my_system.in_schedule(OnEnter(State::Variant))或其OnExit同级。对于应用程序级对何时运行哪些调度的控制流(例如用于回滚网络),请创建自己的调度并将其插入
CoreSchedule::Outer标签下方。固定时间步长现在在调度中进行评估,而不是通过运行标准进行控制。默认情况下,
run_fixed_timestep系统在CoreSet::First和CoreSet::PreUpdate之间运行此调度。由
AssetStage引入的命令刷新点已被移除。如果您依赖这些,请手动添加它们回来。带有
CalculateBounds标签的calculate_bounds系统现在位于CoreSet::Update中,而不是在应用命令之前位于CoreSet::PostUpdate中。您可能需要将移动系统排序为在此系统之前发生,以避免在剔除行为中出现系统顺序歧义。RenderLabelAppLabel已重命名为RenderApp,以提高清晰度在测试系统或以无头方式运行系统时,只需使用
Schedule::new()和World::run_schedule构造和运行调度,而不是构造阶段状态已大大简化:不再有“状态堆栈”。要将状态更改排队到下一个状态,请调用
NextState::set字符串不再可用作
SystemLabel或SystemSet。使用类型,或使用系统函数。
阶段 #
阶段有两个关键元素:它们一个接一个地运行,并在最后应用命令。
前者可以使用系统集替换(除非您需要分支或循环调度逻辑,在这种情况下您应该使用调度),而后者可以使用 apply_system_buffers 手动控制。
为了从 Bevy 的内置阶段迁移,我们提供了 CoreSet、StartupSet 和 RenderSet 系统集。命令刷新已添加到这些中,但如果您添加了自定义阶段,则可能需要添加自己的命令刷新,如果您依赖于这种行为。
之前
app
.add_system_to_stage(CoreStage::PostUpdate, my_system)
.add_startup_system_to_stage(StartupStage::PostStartup, my_startup_system);
之后
app
.add_system(my_system.in_base_set(CoreSet::PostUpdate))
.add_startup_system(my_startup_system.in_base_set(StartupSet::PostStartup));
如果您有自己的阶段
// Bevy 0.9
#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)]
pub struct AfterUpdate;
app.add_stage_after(CoreStage::Update, AfterUpdate, SystemStage::parallel());
// Bevy 0.10, no command flush
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
#[system_set(base)]
pub struct AfterUpdate;
app.configure_set(
AfterUpdate
.after(CoreSet::UpdateFlush)
.before(CoreSet::PostUpdate),
);
// Bevy 0.10, with a command flush
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
#[system_set(base)]
pub enum AfterUpdate {
Parallel,
CommandFlush
}
app.configure_sets(
(
CoreSet::UpdateFlush,
AfterUpdate::Parallel,
AfterUpdate::CommandFlush,
CoreSet::PostUpdate,
).chain()
).add_system(apply_system_buffers.in_base_set(AfterUpdate::CommandFlush));
标签类型 #
系统标签已重命名为系统集,并与阶段标签统一。StageLabel 特征应替换为系统集,使用 SystemSet 特征,如以下讨论。
之前
#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)]
enum MyStage {
BeforeRound,
AfterRound,
}
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemLabel)]
enum MySystem {
ComputeForces,
FindCollisions,
}
之后
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
enum MySet {
BeforeRound,
AfterRound,
}
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
enum MySystem {
ComputeForces,
FindCollisions,
}
系统集(Bevy 0.9) #
在 Bevy 0.9 中,您可以使用 SystemSet 类型和各种方法来同时配置多个系统。此外,这是与各种调度 API(如运行标准)交互的唯一方式。
之前
app.add_system_set(SystemSet::new().with_system(a).with_system(b).with_run_criteria(my_run_criteria));
之后
app.add_systems((a, b).run_if(my_run_condition));
歧义检测 #
ReportExecutionOrderAmbiguities 资源已被移除。相反,这是在每个调度基础上配置的。
app.edit_schedule(CoreSchedule::Main, |schedule| {
schedule.set_build_settings(ScheduleBuildSettings {
ambiguity_detection: LogLevel::Warn,
..default()
});
})
固定时间步长 #
FixedTimestep 运行标准已被移除,现在由调度或 on_timer / on_fixed_timer 运行条件处理。
之前
app.add_stage_after(
CoreStage::Update,
FixedUpdateStage,
SystemStage::parallel()
.with_run_criteria(
FixedTimestep::step(0.5)
)
.with_system(fixed_update),
);
之后
// This will affect the update frequency of fixed time for your entire app
app.insert_resource(FixedTime::new_from_secs(0.5))
// This schedule is automatically added with DefaultPlugins
.add_system(fixed_update.in_schedule(CoreSchedule::FixedUpdate));
应用程序现在可能只有一个统一的固定时间步长。CoreSchedule::FixedTimestep 用于在网络、物理和游戏机制期间实现确定性和稳定性。与计时器不同,如果自上次运行以来已超过一个时间段,它将反复运行。
它不打算用作循环计时器来定期执行工作或轮询。如果您依赖于具有不同时间段的多个 FixedTimestep 运行标准,您应该切换到使用计时器,通过 on_timer(MY_PERIOD) 或 on_fixed_timer(MY_PERIOD) 运行条件。
之前
app.add_system_set(
SystemSet::new()
.with_run_criteria(FixedTimestep::step(0.5))
.with_system(update_pathfinding),
)
.add_system_set(
SystemSet::new()
.with_run_criteria(FixedTimestep::step(0.1))
.with_system(apply_damage_over_time),
);
之后
app
.add_system(update_pathfinding.run_if(on_timer(Duration::from_secs_f32(0.5))))
.add_system(apply_damage_over_time.run_if(on_timer(Duration::from_secs_f32(0.1))));
状态 #
状态已大大简化,不再有状态堆栈。每个状态类型(通常是枚举)都需要 States 特征,通常通过派生宏实现。
例如
#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)]
enum AppState {
#[default]
Menu,
InGame,
}
App::add_state 不再接受参数:起始状态现在通过您的状态类型的 Default 实现控制。
要访问上面 States 类型的当前状态,请使用 Res<State<AppState>,并通过 .0 访问元组字段。要将状态更改排队,请使用 ResMut<NextState<AppState>> 并调用 .set(AppState::Menu).
状态更改现在通过 apply_state_transitions 专属系统应用,当您调用 App::add_state 时,会在 CoreSet::StateTransitions 中添加此系统的副本。您可以在需要的地方添加更多副本,特定于正在应用的状态。
OnEnter 和 OnExit 系统现在位于调度中,通过 apply_state_transitions 系统在 World 上运行。相比之下,OnUpdate 现在是一个系统集,嵌套在 CoreSet::Update 中。
之前
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
enum AppState {
Menu,
InGame,
}
app.add_state(AppState::Menu)
.add_system_set(SystemSet::on_enter(AppState::Menu).with_system(setup_menu))
.add_system_set(SystemSet::on_update(AppState::Menu).with_system(menu))
.add_system_set(SystemSet::on_exit(AppState::Menu).with_system(cleanup_menu))
之后
#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)]
enum AppState {
#[default]
Menu,
InGame,
}
app.add_state::<AppState>()
.add_system(setup_menu.in_schedule(OnEnter(AppState::Menu)))
.add_system(menu.in_set(OnUpdate(AppState::Menu)))
.add_system(cleanup_menu.in_schedule(OnExit(AppState::Menu)));
当您需要在 CoreSet::Update 之外运行特定于状态的系统时,您可以使用内置的 in_state 运行条件。
将窗口作为实体 #
将 WindowDescriptor 替换为 Window。
将 width 和 height 字段更改为 WindowResolution,方法是:
WindowResolution::new(width, height) // Explicitly
// or using From<_> for tuples for convenience
(1920., 1080.).into()
将任何 WindowCommand 代码替换为直接修改 Window 的字段,现在通过像这样生成/销毁具有 Window 组件的实体来创建/关闭窗口
let window = commands.spawn(Window { ... }).id(); // open window
commands.entity(window).despawn(); // close window
要获取窗口,您现在需要使用 Query 而不是 Res
// 0.9
fn count_pixels(windows: Res<Windows>) {
let Some(primary) = windows.get_primary() else {
return;
};
println!("{}", primary.width() * primary.height());
}
// 0.10
fn count_pixels(primary_query: Query<&Window, With<PrimaryWindow>>) {
let Ok(primary) = primary_query.get_single() else {
return;
};
println!("{}", primary.width() * primary.height());
}
使 SystemParam 派生宏更灵活 #
EventWriter 中已移除生命周期 's。任何显式指定此类型生命周期的代码都需要更新。
// 0.9
#[derive(SystemParam)]
struct MessageWriter<'w, 's> {
events: EventWriter<'w, 's, Message>,
}
// 0.10
#[derive(SystemParam)]
struct MessageWriter<'w> {
events: EventWriter<'w, Message>,
}
用于并行查询迭代的基本自适应批处理 #
Query(State)::par_for_each(_mut) 的 batch_size 参数已移除。这些调用会自动为您计算批次大小。从所有调用这些函数的调用中删除这些参数。
// 0.9
fn parallel_system(query: Query<&MyComponent>) {
query.par_for_each(32, |comp| {
...
});
}
// 0.10
fn parallel_system(query: Query<&MyComponent>) {
query.par_iter().for_each(|comp| {
...
});
}
枚举 Visibility 组件 #
visibility.is_visible字段的评估现在应该检查visibility == Visibility::Inherited。- 设置
visibility.is_visible字段现在应直接设置值:*visibility = Visibility::Inherited。 Visibility::VISIBLE或Visibility::INVISIBLE的使用现在应该分别使用Visibility::Inherited或Visibility::Hidden。ComputedVisibility::INVISIBLE和SpatialBundle::VISIBLE_IDENTITY已分别重命名为ComputedVisibility::HIDDEN和SpatialBundle::INHERITED_IDENTITY。
bevy_reflect: 预解析路径 #
GetPath 方法已根据以下内容重命名
path->reflect_pathpath_mut->reflect_path_mutget_path->pathget_path_mut->path_mut
移除 App::add_sub_app #
App::add_sub_app 已移除,取而代之的是 App::insert_sub_app。使用 SubApp::new 并通过 App::insert_sub_app 插入它
// 0.9
let mut sub_app = App::new()
// Build subapp here
app.add_sub_app(MySubAppLabel, sub_app, extract_fn);
// 0.10
let mut sub_app = App::new()
// Build subapp here
app.insert_sub_app(MySubAppLabel, SubApp::new(sub_app, extract_fn));
使 HandleUntyped::id 私有 #
不要直接访问 HandleUntyped 的 ID,如 handle.id,而应使用新的 getter handle.id()。
将 CorePlugin 分解为 TaskPoolPlugin、TypeRegistrationPlugin、FrameCountPlugin。 #
CorePlugin 已分解为单独的插件。如果不使用 DefaultPlugins 或 MinimalPlugins PluginGroup,CorePlugin 的替代方案现在是在应用程序中添加 TaskPoolPlugin、TypeRegistrationPlugin 和 FrameCountPlugin。
用于元数据存储的不可变稀疏集 #
Table::component_capacity() 已移除,因为表不支持在构建后添加/移除列。
拆分组件 Tick #
与更改检测 Tick 交互的各种底层 API 不再返回 &UnsafeCell<ComponentTicks>,而是返回 TickCells,其中包含两个单独的 &UnsafeCell<Tick>。
// 0.9
column.get_ticks(row).deref().changed
// 0.10
column.get_ticks(row).changed.deref()
记录和锁定 bevy_ecs::archetype 中的类型 #
ArchetypeId、ArchetypeGeneration 和 ArchetypeComponentId 现在都是不透明的 ID,无法转换为数值。如果这无法满足您的用例,请提交问题,或查看 bevy_ecs 过度公开 以获取更多信息。
Archetype 和 Archetypes 现在无法在 bevy_ecs 之外构造。使用 World::archetypes 获取对这些类型中任一类型的只读引用。
锁定对实体的访问 #
Entities 的 Default 实现已移除。您可以通过 World::entities 和 World::entities_mut 获取对 World 的 Entities 的引用。
Entities::alloc_at_without_replacement 和 AllocAtWithoutReplacement 已设置为私有,因为在 bevy_ecs 之外正确使用它比较困难。如果您仍然需要使用此 API,请提交问题或查看 bevy_ecs 过度公开 以获取更多信息。
在 EventReader::clear 中使用借用而不是消耗 #
EventReader::clear 现在接受可变引用,而不是消耗事件读取器。这意味着 clear 现在需要对读取器变量进行显式可变访问,而之前在某些情况下可以省略。
// Old (0.9)
fn clear_events(reader: EventReader<SomeEvent>) {
reader.clear();
}
// New (0.10)
fn clear_events(mut reader: EventReader<SomeEvent>) {
reader.clear();
}
新类型 ArchetypeRow 和 TableRow #
Archetype 索引和 Table 行已作为 ArchetypeRow 和 TableRow 进行新类型化。
完善未类型化的 API #
MutUntyped::into_inner 现在会将事物标记为已更改。
使用 TableId 和 TableRow 扩展 EntityLocation #
World 现在只能容纳最多 232 - 1 个原型和表。如果您的用例需要更多,请提交问题并解释您的用例。
移除 ExclusiveSystemParam::apply #
已移除特征方法 ExclusiveSystemParamState::apply。如果您有一个具有必须应用的缓冲区的独占系统,则应在独占系统的主体中应用它们。
移除 SystemParamState 特征,并移除类似 ResState 的类型 #
已移除特征 SystemParamState 和 SystemParamFetch,并且它们的函数已转移到 SystemParam。
特征 ReadOnlySystemParamFetch 已替换为 ReadOnlySystemParam。
// 0.9
impl SystemParam for MyParam<'_, '_> {
type State = MyParamState;
}
unsafe impl SystemParamState for MyParamState {
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... }
}
unsafe impl<'w, 's> SystemParamFetch<'w, 's> for MyParamState {
type Item = MyParam<'w, 's>;
fn get_param(&mut self, ...) -> Self::Item;
}
unsafe impl ReadOnlySystemParamFetch for MyParamState { }
// 0.10
unsafe impl SystemParam for MyParam<'_, '_> {
type State = MyParamState;
type Item<'w, 's> = MyParam<'w, 's>;
fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { ... }
fn get_param<'w, 's>(state: &mut Self::State, ...) -> Self::Item<'w, 's>;
}
unsafe impl ReadOnlySystemParam for MyParam<'_, '_> { }
在非源线程中丢弃 NonSend 时恐慌。 #
普通资源和 NonSend 资源不再共享相同的支持存储。如果 R: Resource,则 NonSend<R> 和 Res<R> 将互相返回不同的实例。如果您同时使用 Res<T> 和 NonSend<T>(或它们的可变变体)来获取相同的资源,强烈建议使用 Res<T>。
记录 Ptr、PtrMut 和 OwningPtr 的对齐要求 #
bevy_ptr 类型上的 new byte_add 和 byte_offset 方法的安全不变式已更改。所有调用者都应重新审核以确保其健全性。
添加 resource_id,并将 init_resource 和 init_non_send_resource 更改为返回 ComponentId #
- 添加
Components::resource_id。 - 将
World::init_resource更改为返回生成的ComponentId。 - 将
World::init_non_send_resource更改为返回生成的ComponentId。
用 Events<Entity> 替换 RemovedComponents<T> 支持 #
- 为
removed: RemovedComponents<T>添加mut,因为我们现在正在内部修改事件读取器。 - 遍历已移除的组件现在需要
&mut removed_components或removed_components.iter(),而不是&removed_components。
移除事件迭代器上的损坏 DoubleEndedIterator 实现 #
ManualEventIterator 和 ManualEventIteratorWithId 不再是 DoubleEndedIterator,因为实现不正确,并且使用它的任何代码都可能已损坏。
将 Tick::is_older_than 重命名为 Tick::is_newer_than #
将 Tick::is_older_than 的用法替换为 Tick::is_newer_than。
清理名为标签的系统集 #
PrepareAssetLabel 现在称为 PrepareAssetSet
简化 SystemParamFunction 特征的泛型 #
对于 SystemParamFunction 特征,类型参数 In、Out 和 Param 已转换为关联类型。
// 0.9
fn my_generic_system<T, In, Out, Param, Marker>(system_function: T)
where
T: SystemParamFunction<In, Out, Param, Marker>,
Param: SystemParam,
{ ... }
// 0.10
fn my_generic_system<T, Marker>(system_function: T)
where
T: SystemParamFunction<Marker>,
{ ... }
对于 ExclusiveSystemParamFunction 特征,类型参数 Param 已转换为关联类型。此外,还添加了 In 和 Out 关联类型,因为独占系统现在支持系统管道。
// 0.9
fn my_exclusive_system<T, Param, Marker>(system_function: T)
where
T: ExclusiveSystemParamFunction<Param, Marker>,
T: Param: ExclusiveSystemParam,
{ ... }
// 0.10
fn my_exclusive_system<T, Marker>(system_function: T)
where
T: ExclusiveSystemParamFunction<Marker>,
{ ... }
弃用 ChangeTrackers<T>,改用 Ref<T> #
ChangeTrackers<T> 已弃用,将在下一个版本中移除。任何使用都应替换为 Ref<T>。
// 0.9
fn my_system(q: Query<(&MyComponent, ChangeTrackers<MyComponent>)>) {
for (value, trackers) in &q {
if trackers.is_changed() {
// Do something with `value`.
}
}
}
// 0.10
fn my_system(q: Query<Ref<MyComponent>>) {
for value in &q {
if value.is_changed() {
// Do something with `value`.
}
}
}
EntityMut:将 remove_intersection 重命名为 remove,将 remove 重命名为 take #
// 0.9
fn clear_children(parent: Entity, world: &mut World) {
if let Some(children) = world.entity_mut(parent).remove::<Children>() {
for &child in &children.0 {
world.entity_mut(child).remove_intersection::<Parent>();
}
}
}
// 0.10
fn clear_children(parent: Entity, world: &mut World) {
if let Some(children) = world.entity_mut(parent).take::<Children>() {
for &child in &children.0 {
world.entity_mut(child).remove::<Parent>();
}
}
}
bevy_ecs: 没有 World 的 ReflectComponentFns #
在调用已更改的 ReflectComponent 方法之前调用 World::entity,用户很可能已经拥有 EntityRef 或 EntityMut,而这些方法正在被冗余地查询。
允许使用 EntityRef 遍历整个 World #
World::iter_entities 现在返回 EntityRef 的迭代器,而不是 Entity 的迭代器。要获取实际的 ID,请使用返回的 EntityRef 的 EntityRef::id。
移除 WorldChildBuilder 的 BuildWorldChildren 实现 #
已从 WorldChildBuilder 中移除层次结构编辑方法,如 with_children 和 push_children。您可以通过 EntityMut 而不是通过 WorldChildBuilder 编辑层次结构。
重命名动态特征 #
dynamic 特征已重命名为 dynamic_linking
bevy_reflect: 在 List 中添加 insert 和 remove 方法 #
List 的手动实现者需要实现新的方法 insert 和 remove,并考虑是否使用 push 和 pop 的新的默认实现。
bevy_reflect: 解耦 List 和 Array 特征 #
List 特征不再依赖于 Array。List 的实现者可以移除 Array 实现,并将它的方法移动到 List 实现中(只需要进行几处调整)。
// 0.9
impl Array for Foo {
fn get(&self, index: usize) -> Option<&dyn Reflect> {/* ... */}
fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {/* ... */}
fn len(&self) -> usize {/* ... */}
fn is_empty(&self) -> bool {/* ... */}
fn iter(&self) -> ArrayIter {/* ... */}
fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>> {/* ... */}
fn clone_dynamic(&self) -> DynamicArray {/* ... */}
}
impl List for Foo {
fn insert(&mut self, index: usize, element: Box<dyn Reflect>) {/* ... */}
fn remove(&mut self, index: usize) -> Box<dyn Reflect> {/* ... */}
fn push(&mut self, value: Box<dyn Reflect>) {/* ... */}
fn pop(&mut self) -> Option<Box<dyn Reflect>> {/* ... */}
fn clone_dynamic(&self) -> DynamicList {/* ... */}
}
// 0.10
impl List for Foo {
fn get(&self, index: usize) -> Option<&dyn Reflect> {/* ... */}
fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {/* ... */}
fn insert(&mut self, index: usize, element: Box<dyn Reflect>) {/* ... */}
fn remove(&mut self, index: usize) -> Box<dyn Reflect> {/* ... */}
fn push(&mut self, value: Box<dyn Reflect>) {/* ... */}
fn pop(&mut self) -> Option<Box<dyn Reflect>> {/* ... */}
fn len(&self) -> usize {/* ... */}
fn is_empty(&self) -> bool {/* ... */}
fn iter(&self) -> ListIter {/* ... */}
fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>> {/* ... */}
fn clone_dynamic(&self) -> DynamicList {/* ... */}
}
需要进行的其他一些小调整包括
- 为
List::iter使用ListIter,而不是ArrayIter(来自Array::iter的返回类型) - 在
List的实现者的Reflect::reflect_hash中将array_hash替换为list_hash
bevy_reflect:从大多数 glam 类型中删除 ReflectSerialize 和 ReflectDeserialize 注册 #
此 PR 从大多数 glam 类型中删除了 ReflectSerialize 和 ReflectDeserialize 注册。这意味着任何依赖于这些 glam 类型存在的类型数据的代码都需要停止这样做。
这也意味着一些序列化后的 glam 类型需要更新。例如,以下是 Affine3A
// 0.9
(
"glam::f32::affine3a::Affine3A": (1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0),
// 0.10
"glam::f32::affine3a::Affine3A": (
matrix3: (
x_axis: (
x: 1.0,
y: 0.0,
z: 0.0,
),
y_axis: (
x: 0.0,
y: 1.0,
z: 0.0,
),
z_axis: (
x: 0.0,
y: 0.0,
z: 1.0,
),
),
translation: (
x: 0.0,
y: 0.0,
z: 0.0,
),
)
)
在 ScalingMode::AutoMin 旁边添加 AutoMax #
将 ScalingMode::Auto 重命名为 ScalingMode::AutoMin。
将 From<Icosphere> 更改为 TryFrom<Icosphere> #
// 0.9
shape::Icosphere {
radius: 0.5,
subdivisions: 5,
}
.into()
// 0.10
shape::Icosphere {
radius: 0.5,
subdivisions: 5,
}
.try_into()
.unwrap()
在 add_slot_edge、add_node_edge 中添加 try_* #
从 add_node_edge 和 add_slot_edge 中删除 .unwrap()。对于处理了错误的用例,请改用 try_add_node_edge 和 try_add_slot_edge。
从 input_node 中删除 .unwrap()。对于处理了选项的用例,请改用 get_input_node。
着色器定义现在可以有值 #
- 用
shader_defs.push("NAME".into());替换shader_defs.push(String::from("NAME")); - 如果您使用的是着色器定义
NO_STORAGE_BUFFERS_SUPPORT,请检查 Bevy 默认着色器 中AVAILABLE_STORAGE_BUFFER_BINDINGS的使用方式。
从 wgpu 获取像素大小 #
PixelInfo 已被删除。PixelInfo::components 等同于 texture_format.describe().components。PixelInfo::type_size 可以从 texture_format.describe().block_size/ texture_format.describe().components 获取。但请注意,这可能会对某些纹理类型(如 Rg11b10Float)产生不正确的结果。
在渲染世界中运行清除跟踪器 #
App 中对 clear_trackers 的调用已从调度移至 App::update(用于主世界),并且已在同一函数中为 sub_apps 添加了对 clear_trackers 的调用。这是因为需要更强的保证。如果在世界中没有调用 clear_trackers,则会导致 RemovedComponents 中发生内存泄漏。如果您以前使用 clear_trackers 对系统进行排序,那么现在无法这样做。
将相机“优先级”重命名为“顺序” #
在 Camera 的使用中将 priority 重命名为 order。
减少 TrackedRenderPass 中的分支 #
TrackedRenderPass 现在需要一个 RenderDevice 来构建。为了简化操作,请改用 RenderContext.begin_tracked_render_pass。
// 0.9
TrackedRenderPass::new(render_context.command_encoder.begin_render_pass(
&RenderPassDescriptor {
...
},
));
// 0.10
render_context.begin_tracked_render_pass(RenderPassDescriptor {
...
});
使 PipelineCache 在内部可变。 #
大多数 resource_mut::<PipelineCache> 和 ResMut<PipelineCache> 的使用可以更改为 resource::<PipelineCache> 和 Res<PipelineCache>,只要它们不使用任何需要可变性的方法——唯一需要它的公共方法是 process_queue。
将 Msaa 更改为枚举 #
// 0.9
let multi = Msaa { samples: 4 }
// 0.10
let multi = Msaa::Sample4
// 0.9
multi.samples
// 0.10
multi.samples()
支持在 RenderContext 中录制多个 CommandBuffer #
RenderContext 的字段现在是私有的。请改用 RenderContext 上的访问器,并使用 RenderContext::new 构建它。
改进 OrthographicCamera 的一致性和可用性 #
将
window_origin更改为viewport_origin;用Vec2::new(0.5, 0.5)替换WindowOrigin::Center,用Vec2::new(0.0, 0.0)替换WindowOrigin::BottomLeft对于阴影投影等,用
area: Rect::new(left, bottom, right, top)替换left、right、bottom和top对于相机投影,从
OrthographicProjection实例化中删除 l/r/b/t 值,因为它们在任何ScalingMode中都无效将
ScalingMode::None更改为ScalingMode::Fixed- 用以下内容替换 l/r/b/t 的手动更改:
ScalingMode::Fixed中的参数来指定大小viewport_origin来指定偏移量
- 用以下内容替换 l/r/b/t 的手动更改:
将
ScalingMode::WindowSize更改为ScalingMode::WindowSize(1.0)
将 &mut PipelineCache 更改为 &PipelineCache #
SpecializedComputePipelines::specialize 现在接受一个 &PipelineCache 而不是 &mut PipelineCache
引入 detailed_trace 宏,在 TrackedRenderPass 中使用 #
一些详细的 bevy 跟踪事件现在需要使用 cargo 功能 detailed_trace(除了启用 TRACE 级别的日志记录)才能查看。如果您希望查看这些日志,请使用 bevy 功能 detailed_trace 编译您的代码。目前,唯一受影响的日志是与 TrackedRenderPass 函数相关的渲染器日志。
在 shape::Plane 中添加细分 #
shape::Plane 现在接受一个额外的 subdivisions 参数,因此用户应该提供它,或者使用新的 shape::Plane::from_size()。
更改标准材质默认值并更新文档 #
StandardMaterial 的默认值现在已更改为具有中等粗糙度的全电介质材质。如果您想使用旧的默认值,可以设置 perceptual_roughness = 0.089 和 metallic = 0.01(不过 metallic 通常应仅设置为 0.0 或 1.0)。
在 #7784 之后删除无用代码 #
删除了 SetShadowViewBindGroup、queue_shadow_view_bind_group() 和 LightMeta::shadow_view_bind_group,改用预备传递视图绑定组。
直接将关节提取到 SkinnedMeshJoints 中 #
ExtractedJoints 已被删除。请改用 SkinnedMeshJoints 读取绑定骨骼。
将 glTF 颜色解释为线性而不是 sRGB #
不需要任何 API 更改,但您的 gltf 网格可能看起来不同。
将发射颜色作为线性而不是 sRGB 发送到统一变量 #
- 如果您以前使用
Color::rgb()手动指定了发射值,并且想要保留旧的视觉效果,那么现在必须改用Color::rgb_linear(); - 如果您以前使用
Color::rgb_linear()手动指定了发射值,并且想要保留旧的视觉效果,则需要对您的通道手动应用一次伽马计算才能获得实际的线性 RGB 值。- 对于大于
0.0031308的通道值,请使用(1.055 * value.powf(1.0 / 2.4)) - 0.055; - 对于小于或等于
0.0031308的通道值,请使用value * 12.92;
- 对于大于
- 否则,结果现在应该与其他工具/引擎更加一致。
update_frame_count 系统应放置在 CorePlugin 中 #
FrameCount 资源以前仅在使用 bevy_render 功能时更新。如果您没有使用此功能,但仍然想要 FrameCount,它现在将被正确更新。
流水线渲染 #
App runner 和 SubApp extract 函数现在需要是 Send
这样做是为了启用流水线渲染。如果这破坏了您的用例,请报告,因为这些新边界可能能够放松。
删除 ImageMode #
ImageMode 从未生效,如果您正在使用它,请创建一个问题。
将 'ExtractedUiNode的background_color重命名为color` #
ExtractedUiNode 的 background_color 字段现在名为 color。
删除 GlobalTransform::translation_mut 方法 #
GlobalTransform::translation_mut 已被删除,没有替代方案,如果您依赖于此,请更新 Transform。如果给定的实体有子实体或父实体,您可能需要删除它的父实体以使它的变换独立(在这种情况下,新的 Commands::set_parent_in_place 和 Commands::remove_parent_in_place 可能有用)。
Bevy 可能会在将来添加一种基于实体的变换传播切换方法。
翻转 UI 图像 #
UiImage现在是一个结构体,因此请使用UiImage::new(handler)而不是UiImage(handler)UiImage不再实现Deref和DerefMut,因此请改用&image.texture或&mut image.texture
删除 TextError::ExceedMaxTextAtlases(usize) 变体 #
TextError::ExceedMaxTextAtlases(usize) 从未抛出,因此如果您匹配此变体,可以简单地删除它。
将默认 FocusPolicy 更改为 Pass #
FocusPolicy 的默认值已从 FocusPolicy::Block 更改为 FocusPolicy::Pass
从 TextAlignment 中删除 VerticalAlign #
Text 的 alignment 字段现在只影响文本的内部对齐方式。
将 TextAlignment 更改为 TextAlignment,它现在是一个枚举。替换
TextAlignment::TOP_LEFT、TextAlignment::CENTER_LEFT、TextAlignment::BOTTOM_LEFT为TextAlignment::LeftTextAlignment::TOP_CENTER、TextAlignment::CENTER_LEFT、TextAlignment::BOTTOM_CENTER为TextAlignment::CenterTextAlignment::TOP_RIGHT、TextAlignment::CENTER_RIGHT、TextAlignment::BOTTOM_RIGHT为TextAlignment::Right
Text2dBundle 的更改
Text2dBundle 有一个新的字段 text_anchor,它接受一个 Anchor 组件,该组件控制它相对于其变换的位置。
Text2dSize 已被删除。请改用 TextLayoutInfo。
删除 QueuedText #
QueuedText 从未面向用户。如果您依赖于它,请创建一个问题。
更改 Size 的默认 width 和 height 为 Val::Auto #
Size 的默认 width 和 height 值已从 Val::Undefined 更改为 Val::Auto。这不太可能导致现有代码出现问题。
修复使用错误默认值的 Size 辅助函数,并改进 UI 示例 #
Size::width 构造函数现在将 height 设置为 Val::Auto,而不是 Val::Undefined。Size::height 构造函数现在将 width 设置为 Val::Auto,而不是 Val::Undefined。
CalculatedSize 的 size 字段不应为 Size #
CalculatedSize 的 size 字段已更改为 Vec2。
将 winit 更新到 0.28 #
// 0.9
app.new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
always_on_top: true,
..default()
}),
..default()
}));
// 0.10
app.new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
window_level: bevy::window::WindowLevel::AlwaysOnTop,
..default()
}),
..default()
}));