Bevy 0.10
发布日期:2023 年 3 月 6 日,作者:Bevy 贡献者
感谢 173 位贡献者、689 个拉取请求、社区审阅者以及我们慷慨的赞助商,我们很高兴宣布 Bevy 0.10 版本已发布在 crates.io 上!
对于那些不知道的人,Bevy 是一款使用 Rust 构建的简单而清爽的数据驱动游戏引擎。您可以查看我们的 快速入门指南 来立即体验它。它是免费且开源的,永远免费!您可以在 GitHub 上获取完整的 源代码。查看 Bevy 资源,了解社区开发的插件、游戏和学习资源的集合。
要将现有 Bevy 应用程序或插件更新到 Bevy 0.10,请查看我们的 0.9 到 0.10 迁移指南。
自从我们几个月前发布最后一个版本以来,我们添加了大量新功能、错误修复和生活质量改进,但以下是一些亮点
- ECS Schedule v3:Bevy 现在拥有更简单、更灵活的调度机制。系统现在存储在一个统一的调度中,命令可以通过
apply_system_buffers
明确应用,并且进行了许多生活质量改进和错误修复。 - 级联阴影贴图:更优质的阴影贴图,可以覆盖更大的距离,贴图质量会随着相机而变化。
- 环境贴图照明:基于 360 度环境图像的照明,可以廉价且大幅度地提高场景的视觉质量。
- 深度和法线预渲染:在主渲染通道之前渲染场景的深度和法线纹理,可以实现新的效果(在某些情况下)提高性能。阴影贴图使用预渲染着色器,这使得透明纹理可以投射阴影。
- 平滑骨骼动画过渡:平滑地过渡在同一时间播放的两个骨骼动画之间的动画!
- 改进的 Android 支持:Bevy 现在可以在更多 Android 设备上开箱即用(有一些注意事项)。
- 改进的 Bloom 效果:Bloom 效果现在看起来更好,更容易控制,视觉伪影也更少。
- 距离和大气雾:使用 3D 距离和大气雾效果为场景添加深度和氛围!
- StandardMaterial 混合模式:使用更多 PBR 材质混合模式实现各种有趣的效果。
- 更多色调映射选择:为您的 HDR 场景选择 7 种流行的色调映射算法之一,以实现您想要的视觉风格。
- 颜色分级:控制每个相机的曝光度、伽马值、“色调映射前饱和度”和“色调映射后饱和度”。
- 并行流水线渲染:应用程序逻辑和渲染逻辑现在自动并行运行,从而显着提高性能。
- 将窗口作为实体:窗口现在以实体而不是资源的形式表示,这改善了用户体验并解锁了新的场景。
- 渲染器优化:我们在本轮开发中投入了大量精力来优化渲染器。Bevy 的渲染器比以往任何时候都快!
- ECS 优化:同样,我们也对许多常见的 ECS 操作进行了加速。Bevy 应用程序获得了不错的速度提升!
ECS Schedule v3 #
感谢我们 ECS 团队的出色工作,备受期待的 "无阶段"调度 RFC 已实施!
Schedule v3 是大量设计和实施工作的结晶。调度 API 是 Bevy 开发体验的核心和决定性部分,因此我们在对 API 的下一个演变进行设计时,必须非常谨慎和细致。除了 RFC PR 之外,由 @maniwani
完成的初始实现 PR 和 由 @alice-i-cecile
完成的 Bevy 引擎内部移植 PR 是非常好的起点,如果您想了解我们的流程和基本原理。众所周知,计划和实施是两码事。我们的最终实现与最初的 RFC 有些不同(以好的方式)。
发生了很多变化,但我们付出了很多努力来确保 迁移路径 对于现有应用程序来说比较简单。不要担心!
让我们来看看 0.10 中发布的内容!
一个统一的调度 #
您是否曾经想指定 system_a
在 system_b
之前运行,却遇到令人困惑的警告,指出 system_b
未找到,因为它位于不同的阶段?
不用再这样了!现在,单个 Schedule
中的所有系统都存储在一个单一数据结构中,并全局了解正在发生的事情。
这简化了我们的内部逻辑,使您的代码在重构时更加健壮,并允许插件作者指定高级不变性(例如,“移动必须在碰撞检测之前发生”),而不会将自己锁定到确切的调度位置。
这张使用 @jakobhellermann 的 bevy_mod_debugdump
箱子 制作的图表展示了 Bevy 默认调度的简化版本。
添加系统 #
系统
(它只是 普通的 Rust 函数!)是您在 Bevy ECS 中定义游戏逻辑的方式。使用 Schedule v3,您可以像以前版本一样将系统添加到您的 App
中
app.add_system(gravity)
但是 Schedule v3 还有一些新招!您现在可以一次添加多个系统
app.add_systems((apply_acceleration, apply_velocity))
默认情况下,Bevy 会并行运行系统。在 Bevy 的早期版本中,您是这样排序系统的
app
.add_system(walk.before(jump))
.add_system(jump)
.add_system(collide.after(jump))
您仍然可以这样做!但是您现在可以使用 add_systems
将其压缩
// much cleaner!
app.add_systems((
walk.before(jump),
jump,
collide.after(jump),
))
before()
和 after()
绝对是很有用的工具!但是,由于有了新的 chain()
函数,现在更容易按特定顺序运行系统
// This is equivalent to the previous example
app.add_systems((walk, jump, collide).chain())
chain()
将按定义顺序运行系统。链式调用还可以与每个系统的配置配对
app.add_systems((walk.after(input), jump, collide).chain())
可配置的系统集 #
在 Schedule v3 中,“系统集”的概念已重新定义,以支持更自然、更灵活地控制系统运行和调度的机制。旧的“系统标签”概念已与“集”概念合并,从而产生了一种简单而强大的抽象。
SystemSets
是系统的命名集合,它们在所有成员之间共享系统配置。相对于 SystemSet
对系统进行排序会将该排序应用于所有该集中的系统,以及每个系统的任何配置。
让我们直接看看它是什么样的。您是这样定义 SystemSets
的
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)]
enum PhysicsSet {
Movement,
CollisionDetection,
}
您可以通过调用 in_set
方法将系统添加到集合中
app.add_system(gravity.in_set(PhysicsSet::Movement))
您可以将其与上面提到的新系统功能结合使用
app.add_systems(
(apply_acceleration, apply_velocity)
.chain()
.in_set(PhysicsSet::Movement)
)
系统可以属于任意数量的集合
app.add_system(
move_player
.in_set(MoveSet::Player)
.in_set(PhysicsSet::Movement)
)
配置是按如下方式添加到集合中的
app.configure_set(
// Run systems in the Movement set before systems in the CollisionDetection set
PhysicsSet::Movement.before(PhysicsSet::CollisionDetection)
)
集合可以嵌套在其他集合中,这将导致它们继承其父集合的配置
app.configure_set(MoveSet::Enemy.in_set(PhysicsSet::Movement))
集合可以多次配置
// In PlayerPlugin:
app.configure_set(MoveSet::Player.before(MoveSet::Enemy))
// In PlayerTeleportPlugin
app.configure_set(MoveSet::Player.after(PortalSet::Teleport))
至关重要的是,系统配置是严格累加的:您无法移除在其他地方添加的规则。这既是“反意大利面式”也是“插件隐私”方面的考虑。当该规则与 Rust 强大的类型隐私规则相结合时,插件作者可以仔细决定需要维护哪些确切的不变性,以及在不破坏使用者的前提下重新组织代码和系统。
配置规则必须彼此兼容:任何悖论(例如集合内的系统集、必须在集合之前和之后运行的系统、顺序循环等)都会导致运行时恐慌并显示有帮助的错误消息。
直接调度独占系统 #
“独占系统”是系统
,它们可以直接访问整个 ECS 世界
。因此,它们不能与其他系统
并行运行。
自从 Bevy 诞生以来,Bevy 开发人员一直希望相对于普通系统来调度独占系统(并刷新命令)。
现在您可以做到!独占系统现在可以像任何其他系统一样进行调度和排序。
app
.add_system(ordinary_system)
// This works!
.add_system(exclusive_system.after(ordinary_system))
这特别强大,因为命令刷新(应用在系统中添加的排队命令
,用于执行诸如生成和销毁实体等操作)现在只是在 apply_system_buffers
独占系统中执行。
app.add_systems(
(
// This system produces some commands
system_a,
// This will apply the queued commands from system_a
apply_system_buffers,
// This system will have access to the results of
// system_a's commands
system_b,
// This chain ensures the systems above run in the order
// they are defined
).chain()
)
但是要小心这种模式:很容易很快地出现许多排序不佳的独占系统,从而导致瓶颈和混乱。
你会用如此强大的力量做什么?我们很想了解!
使用调度管理复杂控制流 #
但是,如果您想对您的调度
做一些奇怪的事情呢?一些非线性的、分支的或循环的。你应该用什么?
事实证明,Bevy 已经拥有了这样一个很棒的工具:在独占系统内运行的调度。这个想法很简单
- 构建一个调度,存储您想要运行的任何复杂逻辑。
- 将该调度存储在资源中。
- 在独占系统中,执行您想要的任何任意 Rust 逻辑来决定您的调度是否以及如何运行。
- 暂时从
世界
中取出调度,在世界其他部分上运行它,以同时改变调度和世界,然后将它放回。
随着新的调度
资源和 world.run_schedule()
API 的加入,它比以往任何时候都更加✨ 人性化 ✨。
// A Schedule!
let mut my_schedule = Schedule::new();
schedule.add_system(my_system);
// A label for our new Schedule!
#[derive(ScheduleLabel, Debug, Hash, PartialEq, Eq, Clone)]
struct MySchedule;
// An exclusive system to run this schedule
fn run_my_schedule(world: &mut World) {
while very_complex_logic() {
world.run_schedule(MySchedule);
}
}
// Behold the ergonomics!
app
.add_schedule(MySchedule, my_schedule)
.add_system(run_my_schedule);
Bevy 在Bevy 0.10中使用这种模式来处理五种截然不同的东西
- 启动系统:这些现在位于自己的调度中,该调度在应用程序启动时运行一次。
- 固定时间步长系统:另一个调度?!运行此调度的独占系统会累积时间,运行一个 while 循环,重复运行
CoreSchedule::FixedUpdate
,直到所有累积的时间都已使用完。 - 进入和退出状态:大量的调度。每个运行逻辑以进入和退出状态变体的系统集合都存储在它自己的调度中,该调度基于
apply_state_transitions::<S>
独占系统中状态的变化而调用。 - 渲染:所有渲染逻辑都存储在它自己的调度中,以允许它相对于游戏逻辑异步运行。
- 控制最外层循环:为了处理“启动调度优先,然后是主调度”逻辑,我们将它全部包装在一个最小开销的
CoreSchedule::Outer
中,然后将我们的调度作为唯一的独占系统运行。
从CoreSchedule
开始关注面包屑以获取更多信息。
运行条件 #
系统
可以具有任意数量的运行条件,它们“仅仅”是返回 bool
的系统。如果系统所有运行条件返回的 bool
都是 true
,则系统将运行。否则系统将在调度的当前运行中被跳过。
// Let's make our own run condition
fn game_win_condition(query: Query<&Player>, score: Res<Score>) -> bool {
let player = query.single();
player.is_alive() && score.0 > 9000
}
app.add_system(win_game.run_if(game_win_condition));
运行条件也有一些“组合器”操作,这要感谢 @JoJoJet 和 @Shatur
它们可以使用 not()
来否定。
app.add_system(continue_game.run_if(not(game_win_condition)))
它们也可以与 and_then
和 or_else
组合。
app.add_system(move_player.run_if(is_alive.or_else(is_zombie)))
Bevy 0.10 附带了一组很棒的内置通用运行条件。您可以轻松地运行系统,前提是存在要处理的事件、已过期的计时器、已更改的资源、输入状态更改、状态更改等等(感谢 @maniwani
、@inodentry
、@jakobhellermann
和 @jabuwu
)。
运行条件也可以用作轻量级优化工具。运行条件在主线程上进行评估,每个运行条件在调度的每次更新时,在第一个依赖它的系统集中进行评估。被运行条件禁用的系统不会生成任务,这在许多系统中可能会累积起来。像往常一样:基准测试!
运行条件已取代 Bevy 以前版本中的“运行条件”。我们终于可以摆脱令人讨厌的“循环运行条件”了!ShouldRun::YesAndCheckAgain
对于引擎开发人员或用户来说都不是很直观。当您的类似布尔的枚举具有四个可能值时,这始终是一个不好的迹象。如果您渴望更复杂的控制流:在上面部分中使用“独占系统中的调度”模式。对于其他 99% 的用例,享受更简单的基于 bool
的运行条件!
更简单的状态 #
调度 v3添加了一个新的、更简单的“状态系统”。状态
允许您轻松地配置基于应用程序
的当前“状态”运行的不同应用程序
逻辑。
您这样定义状态
#[derive(States, PartialEq, Eq, Debug, Clone, Hash, Default)]
enum AppState {
#[default]
MainMenu,
InGame,
}
枚举的每个变体对应于应用程序
可以处的不同状态。
app.add_state::<AppState>()
这将设置您的应用程序
以使用给定的状态。它添加了 状态
资源,它可以用于查找应用程序
当前处于的状态。
fn check_state(state: Res<State<AppState>>) {
info!("We are in the {} state", state.0);
}
此外,add_state
将为每个可能的值创建一个 OnUpdate
集,然后您可以将您的系统添加到其中。这些集合作为正常应用程序更新的一部分运行,但仅当应用程序处于给定状态时运行。
app
.add_systems(
(main_menu, start_game)
.in_set(OnUpdate(AppState::MainMenu))
)
.add_system(fun_gameplay.in_set(OnUpdate(AppState::InGame)));
它还将为每个状态创建 OnEnter
和 OnExit
调度,它们仅在从一种状态转换到另一种状态时运行。
app
.add_system(load_main_menu.in_schedule(OnEnter(AppState::MainMenu)))
.add_system(cleanup_main_menu.in_schedule(OnExit(AppState::MainMenu)))
add_state
还添加了 nextState
资源,它可以用来排队状态更改。
fn start_game(
button_query: Query<&Interaction, With<StartGameButton>>,
mut next_state: ResMut<NextState<AppState>>,
){
if button_query.single() == Interaction::Pressed {
next_state.set(AppState::InGame);
}
}
这取代了 Bevy 以前的状态系统,该系统很难处理。它具有状态堆栈、精心设计的排队转换和错误处理(大多数人只是取消了包装)。状态堆栈非常复杂,难以学习,非常容易出现令人恼火的错误,而且大多被忽略。
因此,在Bevy 0.10中,状态现在是“无堆栈的”:一次只能排队一种类型的状态。经过大量的 alpha 测试,我们有理由相信这对于迁移来说应该不会太糟糕。如果您依赖于状态堆栈,您有很多选择
- 在核心状态系统的基础上构建“堆栈”逻辑
- 将您的状态拆分为多个状态,这些状态捕获应用程序状态的正交元素
- 使用与 Bevy 的第一方版本相同的模式构建您自己的状态堆栈抽象。新的状态逻辑都没有硬编码!如果您构建了一些东西,让社区其他成员知道,以便您进行协作!
基础集:获得正确的默认行为 #
一位敏锐的读者可能会指出
- Bevy 会自动并行运行其系统。
- 除非系统之间存在明确的排序关系,否则系统的顺序是非确定性的。
- 现在所有系统都存储在一个单一的
Schedule
对象中,它们之间没有障碍。 - 系统可以属于任意数量的系统集,每个系统集都可以添加自己的行为。
- Bevy 是一个功能强大的引擎,具有许多内部系统。
这不会导致彻底的混乱以及乏味的面条式工作来解决每一个排序歧义?许多用户喜欢阶段,它们有助于理解应用程序
的结构!
好吧,我们很高兴您提出这个问题,虚构的怀疑者。为了减少这种混乱(并简化迁移),Bevy 0.10 附带了一组全新的系统集,这些系统集由 DefaultPlugins
提供:CoreSet
、StartupSet
和 RenderSet
。它们名称与旧的 CoreStage
、StartupStage
和 RenderStage
的相似之处并非巧合。与阶段非常相似,每个集之间都有命令刷新点,并且现有系统已直接迁移。
以阶段为中心的架构的某些部分很有吸引力:清晰的高级结构、在刷新点上的协调(以减少过度的瓶颈)以及良好的默认行为。为了保留这些部分(同时剔除令人沮丧的部分),我们引入了基础集的概念(由 @cart 添加)。基础集只是普通的系统集
,除了
- 每个系统最多可以属于一个基础集。
- 没有指定基础集的系统将被添加到调度的默认基础集(如果调度有一个)。
// You define base sets exactly like normal sets, with the
// addition of the system_set(base) attribute
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
#[system_set(base)]
enum MyBaseSet {
Early,
Late,
}
app
// This ends up in CoreSet::Update by default
.add_system(no_explicit_base_set)
// You must use .in_base_set rather than .in_set for explicitness
// This is a high-impact decision!
.add_system(post_update.in_base_set(CoreSet::PostUpdate))
// Look, it works!
.add_system(custom_base_set.in_base_set(MyBaseSet::Early))
// Ordering your base sets relative to CoreSet is probably wise
.configure_set(MyBaseSet::Early.before(CoreSet::Update))
.configure_set(MyBaseSet::Late.after(CoreSet::Update));
让我给你讲个故事,故事发生在一个没有基础集的世界里
- 一名新用户将
make_player_run
系统添加到他们的应用程序中。 - 有时这个系统在输入处理之前运行,导致随机丢弃输入。有时它在渲染之后运行,导致奇怪的闪烁。
- 经过一番沮丧后,用户发现这是由于“系统执行顺序歧义”。
- 用户运行了一个专门的检测工具,深入研究引擎的源代码,找出他们的系统应该在相对于引擎系统集的哪个顺序运行,然后继续他们的快乐旅程,对每个新系统都这样做。
- Bevy(或他们的第三方插件之一)更新,再次破坏了我们所有可怜的用户的系统排序。
这说明了一个明显的问题,即大多数游戏系统不需要知道或关心“内部系统”。
我们发现,在实践中,系统主要分为三类:游戏逻辑(所有最终用户系统的大多数)、在游戏逻辑之前需要发生的事情(例如事件清理和输入处理)以及在游戏逻辑之后需要发生的事情(例如渲染和音频)。
通过使用基础集广泛地对调度进行排序,Bevy 应用程序可以具有良好的默认行为和清晰的高级结构,而不会影响高级用户渴望的调度灵活性和明确性。请告诉我们您的使用情况如何!
改进的系统歧义检测 #
当多个系统以冲突的方式与 ECS 资源交互,但它们之间没有排序约束时,我们称之为“歧义”。如果您的 App
存在歧义,这可能会导致错误。我们已显著改善了歧义报告,您可以在新的 ScheduleBuildSettings
中配置它。查看文档以了解更多信息。如果您还没有在您的应用程序上尝试过:您应该看看!
单线程执行 #
现在,您可以通过 SingleThreadedExecutor
轻松地将 Schedule
切换为单线程评估,适用于不需要或不需要并行的用户。
schedule.set_executor_kind(ExecutorKind::SingleThreaded);
级联阴影贴图 #
Bevy 使用“阴影贴图”为灯光/物体投射阴影。以前版本的 Bevy 对定向光源使用了一个简单但有限的阴影贴图实现。对于给定的灯光,您将定义阴影贴图的分辨率和一个手动“视图投影”,它将确定阴影的投射方式。这有一些缺点
- 阴影贴图的分辨率是固定的。您必须在“覆盖较大的区域,但具有较低的分辨率”和“覆盖较小的区域,但具有较高的分辨率”之间做出选择。
- 分辨率不会适应相机位置。阴影可能在一个位置看起来很棒,但在另一个位置看起来很糟糕。
- “阴影投影”必须手动定义。这使得很难且难以接近地配置阴影以匹配给定的场景。
Bevy 0.10 添加了“级联阴影贴图”,它将摄像头的视锥体分解为一系列可配置的“级联”,每个级联都有自己的阴影贴图。这使得“靠近摄像机”的级联中的阴影非常详细,同时允许“远离摄像机”的阴影覆盖更广的区域,但细节更少。因为它使用摄像头的视锥体来定义阴影投影,所以阴影质量在摄像机穿过场景时保持一致。这也意味着用户不再需要手动配置阴影投影。它们会自动计算!
请注意,附近的阴影非常详细,而远处的阴影随着距离的增加而变得不那么详细(这并不重要,因为它们很远)。
虽然阴影级联解决了重要问题,但也引入了新问题。您应该使用多少级联?从摄像机到阴影出现的位置的最小和最大距离是多少?级联之间应该有多少重叠?务必调整这些参数以适应您的场景。
环境贴图照明 #
环境贴图是一种流行且计算成本低廉的方式,可以显著提高场景照明的质量。它使用立方体贴图纹理来提供来自“所有方向”的 360 度照明。这对于反射表面尤其明显,但它适用于所有照明材质。
这是 PBR 材质在没有环境贴图照明的情况下看起来的样子
这是 PBR 材质在有环境贴图照明的情况下看起来的样子
对于需要恒定照明(特别是室外场景)的场景,环境贴图是一个很好的解决方案。并且由于环境贴图是任意图像,因此艺术家对场景照明的特征有很大的控制权。
深度和法线预处理 #
此效果使用预处理中的深度来查找地面和力场之间的交点
Bevy 现在能够运行深度和/或法线预处理。这意味着深度和法线纹理将在主处理之前运行的渲染处理中生成,因此可以在主处理期间使用。这使得各种特殊效果成为可能,例如屏幕空间环境光遮蔽、时间抗锯齿等等。这些目前正在开发中,应该 在 Bevy 的下一个版本中可用。
在右侧的图像中,绿线是在法线纹理中检测到的边缘,蓝线是在深度纹理中检测到的边缘
预处理生成的深度和法线纹理
使用预处理本质上意味着渲染所有内容两次。预处理本身速度要快得多,因为它执行的工作比主处理少得多。预处理的结果可用于减少主处理中的过度绘制,但如果您的场景本来就不存在过度绘制,那么启用预处理将对性能产生负面影响。有很多方法可以改进这一点,我们将继续朝着这个目标努力。就像与任何与性能相关的事情一样,请务必根据您的用例进行测量,看看它是否有帮助。
当使用需要深度或法线纹理的特殊效果时,预处理仍然非常有用,因此,如果您想使用它,只需将DepthPrepass
或 NormalPrepass
组件添加到您的相机即可。
使用预处理着色器的阴影贴图 #
以前,用于阴影贴图的着色器是硬编码的,并且对材质没有了解,只有网格。现在,在 Bevy 0.10 中,Material
的深度预处理着色器用于阴影贴图。这意味着用于对 Material
执行阴影贴图的着色器是可自定义的!
作为奖励,在阴影贴图期间可以使用 Material
信息意味着我们可以立即启用 alpha 遮罩阴影,使树叶根据其纹理中的 alpha 值而不是仅基于其几何体来投射阴影。
平滑的骨骼动画过渡 #
您现在可以在两个(或多个)骨骼动画之间平滑过渡!
使用 play_with_transition
方法在 AnimationPlayer
组件上,您现在可以指定一个过渡持续时间,在此期间,新动画将与当前正在播放的动画进行线性混合,其权重将在该持续时间内线性下降,直到达到 0.0
。
#[derive(Component, Default)]
struct ActionTimer(Timer);
#[derive(Component)]
struct Animations {
run: Handle<AnimationClip>,
attack: Handle<AnimationClip>,
}
fn run_or_attack(
mut query: Query<(&mut AnimationPlayer, &mut ActionTimer, &Animations)>,
keyboard_input: Res<Input<KeyCode>>,
animation_clips: Res<Assets<AnimationClip>>,
time: Res<Time>,
) {
for (mut animation_player, mut timer, animations) in query.iter_mut() {
// Trigger the attack animation when pressing <space>
if keyboard_input.just_pressed(KeyCode::Space) {
let clip = animation_clips.get(&animations.attack).unwrap();
// Set a timer for when to restart the run animation
timer.0 = Timer::new(
Duration::from_secs_f32(clip.duration() - 0.5),
TimerMode::Once,
);
// Will transition over half a second to the attack animation
animation_player
.play_with_transition(animations.attack.clone(), Duration::from_secs_f32(0.5));
}
if timer.0.tick(time.delta()).just_finished() {
// Once the attack animation is finished, restart the run animation
animation_player
.play_with_transition(animations.run.clone(), Duration::from_secs_f32(0.5))
.repeat();
}
}
}
改进的 Android 支持 #
Bevy 现在可以在更多设备上的 Android 上开箱即用。这是通过等待 Resumed
事件来创建窗口而不是在启动时进行创建来实现的,这与 Android 上的 onResume()
回调相匹配。
为了遵循 Suspended
事件的建议,Bevy 现在将在收到该事件时退出。这是一种临时解决方案,直到 Bevy 能够在恢复时重新创建渲染资源。
请在您的设备上测试并报告您遇到的成功或问题!在某些带有软件按钮的设备上,存在一个关于触摸位置的已知问题,因为 winit 不会暴露 (yet) 内插大小,只暴露内部大小。
由于这使得 Bevy 更接近于完全支持 Android,因此不再需要为 Android 和 iOS 创建单独的示例。它们已在一个 "mobile" 示例 中重新组合,并且说明已更新 (for Android 和 for iOS).
以下是在 iOS 上运行的同一个示例!
重新设计的 Bloom #
Bloom 经历了一些重大变化,现在看起来更好,更容易控制,并且视觉伪像更少。结合新的色调映射选项,Bloom 自上一个版本以来有了很大改进!
- 在 Bevy 0.9 中,Bloom 看起来像这样。
- 将色调映射器切换到像
AcesFitted
这样的东西已经是很大改进。 - 在 Bevy 0.10 中,Bloom 现在看起来像这样。它更可控,也不那么霸道。
- 为了使 Bloom 更强,而不是提高
BloomSettings
强度,让我们将每个立方体的emissive
值加倍。 - 最后,如果您想要更极端的 Bloom,类似于旧算法,您可以将
BloomSettings::composite_mode
从BloomCompositeMode::EnergyConserving
更改为BloomCompositeMode::Additive
。 - 使用新的
bloom_3d
(和bloom_2d
)示例在交互式游乐场中探索新的 Bloom 设置。
距离和大气雾 #
Bevy 现在可以渲染距离和大气雾效果,通过使物体在距离视野越远的地方显得更暗,从而为您的场景带来更强烈的深度和氛围。
雾可以通过新的 FogSettings
组件对每个相机进行控制。在暴露几个旋钮方面已投入了特别的关注,让您可以完全艺术地控制雾的外观,包括通过控制雾颜色的 alpha 通道来控制雾的淡入淡出。
commands.spawn((
Camera3dBundle::default(),
FogSettings {
color: Color::rgba(0.1, 0.2, 0.4, 1.0),
falloff: FogFalloff::Linear { start: 50.0, end: 100.0 },
},
));
雾的行为方式,关于距离是由 FogFalloff
枚举控制的。所有来自固定功能 OpenGL 1.x / DirectX 7 时代的“传统”雾衰减模式都受到支持
FogFalloff::Linear
从 start
和 end
参数之间的 0 到 1 线性增加强度。(此示例分别使用 0.8 和 2.2 的值。)
FogFalloff::Exponential
根据由 density
参数控制的(反)指数公式增加。
FogFalloff::ExponentialSquared
根据略微修改的(反)指数平方公式增长,也由 density
参数控制。
此外,还提供了一种更复杂的 FogFalloff::Atmospheric
模式,它通过分别考虑光线extinction
和 inscattering
来提供更物理准确的结果。
DirectionalLight
影响也通过 directional_light_color
和 directional_light_exponent
参数支持所有雾模式,模拟在阳光明媚的户外环境中观察到的光线散射效果。
由于直接“手动”控制非线性雾衰减参数可能很棘手,因此提供了一些基于 气象能见度 的辅助函数,例如 FogFalloff::from_visibility()
FogSettings {
// objects retain visibility (>= 5% contrast) for up to 15 units
falloff: FogFalloff::from_visibility(15.0),
..default()
}
雾在 PBR 片段着色器上以“前向渲染风格”应用,而不是作为后期处理效果,这使得它能够正确处理半透明网格。
大气雾实现主要基于 Inigo Quilez(Shadertoy 联合创始人兼计算机图形传奇人物)的 这篇很棒的文章。感谢您精彩的写作和灵感!
StandardMaterial 混合模式 #
在 **Bevy 0.10** 中,AlphaMode
枚举得到了扩展,为 StandardMaterial
带来了对加色和乘色混合的支持。这两种混合模式是“经典”(非物理基础)计算机图形学工具箱的主力,通常用于实现各种效果。
演示使用混合模式创建彩色玻璃和火焰效果。 (源代码)
此外,还添加了对具有 预乘 alpha 的半透明纹理的支持,通过专用 alpha 模式实现。
以下是新模式的概览
AlphaMode::Add
— 以加法方式将片段的颜色与它们后面的颜色混合在一起(例如,像光一样),产生更亮的结果。适用于火焰、全息图、鬼魂、激光和其他能量束等效果。在图形软件中也称为线性叠加。AlphaMode::Multiply
— 以乘法方式将片段的颜色与它们后面的颜色混合在一起(例如,像颜料一样),产生更暗的结果。适用于近似部分光传输的效果,如彩色玻璃、窗户着色膜和一些彩色液体。AlphaMode::Premultiplied
— 行为与AlphaMode::Blend
非常相似,但假设颜色通道具有预乘 alpha。可以用来避免使用普通 alpha 混合纹理时可能出现的变色“轮廓”伪影,或者巧妙地创建将加色和普通 alpha 混合组合在一个纹理中的材质,因为对于其他恒定的 RGB 值,Premultiplied
对接近 1.0 的 alpha 值表现得更像Blend
,而对接近 0.0 的 alpha 值表现得更像Add
。
注意:使用新混合模式的网格将绘制在现有的 Transparent3d
渲染阶段,因此 AlphaMode::Blend
的相同z 轴排序考虑因素/限制适用。
更多色调映射选择 #
色调映射是使用“显示渲染变换”(DRT)将原始高动态范围 (HDR) 信息转换为实际“屏幕颜色”的过程。在 Bevy 的早期版本中,你只有两个色调映射选项:Reinhard 亮度或完全没有。在 **Bevy 0.10** 中,我们添加了许多选择!
无色调映射 #
这通常不推荐,因为 HDR 照明并非旨在用作颜色。
Reinhard #
一种简单的适应场景中颜色的方法:r = color / (1.0 + color)
。色调变化很大,亮度不会自然地去饱和。亮色主色和次色根本不会去饱和。
Reinhard 亮度 #
一种流行的方法,类似于普通 Reinhard,但包含了亮度。它适应场景中的光量。这是我们在 Bevy 的早期版本中使用的。它仍然是我们的默认算法,但这可能会在未来发生变化。色调变化。亮度在整个频谱中不会发生很大变化。
ACES Fitted #
电影和行业中使用的一种非常流行的算法(例如:ACES 是 Unreal 默认的色调映射算法)。当人们说“电影化”时,通常指的就是这个。
不中性,具有非常特定的美学风格,有意而戏剧性的色调变化。亮绿色和红色变成橙色。亮蓝色变成洋红色。对比度显著提高。亮度在整个频谱中去饱和。
AgX #
非常中性。与其他变换相比,图像有点去饱和。色调变化很小。轻微的 Abney 偏移。 由 Troy Sobotka 创建
Somewhat Boring Display Transform #
在暗部和中性色中几乎没有色调变化,但在亮部变化很大。亮度在整个频谱中去饱和。有点介于 Reinhard 和 Reinhard 亮度之间。概念上类似于 reinhard-jodie。设计为一种折衷方案,如果你想要例如在弱光下获得不错的肤色,但又无法负担重新制作 VFX 以在没有色调变化的情况下看起来不错。由 Tomasz Stachowiak 创建。
TonyMcMapface #
非常中性。轻微但有意而戏剧性的色调变化。亮度在整个频谱中去饱和。
摘自作者:Tony 是一种专为实时应用(如游戏)设计的显示变换。它有意地很无聊,不会增加对比度或饱和度,并且会尽可能地保持输入信号,在不需要压缩的情况下。输入信号的亮度等效亮度会受到压缩。非线性类似于 Reinhard。在压缩过程中,颜色色调会保留,但会进行有意而戏剧性的 Bezold–Brücke 偏移。为了避免出现色带现象,会使用选择性去饱和,同时注意避免 Abney 效应。 由 Tomasz Stachowiak 创建
Blender Filmic #
Blender 中的默认 Filmic 显示变换。有点中性。色调变化。亮度在整个频谱中去饱和。
颜色分级控制 #
我们添加了一些对颜色分级参数的基本控制,例如曝光度、伽马值、“色调映射前饱和度”和“色调映射后饱和度”。这些可以通过使用新的 ColorGrading
组件为每个相机进行配置。
0.5 曝光度 #
2.25 曝光度 #
并行流水线渲染 #
在多线程平台上,**Bevy 0.10** 现在将通过并行运行模拟和渲染而显著加快速度。渲染器在 Bevy 0.6 中重新设计,以启用此功能,但真正将它们并行运行的最后一步直到现在才完成。为了解决这个问题,我们进行了一些棘手的操作。渲染世界有一个必须在主线程上运行的系统,但任务池只能在世界的线程上运行。因此,当我们将渲染世界发送到另一个线程时,我们需要容纳仍在主线程上运行的渲染系统。为此,我们添加了在主线程上(除了世界的线程)生成任务的功能。
在测试不同的 Bevy 示例时,增益通常在 10% 到 30% 的范围内。如上图直方图所示,“多只狐狸”压力测试的平均帧时间比之前快了 1.8 毫秒。
要使用流水线渲染,只需添加 PipelinedRenderingPlugin
。如果你正在使用 DefaultPlugins
,那么它会在所有平台上自动添加,除了 wasm。Bevy 目前不支持 wasm 上的多线程,这是此功能正常工作所需的。如果你没有使用 DefaultPlugins
,则可以手动添加插件。
将窗口作为实体 #
在 Bevy 的早期版本中,Window
被表示为一个 ECS 资源(包含在 Windows
资源中)。在 **Bevy 0.10** 中,Window
现在是一个组件(因此窗口被表示为实体)。
这实现了许多目标
- 它为在 Bevy 的场景系统中表示窗口打开了大门
- 它将
Windows
暴露给 Bevy 的强大 ECS 查询 - 它提供了对每个窗口的粒度变更检测
- 改进了创建、使用和关闭窗口的可读性/可发现性
- 更改窗口的属性对于初始化和修改都是一样的。不再需要
WindowDescriptor
的麻烦! - 它允许 Bevy 开发人员和用户轻松地将新的组件数据附加到窗口
fn create_window(mut commands: Commands) {
commands.spawn(Window {
title: "My window :D".to_string(),
..default()
});
}
fn modify_windows(mut windows: Query<&mut Window>) {
for window in &mut windows {
window.title = "My changed window! :D".to_string();
}
}
fn close_windows(mut commands: Commands, windows: Query<Entity, With<Window>>) {
for entity in &windows {
commands.entity(entity).despawn();
}
}
渲染器优化 #
Bevy 的渲染器已经成熟到可以进行优化了。因此,我们对其进行了优化!
在 Bevy 中渲染任何内容时,最大的瓶颈是最终的渲染阶段,我们收集渲染世界中的所有数据以向 GPU 发送绘制调用。这里的核心循环非常热,任何额外的开销都会很明显。在 **Bevy 0.10** 中,我们对这个问题投入了大量精力,并从各个角度进行了攻击。总的来说,以下优化应该使渲染阶段比 0.9 版本快2-3 倍
- 在 #7639 中,@danchia 发现,即使禁用了日志记录,对热循环也会产生很大影响,在该阶段使速度提高了 20-50%。
- 在 #6944 中,@james7132 缩小了该阶段涉及的核心数据结构,减少了内存获取,使速度提高了 9%。
- 在 #6885 中,@james7132 重新设计了我们的
PhaseItem
和RenderCommand
基础设施,以在从World
获取组件数据时组合常见的操作,使速度提高了 7%。 - 在 #7053 中,@james7132 更改了
TrackedRenderPass
的分配模式,以最大程度地减少这些循环中的分支,使速度提高了 6%。 - 在 #7084 中,@james7132 改变了我们从 World 获取资源的方式,以最大程度地减少在该阶段使用原子操作,使速度提高了 2%。
- 在 #6988 中,@kurtkuehnert 更改了我们的内部资源 ID,使用原子递增计数器代替 UUID,减少了该阶段中一些分支的比较成本。
另一个正在进行的开发是使渲染阶段能够跨多个线程正确地并行化命令编码。继 #7248 由 @james7132 完成之后,我们现在支持将外部创建的 CommandBuffer
导入渲染图,这应该允许用户并行编码 GPU 命令并将它们导入渲染图。目前,这受到 wgpu 的阻碍,wgpu 在编码渲染通道时会锁定 GPU 设备,但我们应该能够在问题解决后尽快支持并行命令编码。
同样,我们也采取了措施,以在渲染管道的其他阶段启用更高的并行性。PipelineCache
是一种资源,几乎每个 Queue 阶段系统都需要以可变的方式访问,但也只需要很少地写入。在 #7205 中,@danchia 将其更改为使用内部可变性,以允许这些系统并行化。这还不能完全允许该阶段的每个系统都并行化,因为仍然存在一些常见的阻碍因素,但它应该允许无冲突的渲染阶段同时排队命令。
优化不仅仅是 CPU 时间!我们还改进了内存使用、编译时间和 GPU 性能!
- 由于 @james7132 的贡献,我们还将
ComputedVisibility
的内存使用量减少了 50%。这是通过用一组位标志替换内部存储来完成的,而不是使用多个布尔值。 - @robfm 还使用类型擦除作为一种解决方法,以解决 rustc 性能回归,以确保渲染相关的 crate 具有更好的编译时间,其中一些 crate 的编译速度提高了 高达 60%!完整的细节可以在 #5950 中查看。
- 在 #7069 中,Rob Swain (@superdump) 减少了 GPU 上使用的活动寄存器的数量,以防止寄存器溢出,从而显着提高了 GPU 端的性能。
最后,我们对特定使用场景进行了一些改进
- 在 #6833 中,@james7132 通过省略不必要的缓冲区复制,将网格蒙皮的骨骼提取速度提高了 40-50%。
- 在 #7311 中,@james7132 通过将一个常用计算从热循环中提取出来,将 UI 提取速度提高了 33%。
并行化变换传播和动画运动学 #
变换传播是任何游戏引擎的核心系统之一。如果你移动一个父实体,你希望它的子级在世界空间中移动。Bevy 的变换传播系统恰好是多个系统的最大瓶颈之一:渲染、UI、物理、动画等系统在它完成之前无法运行。变换传播必须足够快才能避免阻塞所有这些系统。在 Bevy 0.9 及之前的版本中,变换传播始终是单线程的,并且始终需要完整的层次结构遍历。随着世界变得越来越大,这种关键瓶颈所花费的时间也越来越长。在 Bevy 0.10 中,变换传播利用了结构良好的层次结构的结构,可以在多个线程上完全运行。完整的性能优势完全取决于层次结构的结构以及可用的 CPU 内核数量。在我们的测试中,这使得我们 many_foxes
基准测试中的变换传播在我们测试的硬件上 快了 4 倍。
如果变换传播可以并行化,那么动画的正向运动学也可以并行化。我们利用了结构良好的层次结构的相同保证结构,以完全并行化播放骨骼动画。我们还启用了一个基本的实体路径缓存查找,以减少系统进行的额外查找。总的来说,我们能够使相同 many_foxes
基准测试中的动画播放系统 快了 10 倍。
结合本版本中看到的其他所有优化,我们对 many_foxes
基准测试的测试已经从每帧约 10 毫秒(约 100 FPS)提高到每帧约 2.3 毫秒(约 434 FPS),速度提高了近 5 倍!
ECS 优化 #
ECS 是整个引擎的基础,因此消除 ECS 中的开销会导致引擎范围内的加速。在 Bevy 0.10 中,我们发现了很多领域可以大幅减少开销,并提高整个引擎的 CPU 利用率。
在 #6547 中,我们启用了 自动向量化,当使用 Query::for_each
及其并行变体时。根据正在编译引擎的目标架构,这会导致查询迭代时间快 50-87.5%。在 0.11 中,我们可能会将这种优化扩展到所有基于 Iterator::fold
的迭代器组合器,例如 Iterator::count
。有关更多详细信息,请参阅 此 PR。
在 #6681 中,通过紧密打包实体位置元数据并避免额外的内存查找,我们显着减少了通过 Query::get
进行随机查询查找时的开销,在 Query::get
和 World::get
中花费的开销减少了高达 43%。
在 #6800 和 #6902 中,我们发现 rustc 可以优化掉跨函数边界的编译时常量分支,将分支从运行时移动到编译时,从而在使用 EntityRef::get
、EntityMut::insert
、EntityMut::remove
及其变体时,将开销减少了高达 50%。
在 #6391 中,我们重新设计了 CommandQueue
的内部结构,使其更符合 CPU 缓存友好,这表明在编码和应用命令时速度提高了高达 37%。
SystemParam
改进 #
Bevy 的 ECS 的核心是 SystemParam
:这些类型(例如 Query
和 Res
)决定了系统可以做什么和不能做什么。以前,手动创建一个需要实现四个不可分割的特征的家族。在 Bevy 0.10 中,我们 使用了泛型关联类型,将它们 减少到只有两个特征:SystemParam
和 ReadOnlySystemParam
。
此外,#[derive(SystemParam)]
宏还接受了许多杂项可用性改进
- 更灵活:你不再被迫声明你不使用的生命周期。元组结构体现在允许使用,并且 const 泛型不会破坏任何东西。
- 封装:一个长期存在的错误已得到修复,该错误泄露了私有字段的类型。现在,
SystemParam
可以正确地封装私有世界数据。 - 无限:已取消 16 个字段限制,因此你可以使你的参数变得尽可能复杂。这对于生成代码最有用。
延迟世界修改 #
你可能知道,当你发送一个 Command
时,它不会立即修改世界。该命令存储在系统中,并在稍后的调度中应用。以这种方式延迟修改有一些好处
- 最小化世界访问:与可变查询(和资源)不同,延迟修改不受数据访问冲突的影响,这使得使用此模式的系统能够更好地并行化。
- 顺序独立性:当执行幂等操作(如设置全局标志)时,延迟修改允许你不必担心系统的执行顺序。
- 结构修改:延迟修改能够以
Query
和ResMut
无法做到的方式改变世界的结构,例如添加组件或生成和销毁实体。
Bevy 0.10 通过 Deferred
系统参数为此模式添加了头等支持,该参数接受 SystemBuffer
特征实现。这使你能够创建具有自定义延迟修改行为的系统,同时跳过与 Commands
相关的开销!
/// Sends events with a delay, but can run in parallel with other event writers.
pub struct EventBuffer<E>(Vec<E>);
// The `SystemBuffer` trait controls how deferred mutations get applied to the world.
impl<E> SystemBuffer for EventBuffer<E> { ... }
fn my_system(mut events: Deferred<EventBuffer<MyEvent>>) {
// Queue up an event to get sent when commands are applied.
events.0.push(MyEvent);
}
请注意,此功能应谨慎使用 - 尽管有潜在的性能优势,但使用不当实际上会导致性能 下降。在执行任何优化时,请确保你确实提高了速度!
Ref<T> 查询 #
自从 Bevy 0.1 以来,Mut<T>
一直用于启用更改检测(以及相关的类型,如 ResMut<T>
)。它是一个简单的包装类型,它提供了对组件及其更改标记元数据的可变访问,在值被修改时会自动标记更改。
在 Bevy 0.10 中,更改检测家族已经扩展到 Ref<T>
,它是 Mut<T>
的不可变变体。与它的可变同胞一样,它允许你对当前系统之外做出的更改做出反应。
use bevy::prelude::*;
fn inspect_changes_system<T: Component + Debug>(q: Query<Ref<T>>) {
// Iterate over each component of type `T` and log its changed status.
for val in &q {
if val.is_changed() {
println!("Value `{val:?}` was last changed at tick {}.", val.last_changed());
} else {
println!("Value `{val:?}` is unchanged.");
}
}
}
我们还弃用了 ChangeTrackers<T>
,这是检查组件更改标记的旧方法。此类型将在 Bevy 的下一个版本中删除。
三次曲线 #
此视频展示了四种三次曲线使用贝塞尔缓动平滑地动画。曲线本身是白色的,绿色是速度,红色是加速度,蓝色是确定曲线形状的控制点。
为了准备 UI 动画和手动调整的动画曲线,三次曲线已添加到 bevy_math
中。该实现提供了开箱即用的多种曲线,在各种应用程序中很有用
Bezier
:用户绘制的样条曲线,以及用于 UI 的三次贝塞尔动画缓动 - 为三次动画缓动提供了辅助方法,如上图所示。Hermite
:在你知道位置和速度的两个时间点之间进行平滑插值,例如网络预测。Cardinal
:在任意数量的控制点之间进行轻松插值,自动计算切线;Catmull-Rom 是一种 Cardinal 样条曲线。B-Spline
:加速度连续运动,特别适用于摄像机路径,其中速度(加速度)的平滑变化对于防止剧烈的抖动运动很重要。
CubicGenerator
特征是公开的,允许你定义自己的自定义样条曲线,这些样条曲线会生成 CubicCurve
!
性能 #
可以评估 CubicCurve
的位置、速度和加速度在任意点。这些评估都具有相同的性能成本,无论使用的三次曲线的类型如何。在现代 CPU 上,这些评估需要 1-2 纳秒,动画缓动(这是一个迭代过程)需要 15-20 纳秒。
将 AccessKit 集成到 bevy_ui
中 #
游戏是为所有人准备的:游戏的构建方式也应反映这一点。无障碍游戏很少见,适当的支持通常是事后才想到的,无论是从引擎还是游戏的角度。通过在构建 UI 解决方案时将可访问性放在首位,我们希望能够解决这个问题。
Bevy 在优秀 AccessKit crate 的帮助下,加入了 egui
,迈出了迈向跨平台默认可访问性的第一步。据我们所知,这使得 Bevy 成为第一个具有第一方可访问性支持的通用游戏引擎。
我们已经将 Bevy 的 UI 层次结构和文本元素公开给了屏幕阅读器和其他辅助设备,由新的默认开启 bevy_a11y
crate 管理。这最终由新的 AccessibilityNode
组件提供支持,该组件与现有层次结构结合在一起,将此信息直接公开给 AccessKit 和 Focus
资源,该资源存储具有键盘焦点的实体。
这里还有很多工作要做:将焦点系统与 基于游戏手柄的 UI 控件 解决方案集成,清理数据模型以 确保“默认可访问”成为现实,并添加对 AccessKit 中剩余功能的支持。
特别感谢 @mwcampbell
(AccessKit 的主要作者),他审查了我们的集成,并与我们一起努力减少了上游的依赖项,大大改进了编译时间和最终可执行文件的大小。这 在 Linux 上仍然是一个严峻的挑战,因此 accesskit_unix
特征标志 目前默认情况下处于禁用状态。
空间音频 #
Bevy 用於音訊的程式庫 rodio
包含對空間音訊的支持。Bevy 0.10 公開了基本的空間音訊。仍然存在一些注意事項,例如沒有 HRTF,也沒有對 Emitter
和 Listener
組件的一流支持。
有趣的是,在開發這個特定功能期間,@harudagondi
發現了一個 錯誤,其中音訊通道在調試或發布模式下運行應用程式時會反轉。這證明是一個 rodio
問題,而且也會影響以前版本的 Bevy。感謝 @dis-da-moe
,這個錯誤已在 上游修復。請參閱鏈接的 PR,了解有關音訊程式設計怪癖和性能問題的有趣詳細信息。
您現在可以在遊戲中使用空間音訊!克隆 bevy
倉庫,并在命令行中調用 cargo run --example spatial_audio_3d --release
,以展示 Bevy 中的 3D 空間音訊。
自訂音訊來源 #
Bevy 通過 Decodable
特性支持自訂音訊來源,但注冊到 bevy 應用的方式非常冗長,而且文檔很少。在 Bevy 0.10 中,為 App
添加了一個新的擴展特性,並且 Decodable
的文檔得到了很大改善。
因此,不是這樣做
struct MyCustomAudioSource { /* ... */ }
app.add_asset::<MyCustomAudioSource>()
.init_resource::<Audio<MyCustomAudioSource>>()
.init_resource::<AudioOutput<MyCustomAudioSource>>()
.add_system(play_queued_audio_system::<MyCustomAudioSource>.in_base_set(CoreSet::PostUpdate))
您只需要這樣做
app.add_audio_source::<MyCustomAudioSource>()
乾淨多了!
ShaderDef 值 #
Bevy 的著色器處理器現在支持帶有值的 ShaderDefs,使用新的 ShaderDefVal
。這允許開發人員將常數值傳遞到他們的著色器中
let shader_defs = vec![
ShaderDefVal::Int("MAX_DIRECTIONAL_LIGHTS".to_string(), 10),
];
這些可以在 #if
語句中使用,以根據值有選擇地啟用著色器代碼
#if MAX_DIRECTIONAL_LIGHTS >= 10
let color = vec4<f32>(1.0, 0.0, 0.0, 1.0);
#else
let color = vec4<f32>(0.0, 1.0, 0.0, 1.0);
#endif
ShaderDef 值可以內聯到著色器中
for (var i: u32 = 0u; i < #{MAX_DIRECTIONAL_LIGHTS}; i = i + 1u) {
}
它們也可以在著色器中內聯定義
#define MAX_DIRECTIONAL_LIGHTS 10
在著色器中定義的 ShaderDefs 會覆蓋從 Bevy 傳遞的值。
#else ifdef
著色器中的鏈 #
Bevy 的著色器處理器現在也支持這樣的 #else ifdef
鏈
#ifdef FOO
// foo code
#else ifdef BAR
// bar code
#else ifdef BAZ
// baz code
#else
// fallback code
#endif
新的著色器導入:全局和視圖 #
Global
和 View
結構現在可以使用 #import bevy_render::globals
和 #import bevy_render::view
在著色器中導入。Bevy 的內部著色器現在使用這些導入(節省了大量冗余)。以前,您要么需要在每個著色器中重新定義,要么導入更大的 bevy_pbr::mesh_view_types
(這並不總是需要的)。
以前需要這樣做
struct View {
view_proj: mat4x4<f32>,
inverse_view_proj: mat4x4<f32>,
view: mat4x4<f32>,
inverse_view: mat4x4<f32>,
projection: mat4x4<f32>,
inverse_projection: mat4x4<f32>,
world_position: vec3<f32>,
// viewport(x_origin, y_origin, width, height)
viewport: vec4<f32>,
};
現在您只需要這樣做!
#import bevy_render::view
自適應批處理,用于并行查詢迭代 #
Query::par_for_each
一直是大家在查詢過大而無法單線程運行時求助的工具。在您的屏幕上運行 100,000 個實體嗎?沒問題,Query::par_for_each
將其分成更小的批次,并将工作負載分布在多個線程上。但是,在 Bevy 0.9 及更早版本中,Query::par_for_each
要求調用者提供批次大小,以幫助調整這些批次以獲得最佳性能。這個相當不透明的旋鈕經常導致使用者隨機選擇一個值并使用它,或者根據他們的開發機器微調該值。不幸的是,最有效的值取決于運行時環境(即玩家計算機有多少個邏輯核心)和 ECS 世界的狀態(即有多少實體匹配?)。最終,大多數 API 使用者只選擇一個固定數字,並忍受結果,無論好壞。
// 0.9
const QUERY_BATCH_SIZE: usize = 32;
query.par_for_each(QUERY_BATCH_SIZE, |mut component| {
// ...
});
在 0.10 中,您不再需要提供批次大小!如果您使用 Query::par_iter
,Bevy 將自動評估世界的狀態和任務池,并選擇一個批次大小, 使用啟發式方法 來確保足夠的并行性,而不會產生太多開銷。這使得并行查詢與普通的單線程查詢一樣易於使用!雖然對於大多數典型用例來說很棒,但這些啟發式方法可能并不適合所有工作負載,因此我們為那些需要更精細控制工作負載分布的人提供了一個逃生艙。將來,我們可能會進一步調整支持啟發式方法,以嘗試使默認值更接近這些工作負載中的最佳值。
// 0.10
query.par_iter().for_each(|component| {
// ...
});
// Fairly easy to convert from a single-threaded for_each. Just change iter to par_iter!
query.iter().for_each(|component| {
// ...
});
您也可以使用 BatchingStrategy
更精細地控制批處理
query
.par_iter_mut()
// run with batches of 100
.batching_strategy(BatchingStrategy::fixed(100))
.for_each(|mut component| { /* ... */ });
請參閱 BatchingStrategy
文檔以了解更多信息。
UnsafeWorldCell
和 UnsafeEntityCell
#
UnsafeWorldCell
和 UnsafeEntityCell
允許通過不安全的代碼共享可變訪問世界的一部分。它的作用與 UnsafeCell
類似,允許人們構建內部可變性抽象,例如 Cell
Mutex
Channel
等。在 bevy 中,UnsafeWorldCell
將用於支持调度器和系統參數實現,因為這些是 World
的內部可變性抽象,它目前也用於實現 WorldCell
。我們計劃使用 UnsafeEntityCell
實現僅訪問實體上組件而不是整個世界的 EntityRef
/EntityMut
版本。
這些抽象是在 #6404、#7381 和 #7568 中引入的。
圓柱體形狀 #
圓柱體形狀原語已加入我們的內置形狀動物園!
可細分的平面形狀 #
Bevy 的 Plane
形狀現在可以細分任意次。
相機輸出模式 #
在 Bevy 0.9 中 添加的 相機驅動 后處理功能,為場景中多個相機提供了直觀的后期處理控制,但 存在一些邊緣情況,這些情況并不完全適合硬編碼的相機輸出模型。還有一些與雙緩沖目標紋理的真相源在相機之間不一致以及 MSAA 的采樣紋理在某些情況下沒有包含應有內容相關的錯誤和限制。
Bevy 0.10 在 CameraOutputMode
字段中添加了 Camera
,這使 Bevy 應用程式開發人員能夠手動配置 Camera
的渲染結果應如何(以及是否)寫入最終輸出紋理
// Configure the camera to write to the final output texture
camera.output_mode = CameraOutputMode::Write {
// Do not blend with the current state of the output texture
blend_state: None,
// Clear the output texture
color_attachment_load_op: LoadOp::Clear(Default::default()),
};
// Configure the camera to skip writing to the final output texture
// This can save a pass when there are multiple cameras, and can be useful for
// some post-processing situations
camera.output_mode = CameraOutputMode::Skip;
大多數單相機和多相機設置根本不需要接觸此設置。但是,如果您需要它,它就在那里等著您!
MSAA 需要額外的中間“多采樣”紋理,該紋理被解析為“實際”非采樣紋理。在一些渲染到相同紋理的邊緣情況多相機設置中,這可能會根據是否啟用或禁用 MSAA 產生奇怪/不一致的結果。我們添加了一個新的 Camera::msaa_writeback
bool
字段,該字段(啟用時)將將非采樣紋理的當前狀態寫入中間 MSAA 紋理(如果先前的相機已在給定幀上渲染到目標)。這確保了狀態一致,而不管 MSAA 配置如何。這默認為 true,因此您只需要在有多個相機設置并且您不想要 MSAA 回寫的情況下考慮它。
可配置的可见性组件 #
Visibility
組件控制是否應該渲染 Entity
。Bevy 0.10 重做了類型定義:我們不再使用單個 is_visible: bool
字段,而是使用一個枚舉,其中包含一個額外的模式
pub enum Visibility {
Hidden, // unconditionally hidden
Visible, // unconditionally visible
Inherited, // inherit visibility from parent
}
更容易理解!在以前的 Bevy 版本中,“繼承的可見性”和“隱藏”本質上是唯一的兩個選項。現在,實體可以选择可见,即使它们的父级是隐藏的!
AsBindGroup
存儲緩沖區 #
AsBindGroup
是一個有用的 Bevy 特性,它 使將數據傳遞到著色器變得非常容易。
Bevy 0.10 通過支持“存儲緩沖區綁定”擴展了這一點,這在傳遞大量/無界塊數據時非常有用
#[derive(AsBindGroup)]
struct CoolMaterial {
#[uniform(0)]
color: Color,
#[texture(1)]
#[sampler(2)]
color_texture: Handle<Image>,
#[storage(3)]
values: Vec<f32>,
#[storage(4, read_only, buffer)]
buffer: Buffer,
}
ExtractComponent
派生 #
為了將組件數據從“主應用程式”傳遞到“渲染應用程式”以進行 流水線渲染,我們執行“提取步驟”。ExtractComponent
特性用於復制數據。在以前的 Bevy 版本中,您必須手動實現它,但現在您可以派生它!
#[derive(Component, Clone, ExtractComponent)]
pub struct Car {
pub wheels: usize,
}
這擴展到這個
impl ExtractComponent for Car
{
type Query = &'static Self;
type Filter = ();
type Out = Self;
fn extract_component(item: QueryItem<'_, Self::Query>) -> Option<Self::Out> {
Some(item.clone())
}
}
它還支持過濾器!
#[derive(Component, Clone, ExtractComponent)]
#[extract_component_filter(With<Fuel>)]
pub struct Car {
pub wheels: usize,
}
將 wgpu 升級到 0.15 #
Bevy 0.10 現在使用最新最好的 wgpu
(我們選擇的低級圖形層)。除了 許多不錯的 API 改進和錯誤修復 之外,wgpu
現在對 DX12 使用 DXC 著色器編譯器,它更快、更少錯誤,并且允許使用新功能。
默认启用 OpenGL 后端 #
Bevy 一直支持 wgpu
的 OpenGL 后端,但它需要選擇加入。這導致 Bevy 無法在某些不支持 Vulkan 等現代 API 的機器上啟動。在 Bevy 0.10 中,OpenGL 后端默認情況下是啟用的,這意味著機器將在沒有其他 API 可用時自動回退到 OpenGL。
公开非统一索引支持(无绑定) #
Bevy 0.10 連接了對紋理和存儲緩沖區的非統一索引的初始支持。這是邁向現代 "無綁定/ GPU 驅動渲染" 的重要一步,這可以在支持它的平台上釋放顯著的性能。請注意,這只是使功能可供渲染插件開發人員使用。Bevy 的核心渲染功能尚未(還)使用無綁定方法。
我們添加了一個 新的示例,說明如何使用此功能
游戏手柄 API 改进 #
GamepadEventRaw
類型已刪除,取而代之的是單獨的 GamepadConnectionEvent
、GamepadAxisChangedEvent
和 GamepadButtonChangedEvent
,并且內部已重新設計以適應這種變化。
這允許在不篩選一般 GamepadEvent
類型的 情況下,更簡單、更細粒度的事件訪問。不錯!
fn system(mut events: EventReader<GamepadConnectionEvent>)
for event in events.iter() {
}
}
输入法编辑器 (IME) 支持 #
Window
現在可以使用 ime_enabled
和 ime_position
配置 IME 支持,這啟用了“死鍵”的使用,這為法語、拼音等提供了支持
反射路径:枚举和元组 #
Bevy 的“反射路徑”允許使用簡單(且動態)的字符串語法導航 Rust 值。Bevy 0.10 通過在反射路徑中添加對元組和枚舉的支持來擴展此系統
#[derive(Reflect)]
struct MyStruct {
data: Data,
some_tuple: (u32, u32),
}
#[derive(Reflect)]
enum Data {
Foo(u32, u32),
Bar(bool)
}
let x = MyStruct {
data: Data::Foo(123),
some_tuple: (10, 20),
};
assert_eq!(*x.path::<u32>("data.1").unwrap(), 123);
assert_eq!(*x.path::<u32>("some_tuple.0").unwrap(), 10);
预解析的反射路径 #
反射路径可以实现很多有趣且动态的编辑器场景,但它们也存在一个缺点:每次调用 path()
都需要解析字符串。为了解决这个问题,我们添加了 ParsedPath
,它允许预解析路径并在每次访问时重复使用解析结果。
let parsed_path = ParsedPath::parse("foo.bar[0]").unwrap();
let element = parsed_path.element::<usize>(&some_value);
这更适合重复访问,例如在每一帧都进行相同的查找!
ReflectFromReflect
#
在使用 Bevy 的 Rust 反射系统时,我们有时会遇到这样的情况:我们有一个表示特定类型 MyType
的“动态反射值”(尽管在幕后,它并不真正是那个类型)。当我们调用 Reflect::clone_value
、使用反射反序列化器或自己创建动态值时,就会发生这种情况。不幸的是,我们不能简单地调用 MyType::from_reflect
,因为我们没有在运行时了解具体 MyType
的知识。
ReflectFromReflect
是 TypeRegistry
中一个新的“类型数据”结构,它可以在没有任何对给定类型的具体引用情况下实现 FromReflect
特性操作。非常酷!
#[derive(Reflect, FromReflect)]
#[reflect(FromReflect)] // <- Register `ReflectFromReflect`
struct MyStruct(String);
let type_id = TypeId::of::<MyStruct>();
// Register our type
let mut registry = TypeRegistry::default();
registry.register::<MyStruct>();
// Create a concrete instance
let my_struct = MyStruct("Hello world".to_string());
// `Reflect::clone_value` will generate a `DynamicTupleStruct` for tuple struct types
// Note that this is _not_ a MyStruct instance
let dynamic_value: Box<dyn Reflect> = my_struct.clone_value();
// Get the `ReflectFromReflect` type data from the registry
let rfr: &ReflectFromReflect = registry
.get_type_data::<ReflectFromReflect>(type_id)
.unwrap();
// Call `FromReflect::from_reflect` on our Dynamic value
let concrete_value: Box<dyn Reflect> = rfr.from_reflect(&dynamic_value);
assert!(concrete_value.is::<MyStruct>());
其他反射改进 #
Reflect
现在已为std::collections::VecDeque
实现。- 反射的
List
类型现在具有insert
和remove
操作。 - 反射的
Map
类型现在具有remove
操作。 - 反射的泛型类型现在会自动实现
Reflect
,如果泛型也实现了 Reflect。无需添加手动T: Reflect
约束! - 组件反射现在使用
EntityRef
/EntityMut
而不是同时使用World
和Entity
,这允许它在更多场景中使用。 - 反射反序列化器现在可以避免在某些情况下不必要地克隆字符串!
Taffy 升级到 0.3 #
Taffy 是我们用来计算 bevy_ui
布局的库。Taffy 0.2 显著提高了嵌套 UI 的性能(我们的 many_buttons
示例现在快了 8%,更深层次的嵌套 UI 应该会看到更大的提升!)。它还支持 gap 属性,这使得创建具有均匀间距项目的 UI 变得更加容易。Taffy 0.3 添加了一些不错的 API 调整(还添加了一个网格布局功能,我们目前已将其禁用,因为它还需要一些集成工作)。
相对光标位置 #
我们添加了一个新的 RelativeCursorPosition
UI 组件,它在添加到 UI 实体时会跟踪相对于节点的光标位置。Some((0, 0))
表示节点的左上角,Some((1,1))
表示节点的右下角,None
表示光标“在节点之外”。
commands.spawn((
NodeBundle::default(),
RelativeCursorPosition::default(),
));
常量 Bevy UI 默认值 #
Bevy 广泛使用 Default
特性来简化类型的构造。Bevy UI 类型通常实现 Default
。但是,它有一个缺点(这是 Rust 的根本问题):Default
不能在 const
上下文中使用 (尚未!)。为了使 UI 布局配置可以定义为常量,我们在大多数 Bevy UI 类型中添加了 DEFAULT
关联常量。例如,您可以使用 Style::DEFAULT
来定义一个常量样式。
const COOL_STYLE: Style = Style {
size: Size::width(Val::Px(200.0)),
border: UiRect::all(Val::Px(2.0)),
..Style::DEFAULT
};
遍历世界的实体 #
在 Bevy 0.9 中,World::iter_entities
允许用户获取 World
中所有实体的迭代器,以 Entity
形式。在 Bevy 0.10 中,这已更改为对 EntityRef
的迭代器,它提供对所有实体组件的完整只读访问,而不仅仅是获取其 ID。它的新实现也应该比手动获取 EntityRef
快得多(尽管请注意,如果您知道要查找的确切组件,则 Query
仍然会更快)。这使用户可以任意从世界中读取任何实体数据,并且可能会在脚本语言集成和反射密集型工作流程中得到应用。
// Bevy 0.9
for entity in world.iter_entities() {
if let Some(entity_ref) = world.get_entity(entity) {
if let Some(component) = entity_ref.get::<MyComponent>() {
...
}
}
}
// Bevy 0.10
for entity_ref in world.iter_entities() {
if let Some(component) = entity_ref.get::<MyComponent>() {
...
}
}
将来,我们可能会有一个 World::iter_entities_mut
,它公开此功能,但提供对 World
中所有实体的任意可变访问。我们目前避免实现这一点,因为返回 EntityMut
迭代器可能会存在安全问题。有关更多详细信息,请参阅此 GitHub 问题。
LCH 颜色空间 #
Bevy 的 Color
类型现在支持 LCH 颜色空间(亮度、色度、色调)。LCH 有很多论据支持它,包括它提供了比 sRGB 多约 50% 的颜色。请查看 这篇文章,了解更多信息。
Color::Lcha {
lightness: 1.0,
chroma: 0.5,
hue: 200.0,
alpha: 1.0,
}
优化 Color::hex
性能 #
Color::hex
现在是一个 const
函数,这使 hex
的运行时间从大约 14ns 降至大约 4ns!
拆分 CorePlugin
#
CorePlugin
从历史上来说一直是一个“厨房水槽插件”。“核心”事物如果找不到其他地方,最终都会放在那里。这不是一个很好的组织策略,所以我们将它拆分为单独的部分:TaskPoolPlugin
、TypeRegistrationPlugin
和 FrameCountPlugin
。
EntityCommand
#
Commands
是“延迟 ECS”操作。它们使开发人员能够定义自定义 ECS 操作,这些操作在并行系统运行完毕后应用。许多 Commands
在单个实体上运行,但这种模式有点繁琐。
struct MyCustomCommand(Entity);
impl Command for MyCustomCommand {
fn write(self, world: &mut World) {
// do something with the entity at self.0
}
}
let id = commands.spawn(SpriteBundle::default()).id();
commands.add(MyCustomCommand(id));
为了解决这个问题,在 Bevy 0.10 中,我们添加了 EntityCommand
特性。这允许命令以符合人体工程学的方式应用于生成的实体。
struct MyCustomCommand;
impl EntityCommand for MyCustomCommand {
fn write(self, id: Entity, world: &mut World) {
// do something with the given entity id
}
}
commands.spawn(SpriteBundle::default()).add(MyCustomCommand);
像素完美示例 #
我们现在有一个新的 “像素完美”示例,说明了如何设置像素完美精灵。它使用了 Bevy 的新可爱徽标精灵!
UI 文本布局示例 #
我们添加了一个很好的 “文本布局”示例,它说明了各种 Bevy UI 文本布局设置。
CI 改进 #
我们在 Bevy 领域非常重视 CI,并且一直在寻找让我们的生活更美好的新方法。在本周期中,我们进行了一些不错的改进。
- 我们现在为
bevy
crate 设置了一个 MSRV(最低支持 Rust 版本),并且有一个 CI 任务检查 MSRV。 - CI 会向新贡献者发送友好的欢迎信息!
- CI 现在会在 PR 被标记为重大更改并且没有迁移指南时要求提供迁移指南。
第一个主题专家版本 #
这是我们使用新的 主题专家 (SME) 系统 发布的第一个版本。我们合并了大量更改,并且这尽管我们的项目负责人 @cart
由于圣诞节和滑雪度假而缺席了大约一个月。我们保持了高标准,并且创造了令人惊叹的东西。可以肯定地说,未来一片光明(并且可持续)!敬请关注更多领域的更多 SME 职位。
下一步是什么? #
- 资产系统演变:我们在 Bevy 资产系统的下一个迭代 上取得了进展,这将添加预处理资产的能力,并提高资产系统的灵活性和可用性。
- 启动 Bevy 编辑器工作:我们已准备好开始将重点转移到构建 Bevy 编辑器!我们已经开始 收集需求,并且希望在 Bevy 0.11 周期中开始初始设计阶段。
- 时间抗锯齿 (TAA):我们已经基本实现了 TAA,它使用运动向量和时间来产生一种非常流行的屏幕空间抗锯齿效果。
- 屏幕空间环境光遮蔽 (SSAO):这是一种流行且相对便宜的照明技术,可以使场景看起来更加自然。它建立在深度预处理工作之上。
- 自动渲染批处理和实例化:通过组合几何图形或使用实例化来自动减少绘制调用。这将使 Bevy 能够渲染数十万个对象,而不会出现停滞现象。我们实际上已经支持这一点,但它必须在我们的标准管道之外手动实现。这将在我们的内置渲染管道中“免费”带来批处理和实例化优势。
- 一次性系统:通过命令以 基于推送的方式运行任意系统,并将它们存储为回调组件以实现超灵活的行为定制。
- 更好的插件:更清晰、更标准化的工具,用于 将第三方插件适应您应用程序的独特架构,消除 它们初始化时的顺序依赖性 并定义 它们之间的依赖性。
- 从
World
中拉出!Send
数据:在旨在跨线程发送的结构中存储非线程安全数据给我们带来了很多麻烦。我们计划将其拉到App
中,从而解决 多个世界 设计的第一步障碍。 - 时间戳窗口和输入事件:正如在 #5984 中所讨论的那样,跟踪输入事件的确切时间对于确保事件排序和时间可以准确地重建至关重要。
- 选择退出更改检测:通过 在编译或运行时关闭更改检测,提高小型组件的性能。
- 全面的动画组合:支持非过渡动画组合(即动画的任意加权混合)。有关更完整的信息,请参阅 RFC。
查看 Bevy 0.11 里程碑,了解当前正在考虑用于 Bevy 0.11 的工作的最新列表。
支持 Bevy #
赞助有助于使我们对 Bevy 的工作可持续发展。如果您相信 Bevy 的使命,请考虑 赞助我们... 每一点帮助都有意义!
贡献者 #
Bevy 是由 一大群人 制作的。衷心感谢 173 位贡献者使此版本(和相关文档)成为可能!按随机顺序排列
- @killercup
- @torsteingrindvik
- @utilForever
- @garychia
- @lewiszlw
- @myreprise1
- @tomaspecl
- @jinleili
- @nicopap
- @edgarssilva
- @aevyrie
- @laundmo
- @AxiomaticSemantics
- @polygon
- @SkiFire13
- @SludgePhD
- @abnormalbrain
- @Testare
- @ldubos
- @SpeedRoll
- @rodolphito
- @hymm
- @rdbo
- @AndrewB330
- @13ros27
- @lupan
- @iwek7
- @ErickMVdO
- @kerkmann
- @davidhof
- @Pietrek14
- @Guvante
- @lidong63
- @Tirthnp
- @x-52
- @Suficio
- @pascualex
- @xgbwei
- @BoxyUwU
- @superdump
- @TheRawMeatball
- @wackbyte
- @StarLederer
- @MrGunflame
- @akimakinai
- @doup
- @komadori
- @darthdeus
- @phuocthanhdo
- @DanielJin21
- @LiamGallagher737
- @oliviacrain
- @IceSentry
- @Vrixyz
- @johanhelsing
- @Dessix
- @woodroww
- @SDesya74
- @alphastrata
- @wyhaya
- @foxzool
- @DasLixou
- @nakedible
- @soqb
- @Dorumin
- @maniwani
- @Elabajaba
- @geieredgar
- @stephenmartindale
- @TimJentzsch
- @holyfight6
- @targrub
- @smessmer
- @redwarp
- @LoopyAshy
- @mareq
- @bjrnt
- @slyedoc
- @kurtkuehnert
- @Charles Bournhonesque
- @cryscan
- @A-Walrus
- @JMS55
- @cBournhonesque
- @SpecificProtagonist
- @Shatur
- @VitalyAnkh
- @aktaboot
- @dis-da-moe
- @chrisjuchem
- @wilk10
- @2ne1ugly
- @zeroacez
- @jabuwu
- @Aceeri
- @coreh
- @SuperSodaSea
- @DGriffin91
- @DanielHZhang
- @mnmaita
- @elbertronnie
- @Zeenobit
- @oCaioOliveira
- @Sjael
- @JonahPlusPlus
- @devmitch
- @alice-i-cecile
- @remiCzn
- @Sasy00
- @sQu1rr
- @Ptipiak
- @zardini123
- @alradish
- @adam-shih
- @LinusKall
- @jakobhellermann
- @Andrii Borziak
- @figsoda
- @james7132
- @l1npengtul
- @danchia
- @AjaxGb
- @VVishion
- @CatThingy
- @zxygentoo
- @nfagerlund
- @silvestrpredko
- @ameknite
- @shuoli84
- @CrystaLamb
- @Nanox19435
- @james-j-obrien
- @mockersf
- @R2Boyo25
- @NeoRaider
- @MrGVSV
- @GuillaumeGomez
- @wangling12
- @AndrewJakubowicz
- @rick68
- @RedMachete
- @tbillington
- @ndarilek
- @Ian-Yy
- @Edwox
- @DevinLeamy
- @TehPers
- @cart
- @mvlabat
- @NiklasEi
- @ItsDoot
- @JayPavlina
- @ickk
- @Molot2032
- @devil-ira
- @inodentry
- @MinerSebas
- @JoJoJet
- @Neo-Zhixing
- @rparrett
- @djeedai
- @Pixelstormer
- @iiYese
- @harudagondi
- @1e1001
- @ickshonpe
- @rezural
- @arewerage
- @ld000
- @imustend
- @robtfm
- @frewsxcv
完整变更日志 #
新增 #
- 无障碍:为标记特定文本作为 UI 控件的标签添加了
Label
。 - 无障碍:集成并公开 AccessKit 无障碍功能。
- App:
App::setup
- App:
SubApp::new
- App:Bevy 应用现在将在启动时默认记录系统信息。
- 音频:公开来自 rodio 的 symphonia 功能,在 bevy_audio 和 bevy 中。
- 音频:基本空间音频。
- ECS:
bevy_ptr::dangling_with_align
:为在编译时未知对齐方式的类型创建对齐良好的悬空指针。 - ECS:
Column::get_added_ticks
- ECS:
Column::get_column_ticks
- ECS:
DetectChanges::set_if_neq
:当新值和旧值相等时触发更改检测。这将适用于组件和资源。 - ECS:
SparseSet::get_added_ticks
- ECS:
SparseSet::get_column_ticks
- ECS:
Tick
,一个围绕单个更改检测滴答的包装器。 - ECS:
UnsafeWorldCell::world_mut
现在存在,可以用来从UnsafeWorldCell
中获取一个&mut World
。 - ECS:
WorldId
现在实现了FromWorld
特征。 - ECS:对
Ptr
、PtrMut
和OwnedPtr
实现一个core::fmt::Pointer
。 - ECS:添加
bevy_ecs::schedule_v3
模块。 - ECS:添加
EntityMap::iter()
。 - ECS:将
Ref
添加到 prelude 中。 - ECS:在
ScheduleBuildSettings
中添加report_sets
选项。 - ECS:为所有资源 ID 添加
Resources::iter
以进行迭代。 - ECS:添加
UnsafeWorldCell
抽象。 - ECS:添加
World::clear_resources
&World::clear_all
。 - ECS:为系统排序添加了一个基本示例。
- ECS:为
Option<NonSend<>>
添加ReadOnlySystemParam
的缺失实现。 - ECS:为允许在作用域的线程或外部线程上进行生成,添加了一个
spawn_on_external
方法。 - ECS:添加常量
Entity::PLACEHOLDER
。 - ECS:添加示例以展示如何使用
apply_system_buffers
。 - ECS:添加系统管道的日志记录变体。
- ECS:为无类型指针
Ptr
和PtrMut
添加安全构造函数。 - ECS:添加包含崩溃系统的单元测试。
- ECS:将
wrapping_add
添加到change_tick
。 - ECS:添加了“基本集”并将 CoreSet 移植到使用它们。
- ECS:为
MutUntyped
添加了as_mut
和as_ref
方法。 - ECS:添加了
bevy::ecs::system::assert_is_read_only_system
。 - ECS:添加了
Components::resource_id
。 - ECS:为实体添加了
DebugName
世界查询,以获得更友好的调试名称。 - ECS:为
IntoSystemConfigs
添加了distributive_run_if
,以在使用add_systems
时能够为每个系统添加一个运行条件。 - ECS:添加了
EntityLocation::table_id
。 - ECS:添加了
EntityLocation::table_row
。 - ECS:为
EventReader
添加了IntoIterator
实现,因此您现在可以对事件执行&mut reader
而不是reader.iter()
。 - ECS:在 SparseSet 上添加了
len
、is_empty
、iter
方法。 - ECS:添加了
ManualEventReader::clear()
。 - ECS:添加了
MutUntyped::with_type
,它允许转换为Mut<T>
。 - ECS:在
ComponentInfo
上添加了new_for_test
,以简化测试代码。 - ECS:添加了
not
条件。 - ECS:添加了
on_timer
和on_fixed_timer
运行条件。 - ECS:添加了
OwningPtr::read_unaligned
。 - ECS:添加了
ReadOnlySystem
,它为所有参数都实现ReadOnlySystemParam
的System
类型实现。 - ECS:添加了
Ref
,它允许以不可变的方式检查更改检测标志。 - ECS:为
PtrMut
添加了shrink
和as_ref
方法。 - ECS:添加了
SystemMeta::name
。 - ECS:添加了
SystemState::get_manual_mut
。 - ECS:添加了
SystemState::get_manual
。 - ECS:添加了
SystemState::update_archetypes
。 - ECS:在
App
上添加了大量方法以以符合人体工程学的方式处理计划。 - ECS:添加了从
Ptr
、PtrMut
和OwningPtr
到NonNull<u8>
的转换。 - ECS:添加了更常见的运行条件:
on_event
、资源更改检测、state_changed
、any_with_component
。 - ECS:添加了对
bevy_ptr
类型的变体的支持,这些变体不需要为指向的类型正确对齐。 - ECS:添加了
CoreSchedule
枚举。 - ECS:添加了系统参数类型
Deferred<T>
,它可用于推迟World
突变。由新的特征SystemBuffer
提供支持。 - ECS:为运行条件添加了扩展方法
.and_then(...)
和.or_else(...)
,它们允许使用短路行为组合运行条件。 - ECS:添加了标记特征
BaseSystemSet
,它与FreeSystemSet
区分开来。这两个都是SystemSet
的子特征。 - ECS:为
Mut
、ResMut
、NonSendMut
和MutUntyped
添加了reborrow
方法。 - ECS:添加了私有
prepare_view_uniforms
系统现在有一个用于计划目的的公共系统集,称为ViewSet::PrepareUniforms
。 - ECS:添加了特征
Combine
,它可以与新的CombinatorSystem
一起使用来创建具有自定义行为的系统组合器。 - ECS:添加了特征
EntityCommand
。这是Command
的对应项,用于为单个实体执行代码的类型。 - ECS:引入 EntityLocation::INVALID 常量并调整 Entities::get 注释。
- ECS:状态派生宏。
- ECS:对元组结构和单元结构支持
SystemParam
派生宏。 - 层次结构:添加
Transform::look_to
。 - 层次结构:为
EntityMut
添加了add_child
、set_parent
和remove_parent
。 - 层次结构:在
BuildChildren
特征中添加了clear_children(&mut self) -> &mut Self
和replace_children(&mut self, children: &[Entity]) -> &mut Self
函数。 - 层次结构:添加了
ClearChildren
和ReplaceChildren
结构体。 - 层次结构:添加了
push_and_replace_children_commands
和push_and_clear_children_commands
测试。 - 层次结构:添加了
BuildChildrenTransformExt
特征。 - 输入:添加输入法编辑器支持。
- 输入:添加了
Axis<T>::devices
。 - 输入:为
bevy_input
添加了常见的运行条件。 - 宏:添加帮助程序以根据导入方式获取
bevy::x
或bevy_x
。 - 数学:
CubicBezier2d
、CubicBezier3d
、QuadraticBezier2d
和QuadraticBezier3d
类型,具有用于采样位置、速度和加速度的方法。通用Bezier
类型也可用,并且泛型化了所有级别的贝塞尔曲线。 - 数学:
CubicBezierEasing
,具有其他方法以允许平滑的缓动动画。 - 数学:添加了一个通用的三次曲线特征以及对基数样条线(包括 Catmull-Rom)、B 样条线、贝塞尔曲线和埃尔米特样条线的实现。二维三次曲线段也为动画实现了缓动功能。
- 新的反射路径语法:按索引访问结构体字段(示例语法:
foo#1
)。 - 反射:除了
RandomState
之外的State
泛型现在可以为hashbrown::HashMap
和collections::HashMap
反射。 - 反射:
Aabb
现在实现了FromReflect
。 - 反射:
derive(Reflect)
现在支持包含泛型类型的结构体和枚举。 - 反射:
ParsedPath
用于缓存反射路径。 - 反射:
std::collections::HashMap
现在可以反射。 - 反射:
std::collections::VecDeque
现在实现了Reflect
以及所有相关的特征。 - 反射:为
Tuple
类型添加反射路径支持。 - 反射:添加了
ArrayIter::new
。 - 反射:添加了
FromReflect::take_from_reflect
。 - 反射:添加了
List::insert
和List::remove
。 - 反射:添加了
Map::remove
。 - 反射:添加了
ReflectFromReflect
。 - 反射:添加了
TypeRegistrationDeserializer
,它简化了在反序列化字符串时获取&TypeRegistration
的过程。 - 反射:为
List
添加了以前由Array
提供的方法。 - 反射:添加了对反射路径中枚举的支持。
- 反射:添加了
bevy_reflect_compile_fail_tests
容器,用于测试编译错误。 - 反射:bevy_reflect:添加缺少的基元注册。
- 反射:为
&'static Path
实现Reflect
。 - 反射:为
Fxaa
实现Reflect
。 - 反射:为基元实现
TypeUuid
,并修复多个参数泛型具有相同TypeUuid
的问题。 - 反射:为窗口事件和相关类型实现了
Reflect
+FromReflect
。添加WindowPlugin
时,这些类型会自动注册。 - 反射:为 glam 类型注册哈希。
- 反射:为
bevy_render
注册缺少的反射类型。 - 渲染: 为
GltfNode
/GltfMesh
/GltfPrimitive
添加一个公有字段extras
,用于存储额外数据。 - 渲染: 为
GltfPrimitive
添加一个公有字段material_extras
,用于存储材质额外数据。 - 渲染: 添加 'Color::as_lcha' 函数 (#7757)
- 渲染: 添加
Camera::viewport_to_world_2d
- 渲染: 添加更常用的十六进制颜色条目
- 渲染: 添加环境光钩子
- 渲染: 在光照示例中添加 bevy logo 以演示 alpha mask 阴影
- 渲染: 添加 Box::from_corners 方法
- 渲染: 添加 OpenGL 和 DX11 后端
- 渲染: 将正交摄像机支持添加回定向阴影
- 渲染: 将标准材质深度偏差添加到管道
- 渲染: 添加对 Rgb9e5Ufloat 纹理的支持
- 渲染: 为缓冲区添加了缓冲区使用字段
- 渲染: 可以在着色器内部定义一个值
- 渲染: EnvironmentMapLight 对 WebGL2 的支持
- 渲染: 为
Extract<>
实现ReadOnlySystemParam
- 渲染: 初始色调映射选项
- 渲染: ShaderDefVal: 添加一个
UInt
选项 - 渲染: 支持在 AsBindGroup 宏中使用原始缓冲区
- 渲染:
Aabb
现在实现了Copy
。 - 渲染:
ExtractComponent
可以指定输出类型,输出是可选的。 - 渲染:
Mssaa::samples
- 渲染: 在着色器预处理中添加
#else ifdef
。 - 渲染: 为 RenderPipelineDescriptor 和 ComputePipelineDescriptor 添加一个字段
push_constant_ranges
- 渲染: 添加了
Material::prepass_vertex_shader()
和Material::prepass_fragment_shader()
用于从Material
控制预渲染 - 渲染: 添加了
BloomSettings:lf_boost
,BloomSettings:lf_boost_curvature
,BloomSettings:high_pass_frequency
和BloomSettings:composite_mode
. - 渲染: 添加了
BufferVec::extend
- 渲染: 添加了
BufferVec::truncate
- 渲染: 添加了
Camera::msaa_writeback
,它可以启用和禁用 msaa 写回。 - 渲染: 添加了
CascadeShadowConfigBuilder
用于帮助创建CascadeShadowConfig
- 渲染: 添加了
DepthPrepass
和NormalPrepass
组件,用于控制预渲染将创建哪些纹理,以及这些纹理在后续渲染阶段中是否可用。 - 渲染: 添加了
Draw<T>::prepare
可选的特征函数。 - 渲染: 添加了
DrawFunctionsInternals::id()
- 渲染: 添加了
FallbackImageCubemap
。 - 渲染: 添加了
FogFalloff
枚举,用于在三种广泛使用的“传统”雾化衰减模式之间进行选择:Linear
,Exponential
和ExponentialSquared
,以及更高级的Atmospheric
雾; - 渲染: 添加了
get_input_node
- 渲染: 为
bevy_render::color::Color
枚举添加了Lcha
成员 - 渲染: 添加了
MainTaret::main_texture_other
- 渲染: 添加了
PhaseItem::entity
- 渲染: 为
MaterialPlugin
添加了prepass_enabled
标志,用于控制材质是否使用预渲染。 - 渲染: 为
PbrPlugin
添加了prepass_enabled
标志,用于控制 StandardMaterial 是否使用预渲染。目前默认设置为 false。 - 渲染: 添加了
PrepassNode
,它在主渲染阶段之前运行 - 渲染: 添加了
PrepassPlugin
,用于提取/准备/排队必要的数据 - 渲染: 添加了
RenderCommand::ItemorldQuery
关联类型。 - 渲染: 添加了
RenderCommand::ViewWorldQuery
关联类型。 - 渲染: 添加了
RenderContext::add_command_buffer
- 渲染: 添加了
RenderContext::begin_tracked_render_pass
。 - 渲染: 添加了
RenderContext::finish
- 渲染: 添加了
RenderContext::new
- 渲染: 添加了
SortedCameras
,它公开了以前对摄像机驱动节点内部的信息。 - 渲染: 添加了
try_add_node_edge
- 渲染: 添加了
try_add_slot_edge
- 渲染: 为
Color
添加了with_r
,with_g
,with_b
, 和with_a
。 - 渲染: 为 MSAA 添加了 2x 和 8x 样本数量。
- 渲染: 为派生
AsBindGroup
宏添加了#[storage(index)]
属性。 - 渲染: 添加了一个
EnvironmentMapLight
摄像机组件,它为场景添加额外的环境光。 - 渲染: 为
ScalingMode::WindowSize
添加了参数,用于指定一个世界单位等于多少像素。 - 渲染: 添加了圆柱体形状
- 渲染: 添加了示例
shaders/texture_binding_array
。 - 渲染: 添加了着色器验证的新功能。
- 渲染: 添加了可专门化的
BlitPipeline
,并将上采样节点移植到使用它。 - 渲染: 为 shape::Plane 添加了细分数字段
- 渲染: 为 PBR
StandardMaterial
添加了对加法和乘法混合模式的支持,通过AlphaMode::Add
和AlphaMode::Multiply
实现; - 渲染: 为 PBR 材质添加了对基于距离的雾化效果的支持,可以通过新的
FogSettings
组件,在每个摄像机中进行控制; - 渲染: 添加了对 KTX2
R8_SRGB
,R8_UNORM
,R8G8_SRGB
,R8G8_UNORM
,R8G8B8_SRGB
,R8G8B8_UNORM
格式的支持,通过将其转换为支持的 wgpu 格式来实现 - 渲染: 为 PBR
StandardMaterial
添加了对预乘 alpha 的支持,通过AlphaMode::Premultiplied
实现; - 渲染: 添加了使用可选过滤器进行
#[derive(ExtractComponent)]
的能力。 - 渲染: 添加了:
bevy_render::color::LchRepresentation
结构体 - 渲染: MaterialPipeline 的克隆实现
- 渲染: 为所有管道类型实现了
Clone
。 - 渲染: 动画之间的平滑过渡
- 支持可选环境变量
BEVY_ASSET_ROOT
,用于显式指定根资产目录。 - 任务: 为 TaskPool 添加线程创建/销毁回调
- 任务: 添加了
ThreadExecutor
,它只能在一个线程上被执行。 - 用于配置系统所属调度程序的扩展方法
in_schedule(label)
和on_startup()
。 - 变换: 添加了
GlobalTransform::reparented_to
- UI:
Size::new
现在是const
- UI: 为 bevy_ui 添加方法和默认 const
- UI: 为
Size
添加了all
,width
和height
函数。 - UI: 为
Text2dBundle
添加了Anchor
组件 - UI: 添加了
CalculatedSize::preserve_aspect_ratio
- UI: 为
Anchor
添加了Component
派生 - UI: 添加了
RelativeCursorPosition
,以及一个展示它的示例 - UI: 添加了
Text::with_linebreak_behaviour
- UI: 添加了
TextBundle::with_linebreak_behaviour
- UI: 为
TextBundle
添加了一个BackgroundColor
组件。 - UI: 为
TextBundle
添加了一个辅助方法with_background_color
。 - UI: 为
AlignContent
添加了SpaceEvenly
变体。 - UI: 为
AlignItems
,AlignSelf
,AlignContent
和JustifyContent
添加了Start
和End
变体。 - UI: 为
ExtractedUiNode
添加了flip_x
和flip_y
字段。 - 实用程序: 添加了
SyncCell::read
,它允许对已经实现Sync
特征的值进行共享访问。 - 实用程序: 添加了保护类型
bevy_utils::OnDrop
。 - 窗口: 添加
Windows::get_focused(_mut)
- 窗口: 将跨度添加到 winit 事件处理程序
- 窗口: macOS 上的透明窗口
- 窗口:
WindowDescriptor
重命名为Window
。 - 窗口: 为
WindowAttributes
添加了hittest
- 窗口: 添加了
Window::prevent_default_event_handling
。这允许 bevy 应用程序不覆盖热键上的默认浏览器行为,例如 F5、F12、Ctrl+R 等。 - 窗口: 添加了
WindowDescriptor.always_on_top
,它将窗口配置为始终保持在最上面。 - 窗口: 添加了一个示例
cargo run --example fallthrough
- 窗口: 添加了
hittest
的设置器/获取器 - 窗口: 修改了
WindowDescriptor
的Default
实现。 - 窗口: 修改了
WindowBuilder
更改 #
- 动画: 在另一个实体的子级或后代上具有另一个播放器的
AnimationPlayer
将不再运行。 - 动画: 动画采样现在使用来自
ComputeTaskPool
的线程完全多线程运行。 - 应用程序: 调整 dynamically_load_plugin 的路径类型
- 应用程序: 将 CorePlugin 分解为 TaskPoolPlugin、TypeRegistrationPlugin、FrameCountPlugin。
- 应用程序: 在 CoreStage::Last 中递增 FrameCount。
- App::run() 现在将在从 Plugin::build() 调用时引发恐慌
- 资产:
AssetIo::watch_path_for_changes
允许监视的路径和要重新加载的路径不同 - 资产: 将 HandleUntyped::id 设置为私有
- 音频:
AudioOutput
现在是一个Resource
。它不再是!Send
- 音频: AudioOutput 现在实际上是一个普通的资源,而不是一个不可发送的资源
- ECS:
.label(SystemLabel)
现在被称为.in_set(SystemSet)
- ECS:
App::add_default_labels
现在是App::add_default_sets
- ECS:
App::add_system_set
重命名为App::add_systems
- ECS:
Archetype
索引和Table
行已被新类型化为ArchetypeRow
和TableRow
。 - ECS:
ArchetypeGeneration
现在实现了Ord
和PartialOrd
。 - ECS:
bevy_pbr::add_clusters
不再是排他性系统 - ECS:
Bundle::get_components
现在接受FnMut(StorageType, OwningPtr)
。提供的存储类型必须与正在获取的组件的类型相匹配。 - ECS:
ChangeTrackers<T>
已被弃用。它将在 Bevy 0.11 中被移除。 - ECS:
Command
闭包不再需要实现标记特征std::marker::Sync
。 - ECS:
CoreStage
和StartupStage
枚举现在是CoreSet
和StartupSet
- ECS:
EntityMut::world_scope
现在允许从立即计算的闭包中返回值。 - ECS:
EntityMut
: 将remove_intersection
重命名为remove
,将remove
重命名为take
- ECS:
EventReader::clear
现在接受可变引用,而不是消耗事件读取器。 - ECS:
EventWriter::send_batch
仅在批次不为空时记录 TRACE 级别的日志。 - ECS: 为
Events<T>
添加了oldest_id
和get_event
方便方法。 - ECS:
OwningPtr::drop_as
现在将在调试版本中引发恐慌,如果指针未对齐。 - ECS:
OwningPtr::read
现在将在调试版本中引发恐慌,如果指针未对齐。 - ECS:
Ptr::deref
现在将在调试版本中引发恐慌,如果指针未对齐。 - ECS:
PtrMut::deref_mut
现在将在调试版本中引发恐慌,如果指针未对齐。 - ECS:
Query::par_for_each(_mut)
已更改为Query::par_iter(_mut)
,现在将根据当前的World
状态自动尝试为调用者生成批次大小。 - ECS:
RemovedComponents
现在在内部使用Events<RemovedComponentsEntity>
,而不是Events<Entity>
- ECS:
SceneSpawnerSystem
现在在CoreSet::Update
下运行,而不是CoreStage::PreUpdate.at_end()
。 - ECS:
StartupSet
现在是一个基础集合 - ECS:
System::default_labels
现在是System::default_system_sets
。 - ECS:
SystemLabel
特征已替换为SystemSet
- ECS:
SystemParamState::apply
现在除了提供的&mut World
之外,还接受&SystemMeta
参数。 - ECS:
SystemTypeIdLabel<T>
已替换为SystemSetType<T>
- ECS:
tick_global_task_pools_on_main_thread
不再作为排他性系统运行。相反,它已被tick_global_task_pools
替换,该系统使用NonSend
资源强制在主线程上运行。 - ECS:
Tick::is_older_than
已重命名为Tick::is_newer_than
。这不是功能性更改,因为尽管名称错误,但这始终是正在计算的内容。 - ECS:
UnsafeWorldCell::world
现在用于获取对整个世界的不可变访问,而不是仅仅获取元数据,现在可以通过UnsafeWorldCell::world_metadata
完成 - ECS:
World::init_non_send_resource
现在返回生成的ComponentId
。 - ECS:
World::init_resource
现在返回生成的ComponentId
。 - ECS:
World::iter_entities
现在返回一个EntityRef
迭代器,而不是Entity
。 - ECS:
World
现在最多只能包含 2^32 - 1 个表格。 - ECS:
World
现在最多只能包含 2^32 - 1 个原型。 - ECS:
WorldId
现在实现了SystemParam
,并将返回系统正在运行的世界的 ID。 - ECS: 如果没有找到带有
RenderApp
标签的子应用程序,添加渲染提取系统现在会引起恐慌,而不是默默地失败。 - ECS: 允许将系统添加到多个共享相同基集的集合中。
- ECS: 将
is_system_type() -> bool
更改为system_type() -> Option<TypeId>
- ECS: 将一些
UnsafeWorldCell
方法更改为采用self
而不是&self
/&mut self
,因为它们这样做实际上没有任何意义。 - ECS: 更改:
Query::for_each(_mut)
、QueryParIter
现在将利用自动矢量化来尽可能加快查询迭代速度。 - ECS: 在 wasm32 上默认使用 ExecutorKind::SingleThreaded。
- ECS: 确保
Query
不使用错误的World
。 - ECS: 独占系统现在可以与系统管道一起使用。
- ECS: 公开
ScheduleGraph
以供第三方工具使用。 - ECS: 将拓扑排序逻辑提取到一个新方法中,一次性检测循环并…
- ECS: 固定时间步长现在使用调度(
CoreSchedule::FixedTimeStep
)而不是运行标准。 - ECS: 对于断开连接,使用 Vec 而不是 HashSet 来减少插入开销。
- ECS: 为
WorldId
实现SparseSetIndex
。 - ECS: 改进调度构建错误的恐慌消息。
- ECS: 从
SystemParam
推导中取消 16 个字段的限制。 - ECS: 使
EntityRef::new
不安全。 - ECS: 使
Query
字段私有。 - ECS: 使
ScheduleGraph::initialize
公开。 - ECS: 使装箱条件只读。
- ECS: 使 RemovedComponents 镜像 EventReaders API 表面。
- ECS: 将 TableRow 和 TableId 标记为 repr(transparent)。
- ECS: 大多数返回
&UnsafeCell<ComponentTicks>
的 API 现在返回TickCells
,其中包含两个独立的&UnsafeCell<Tick>
用于任一组件刻度。 - ECS: 为无阶段迁移移动 MainThreadExecutor。
- ECS: 将
Query
中unsafe
块中的安全操作移出。 - ECS: 优化事件迭代器的
.nth()
和.last()
。 - ECS: 优化事件迭代器的
Iterator::count
。 - ECS: 提供公共
EntityRef::get_change_ticks_by_id
,它采用ComponentId
。 - ECS: 重构:将内部内容从
entity_ref
移动到World
,添加SAFETY
注释。 - ECS: 将
EntityId
重命名为EntityIndex
。 - ECS: 将
UnsafeWorldCellEntityRef
重命名为UnsafeEntityCell
。 - ECS: 将调度 v3 重命名为调度。
- ECS: 将 state_equals 条件重命名为 in_state。
- ECS: 在
bevy_ecs
crate 中用World::change_ticks
替换World::read_change_ticks
。 - ECS: 用
ReadOnlySystemParam
替换了 traitReadOnlySystemParamFetch
。 - ECS: 简化了
SystemParamFunction
和ExclusiveSystemParamFunction
trait。 - ECS: 通过更密集地存储命令来加快
CommandQueue
的速度。 - ECS: 无阶段:将最终应用移出生成的执行器。
- ECS: 无阶段:更漂亮的循环报告。
- ECS: 没有
Commands
和ParallelCommands
的系统在分析时将不再显示system_commands
跨度。 - ECS:
ReportHierarchyIssue
资源现在有一个公共构造函数(new
),并实现了PartialEq
。 - ECS:
StartupSchedule
标签现在定义为CoreSchedules
枚举的一部分。 - ECS:
SystemParam
推导现在更加灵活,允许您省略未使用的生命周期参数。 - ECS: 顶级
bevy_ecs::schedule
模块已被bevy_ecs::scheduling
替换。 - ECS: 使用
World
辅助方法来发送HierarchyEvent
。 - ECS: 在多线程执行器中使用有界通道。
- ECS: 为
set_if_neq
使用默认实现。 - ECS: 使用一致的名称为标记泛型。
- ECS: 为
NonSend
运行条件恐慌使用正确的术语。 - ECS: 为
IntoSystemConfig<>
使用默认实现的方法。 - ECS: 使用 try_send 来替换 send.await,无界通道应该始终 b…
- 通用:引擎的 MSRV 现在是 1.67。
- 输入:将 gilrs 版本提升至 0.10。
- IOS、Android... 同样的事情。
- 数学:将
glam
更新到0.23
。 - 数学:使用
Mul<f32>
来将Vec3
的值翻倍。 - 反射:bevy_reflect 现在对它的哈希器使用固定状态,这意味着
Reflect::reflect_hash
的输出现在在进程之间是确定性的。 - 反射:更改了
ReflectComponent
方法的函数签名,包括apply
、remove
、contains
和reflect
。 - 反射:更改了
List::push
和List::pop
以具有默认实现。 - 反射:在类型注册表中注册了
SmallVec<[Entity; 8]>
。 - 重命名了
GetPath
上的方法。path
->reflect_path
path_mut
->reflect_path_mut
get_path
->path
get_path_mut
->path_mut
- 渲染:允许在 webgl 中使用预处理。
- 渲染:bevy_pbr:避免在着色器中复制结构体和使用寄存器。
- 渲染:bevy_pbr:在填充每一帧之前清除 fog DynamicUniformBuffer。
- 渲染:bevy_render:在更新结束的独占系统中运行 calculate_bounds。
- 渲染:更改 glTF 加载器以使用
Camera3dBundle
。 - 渲染:将 &mut PipelineCache 更改为 &PipelineCache。
- 渲染:将 glTF 颜色解释为线性而不是 sRGB。
- 渲染:将“启动”资源
WgpuSettings
移动到RenderPlugin
中。 - 渲染:将预处理函数移动到 prepass_utils。
- 渲染:每个四边形仅计算一次精灵颜色。
- 渲染:仅在当前作用域接受行时才执行
#define
。 - 渲染:流水线渲染。
- 渲染:将 Globals 和 View 结构体重构到单独的着色器中。
- 渲染:用原子计数的 ID 替换基于 UUID 的 ID。
- 渲染:在渲染世界中运行清除跟踪器。
- 渲染:为 Mesh2d 设置剔除模式:None。
- 渲染:着色器定义现在可以具有值。
- 渲染:缩减 ComputedVisibility。
- 渲染:将阴影使用预处理着色器。
- 渲染:
add_node_edge
现在是不可出错的(错误时会引起恐慌)。 - 渲染:
add_slot_edge
现在是不可出错的(错误时会引起恐慌)。 - 渲染:
AsBindGroup
现在是对象安全的。 - 渲染:
BloomSettings::knee
重命名为BloomPrefilterSettings::softness
。 - 渲染:
BloomSettings::threshold
重命名为BloomPrefilterSettings::threshold
。 - 渲染:
HexColorError::Hex
已重命名为HexColorError::Char
。 - 渲染:
input_node
现在在None
时引起恐慌。 - 渲染:
ktx2
和zstd
现在是 bevy 的默认启用功能的一部分。 - 渲染:
Msaa
现在是枚举。 - 渲染:
PipelineCache
不再需要可变访问权限才能排队渲染/计算管道。 - 渲染:
RenderContext::command_encoder
现在是私有的。使用访问器RenderContext::command_encoder()
代替。 - 渲染:
RenderContext::render_device
现在是私有的。使用访问器RenderContext::render_device()
代替。 - 渲染:
RenderContext
现在支持添加外部CommandBuffer
,以便将其包含到渲染图中。这些缓冲区可以在渲染图之外(即在系统中)进行编码。 - 渲染:
scale
现在在更新area
之前应用。从中读取将考虑scale
。 - 渲染:
SkinnedMeshJoints::build
现在使用&mut BufferVec
而不是&mut Vec
作为参数。 - 渲染:
StandardMaterial
现在默认使用介电材料(0.0metallic
)和 0.5perceptual_roughness
。 - 渲染:
TrackedRenderPass
现在在构造时需要&RenderDevice
。 - 渲染:
Visibility
现在是枚举。 - 渲染:绽放效果现在看起来不同了。
- 渲染:定向光现在使用级联阴影贴图来提高阴影质量。
- 渲染:ExtractedMaterials、extract_materials 和 prepare_materials 现在是公开的。
- 渲染:出于性能原因,一些详细的渲染器跟踪日志现在需要使用 cargo 功能
detailed_trace
以及将日志级别设置为TRACE
才能显示。 - 渲染:使具有相同目标的摄像机共享相同的
main_texture
跟踪器,这确保了摄像机之间的连续性。 - 渲染:将
ScalingMode::Auto
重命名为ScalingMode::AutoMin
。 - 渲染:将
ScalingMode::None
重命名为ScalingMode::Fixed
。 - 渲染:将
window_origin
重命名为viewport_origin
。 - 渲染:将
Camera
上的priority
字段重命名为order
。 - 渲染:用单个
area: Rect
替换了left
、right
、bottom
和top
字段。 - 渲染:由于内部材料更改,标准材料在高粗糙度下现在会显得更亮,饱和度更高。这在物理上更正确。
- 渲染:
RenderPipelineDescriptor
和ComputePipelineDescriptor
的layout
字段现在是必须的。 - 渲染:
rangefinder
模块已移动到render_phase
模块中。 - 渲染:绽放示例已重命名为 bloom_3d 并改进。添加了 bloom_2d 示例。
- 渲染:子应用程序提取阶段已从运行子应用程序调度中分离出来。
- 渲染:为了使多个
RenderPhases
共享相同的TrackedRenderPass
,RenderPhase::render
签名已更改。 - 渲染:更新其
Transform
以便在父级更改后保留其GlobalTransform
。 - 渲染:更新到 wgpu 0.15、wgpu-hal 0.15.1 和 naga 0.11。
- 渲染:用户现在可以在 Windows 上使用 DirectX 着色器编译器 (DXC) 和 DX12 来实现更快的着色器编译和 ShaderModel 6.0+ 支持(需要
dxcompiler.dll
和dxil.dll
)。 - 渲染:您现在可以使用
RenderPhase::render
方法直接设置RenderPhase
的渲染代码,而不是在您的渲染图节点中手动实现它。 - 场景:
SceneSpawner::spawn_dynamic
现在返回InstanceId
而不是()
。 - 形状:将
From<Icosphere>
更改为TryFrom<Icosphere>
。 - 任务:
Scope
现在使用FallibleTask
来等待所有剩余任务在被丢弃时取消。 - 时间:
Time::set_relative_speed_fXX
现在允许相对速度为 -0.0。 - UI:
FocusPolicy
默认值已从FocusPolicy::Block
更改为FocusPolicy::Pass
。 - UI:
TextPipeline::queue_text
和GlyphBrush::compute_glyphs
现在需要一个 TextLineBreakBehaviour 参数,以便传递新的字段。 - UI:
update_image_calculated_size_system
为具有图像的节点将preserve_aspect_ratio
设置为 true。 - UI:已将
Changed<Node>
添加到text_system
的更改检测查询中。这确保了文本节点大小的任何更改都会导致其包含的任何文本重新计算。 - UI:更改了
Size::height
,以便它将width
设置为Val::AUTO
。 - UI:更改了
Size::width
,以便它将height
设置为Val::AUTO
。 - UI: 将 `TextAlignment` 改为枚举类型,包含 `Left`、`Center` 和 `Right` 选项。
- UI: 将 `extract_uinodes` 修改为从 UiImage 中提取 `flip_x` 和 `flip_y` 值。
- UI: 将 `prepare_uinodes` 修改为根据需要交换 UV 坐标。
- UI: 将 Taffy 版本升级至 0.3.3,并禁用其 `grid` 功能。
- UI: 将 `Size` 的 `width` 和 `height` 默认值更改为 `Val::Auto`。
- UI: 将 `CalculatedSize` 的 `size` 字段更改为 Vec2。
- UI: 将 UiImage 的解引用操作更改为纹理字段访问。
- UI: 将 UiImage 改为结构体,包含纹理、`flip_x` 和 `flip_y` 字段。
- UI: 修改了 `text2d` 示例,展示了两种换行行为。
- UI: 将 `image_node_system` 重命名为 `update_image_calculated_size_system`。
- UI: 将 `ExtractedUiNode` 的 `background_color` 字段重命名为 `color`。
- UI: 简化了 UI 示例。将数值替换为 Flex 属性枚举,或尽可能省略,并删除了剩余的自动边距使用。
- UI: `MeasureFunc` 仅在 `preserve_aspect_ratio` 为 true 时才保留纵横比。
- UI: 更新了 Taffy 0.3.3 的 `from_style`。
- UI: 升级至 Taffy 0.2,显著提升了 UI 布局性能,并添加了 flexbox `gap` 属性和 `AlignContent::SpaceEvenly`。
- UI: 使用 `f32::INFINITY` 代替 `f32::MAX` 来表示 Text2dBounds 中的无界文本。
- 窗口: 使用带缩放值的游标位置。
- 窗口: 将 WindowId::primary() 设为 const。
- 窗口: 恢复窗口关闭时的阶段更改。
- 窗口:
WindowId
现在是Entity
。 - 窗口: 将 `changed_window` 和 `despawn_window` 系统移至 `CoreStage::Last`,以避免系统在 `changed_window` 和帧结束之间对 `Window` 进行更改,因为这些更改会被忽略。
- 窗口: 最大化/最小化请求现在在 [
Window::state
] 字段上进行。 - 窗口: 将宽度/高度合并到
WindowResolution
组件中。
删除了 #
- App: 删除了
App::add_sub_app
。 - App: 重命名动态特性。
- ECS: 删除了 .on_update 方法,以提高 API 的一致性和清晰度。
- ECS: 从
WorldChildBuilder
中删除了BuildWorldChildren
的实现。 - ECS: 删除了
apply_state_transitions
中的重复查找。 - ECS: 删除了
NonSendMut
的ReadOnlySystemParam
的错误实现。 - ECS: 删除了 0.9 版本中已弃用的 API。
- ECS: 删除了事件迭代器上的错误
DoubleEndedIterator
实现。 - ECS: 从
Resource
初始化中删除了重复查找。 - ECS: 从
UnsafeWorldCell::fetch_table
中删除了对原型的不必要访问。 - ECS: 删除了
AddBundle
。Edges::get_add_bundle
现在返回Option<ArchetypeId>
。 - ECS: 删除了
Archetype::new
和Archetype::is_empty
。 - ECS: 删除了
ArchetypeComponentId::new
和ArchetypeComponentId::value
。 - ECS: 删除了
ArchetypeGeneration::value
。 - ECS: 删除了
ArchetypeId::new
和ArchetypeId::value
。 - ECS: 删除了
ArchetypeIdentity
。 - ECS: 删除了
Archetypes
的Default
实现。 - ECS: 删除了
AsSystemLabel
特性。 - ECS: 删除了
Entities::alloc_at_without_replacement
和AllocAtWithoutReplacement
。 - ECS: 删除了
Entities
的Default
实现。 - ECS: 删除了
EntityMeta
。 - ECS: 删除了
on_hierarchy_reports_enabled
运行条件(现在只使用特设资源检查运行条件)。 - ECS: 删除了
RunCriteriaLabel
。 - ECS: 删除了
RunCriteriaLabel
。 - ECS: 删除了
SystemParamFetch
,其功能已移至SystemParamState
。 - ECS: 删除了
Table::component_capacity
。 - ECS: 删除了
transform_propagate_system_set
:这是一种非标准模式,实际上没有提供足够的控制。这些系统已经是pub
:文档已更新以确保第三方使用清晰。 - ECS: 删除了
UnsafeWorldCell::storages
,因为这可能是不安全的,因为 storages 包含实际的组件/资源数据,而不仅仅是元数据。 - ECS: 删除了阶段,以及所有提到阶段的代码。
- ECS: 删除的状态已大幅简化,不再使用堆栈。
- ECS: 删除了
RenderSet/Stage::Extract
中的系统,如果它们没有从主世界读取数据,则不再发出警告。 - ECS: 删除了
Local<T>
用作ExclusiveSystemParam
时的约束T: Sync
。 - ECS: 删除了方法
ExclusiveSystemParamState::apply
。 - ECS: 删除了特性
ExclusiveSystemParamState
,将其功能合并到ExclusiveSystemParam
中。 - ECS: 删除了特性
SystemParamState
,将其功能合并到SystemParam
中。 - ECS: 支持使用 const 泛型的
SystemParam
类型。 - ECS: 使用 T::Storage::STORAGE_TYPE 来优化未使用的分支。
- 层次结构: 公开变换传播系统。
- 层次结构: 使添加子节点成为幂等的。
- 层次结构: 删除了
EntityCommands::add_children
。 - 输入: 游戏手柄事件重构。
- 反射: 使 bevy_reflect_derive 中的 proc 宏保持卫生。
- 反射: 删除了用于
Reflect
派生的#[module]
辅助属性(目前未使用)。 - 反射: 删除了
List
的超特性Array
。 - 反射: 删除了
PixelInfo
,并从 wgpu 中获取pixel_size
。 - 反射: 从大多数 glam 类型中删除了
ReflectSerialize
和ReflectDeserialize
注册。 - 删除了 HandleType 的不必要
Default
实现。 - 删除了由于误报导致的事件丢失的警告。
- 渲染: 使核心管道图节点公开。
- 渲染: 优化了 `prepare_uinodes` 中的颜色计算。
- 渲染: 将 scene_viewer 整理为插件,以便重用和组织。
- 渲染: 将
update_frusta::<Projection>
放入UpdateProjectionFrusta
集合中。 - 渲染: 删除了 pbr 函数对网格结构的依赖。
- 渲染: 删除了
render_resource_wrapper
中的潜在 UB。 - 渲染: 删除了冗余的按位或
TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES
。 - 渲染: 删除了提前退出,以确保预处理纹理被清除。
- 渲染: 在
extract_uinodes
中删除了对没有图像的节点的图像加载检查。 - 渲染: 删除了
prepare_asset
中为 Image 创建纹理的额外路径。 - 渲染: 删除了 fxaa 着色器中未使用的变量。
- 渲染: 将 AVAILABLE_STORAGE_BUFFER_BINDINGS 设置为实际可用的缓冲区数量。
- 渲染: 使用
Time
resource
代替提取Time
。 - 渲染: 在渲染系统中使用了更好的集合继承。
- 渲染: 对 alphamode::blend 使用 blendstate blend。
- 渲染: 直接使用 Image::default 创建 1 像素白色纹理。
- 渲染: 删除了
bevy_render::render_phase::DrawState
。它无法以任何形式在bevy_render
之外使用。 - 渲染: 删除了
BloomSettings::scale
。 - 渲染: 删除了
EntityPhaseItem
特性。 - 渲染: 删除了
ExtractedJoints
。 - 渲染: 删除了
SetShadowViewBindGroup
、queue_shadow_view_bind_group()
和LightMeta::shadow_view_bind_group
,转而重复使用预处理视图绑定组。 - 渲染: 删除了
render
特性组。 - 场景: 场景查看器: 可以从资产路径选择场景。
- 文本: 当超过
max_font_atlases
时,发出警告而不是错误。 - 变换: 删除了
GlobalTransform::translation_mut
。 - UI: 重新启用 taffy send+sync 断言。
- UI: 删除了
TextError::ExceedMaxTextAtlases(usize)
变量。 - UI: 删除了 ButtonBundle 的不必要手动默认实现。
- UI: 删除了
HorizontalAlign
和VerticalAlign
。 - UI: 删除了
ImageMode
。 - UI: 删除了
QueuedText
。 - UI: 从
ImageBundle
中删除了image_mode
字段。 - UI: 删除了
Val
<->f32
的转换,用于CalculatedSize
。 - 将 toml_edit 升级至 0.18。
- 将 tracing-chrome 依赖关系从 0.6.0 更新至 0.7.0。
- 窗口: 删除了不必要的 windows.rs 文件。
- 窗口: 删除了
window.always_on_top
,现在可以使用window.window_level
。 - 窗口: 删除了
ModifiesWindows
系统标签。
修复了 #
- 资产: 修复了 asset_debug_server 挂起问题。应该最多只有一个 ThreadExecut…
- 资产: 使用 debug_asset_server 修复了 load_internal_binary_asset。
- 资产: 为
LoadContext::read_asset_bytes
添加了热重载功能。 - 诊断: 控制台日志消息现在会显示何时启用了
trace_tracy
特性。 - ECS: 修复了
MutUntyped
的last_changed()
和set_last_changed()
。 - ECS: 修复了
#[derive(SystemParam)]
的编译错误。 - ECS: 修复了
get_unchecked_manual
使用原型索引而不是表行的问题。 - ECS: 修复了
#[derive(SystemParam)]
中忽略的生命周期。 - ECS: 修复了
init_non_send_resource
覆盖之前值的问题。 - ECS: 修复了如果
WorldCell
已经被借用,则可变别名会存在很短时间的问题。 - ECS: 修复了部分消耗的
QueryIter
和QueryCombinationIter
具有无效的size_hint
的问题。 - ECS: 修复了 PipeSystem 在使用独占系统时出现恐慌的问题。
- ECS: 修复了
World: Send
的健全性错误。如果在错误的线程上丢弃包含!Send
资源的World
,现在会引发恐慌。 - ECS: 修复了稀疏更改检测。
- ECS: 修复了运行条件的特性约束。
- ECS: 修复了
insert
、remove
和despawn
的健全性问题。 - ECS: 修复了
EntityMut::world_scope
的健全性问题。 - ECS: 修复了
DetectChanges::last_changed
返回错误值的问题。 - ECS: 修复了
DetectChangesMut::set_last_changed
实际上没有更新changed
标记的问题。 - ECS: 修复了
Res
和Query
参数永远不会相互排斥的问题。 - ECS: 修复了导致
#[derive(SystemParam)]
泄露私有字段类型的错误。 - ECS: schedule_v3: 修复了未应用于系统的默认集合。
- ECS: 无阶段: 关闭完成通道,以防止执行器死锁。
- ECS: 无阶段: 修复了未应用的系统。
- 层次结构: 当事件类型未注册时,不要在发送 HierarchyEvents 时出错。
- 层次结构: 修复了
propagate_recursive
的健全性问题。 - 层次结构: 修复了缺少
ChildAdded
事件的问题。 - 输入: 避免触发对输入的更改检测。
- 输入: 修复了
AxisSettings::new
只接受无效边界的错误。 - 输入: 修复了
Input<GamepadButton>
中just_pressed
和just_released
的错误行为。 - 输入: 删除了移动触摸事件的 y 轴翻转。
- 反射: bevy_reflect: 修复了位置错误的实现。
- 反射: 修复了对非自描述格式进行反序列化时,单位结构体反序列化会失败的错误。
- 反射: 修复了使用某些读取器进行场景反序列化时可能失败的错误(例如
BufReader
、File
等)。 - 反射: 修复了 bevy_reflect::impls::std 中的拼写错误,用于为类似…的向量获取 TypeRegistration。
- 反射: 在缩短类型名称时,在
>
、)
或括号后面保留::
。 - 渲染: bevy_core_pipeline: 修复了预处理排序顺序。
- 渲染: 摄像机缩放集群修复。
- 渲染: 修复了渲染计划中的歧义。
- 渲染: 修复了 bloom 视口。
- 渲染: 修复了阴影映射对可选
PrepassPlugin
的依赖关系。 - 渲染: 修复了
texture_binding_array
示例中的特性门控。 - 渲染: 修复了
global_vs_local_translation
示例中材质的alpha_mode
。 - 渲染: 修复了着色器定义的正则表达式: 必须至少有一个空格。
- 渲染: 修复了
shader_instancing
。 - 渲染: 再次修复了 spot dir nan。
- 渲染: 如果视图制服缓冲区已更改,则重新创建色调映射绑定组。
- 渲染: 阴影渲染阶段 - 传递正确的视图实体。
- 渲染: Text2d 在文本边界发生更改时不会重新计算文本。
- 渲染: wasm: 在 2D 中也填充全局制服。
- 渲染: 发射强度现在被
StandardMaterial
正确地解释为线性而不是 sRGB。 - 渲染: 修复了非 HDR 管道的去带抖动强度。
- 渲染: 修复了
StandardMaterial
闭塞错误地应用于直接照明的错误。 - 渲染: 修复了
bevy_render::texture::Image::from_dynamic()
中image::DynamicImage::ImageRgb32F
的 alpha 通道到bevy_render::texture::Image
转换的问题。 - 场景: 在构建之前清理动态场景。
- 任务: 修复了在另一个范围上出现恐慌的问题。
- UI:
Size::height
设置了width
而不是height
。 - UI: 不要忽略文本的 UI 缩放比例。
- UI: 修复
bevy_ui
在没有bevy_text
的情况下编译错误 - UI: 修复图像的溢出缩放
- UI: 修复
upsert_leaf
没有为新叶节点设置MeasureFunc
的问题 - 窗口: 在所有模式下应用
WindowDescriptor
设置 - 窗口: 移动光标时打破反馈循环
- 窗口: 尽快创建窗口
- 窗口: 修复
Window::set_minimized
中的拼写错误 - 窗口: 修复在
desktop_app
模式下关闭窗口不会退出应用程序的问题 - 窗口: 修复光标抓取问题
- 窗口: 修复
set_cursor_grab_mode
在出现错误之前尝试其他模式的问题