- 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
中。您可能需要将移动系统排序为在此系统之前发生,以避免在剔除行为中出现系统顺序歧义。RenderLabel
AppLabel
已重命名为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_path
path_mut
->reflect_path_mut
get_path
->path
get_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::Left
TextAlignment::TOP_CENTER
、TextAlignment::CENTER_LEFT
、TextAlignment::BOTTOM_CENTER
为TextAlignment::Center
TextAlignment::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()
}));