Bevy 0.19
摘要
Bevy 0.19 是 Rust 游戏引擎的一个重要更新,引入了下一代场景(BSN 格式)、通过更多 GPU 工作实现更快的渲染、接触阴影、新的 UI 组件、文本输入支持、后处理效果等等。
<p><a href="https://lobste.rs/s/k5raot/bevy_0_19">评论</a></p>
查看缓存全文
缓存时间: 2026/06/20 14:31
# Bevy 0.19 来源: https://bevy.org/news/bevy-0-19/ 感谢 **261 位贡献者**、**1185 个拉取请求**、社区审查者以及我们的 **慷慨捐赠者** (https://bevy.org/donate),我们很高兴宣布 **Bevy 0.19** 版本已上线 crates.io (https://crates.io/crates/bevy)!对于不了解 Bevy 的朋友来说,它是一个用 Rust 编写的、令人耳目一新的数据驱动游戏引擎。你可以查看我们的快速入门指南 (https://bevy.org/learn/quick-start) 立即尝试。它永远免费且开源!你可以在 GitHub 上获取完整源代码 (https://github.com/bevyengine/bevy)。查看 Bevy Assets (https://bevy.org/assets) 获取社区开发的插件、游戏和学习资源合集。要将现有的 Bevy App 或插件更新到 **Bevy 0.19**,请查看我们的 0.18 到 0.19 迁移指南 (https://bevy.org/learn/migration-guides/0-18-to-0-19/)。自上次发布几个月以来,我们添加了大量新功能、错误修复和生活质量改进,以下是一些亮点: - **下一代场景**: 我们全新、大幅改进的 Bevy 场景系统终于落地了!通过 `bsn!` 宏在代码中(或在未来版本中通过资源文件)以我们新的 BSN(Bevy Scene Notation)格式定义场景。场景可组合、可修补且具有依赖感知能力。不再需要手动拉取生成某个实体所需的所有 ECS 和资源依赖! - **更快渲染更大场景**: 我们将更多工作转移到 GPU,并在多个领域优化了渲染器。Bevy 可以绘制更多东西,而且更快! - **接触阴影**: 阴影质量对你的游戏“精致度”影响巨大。Bevy 0.19 新增了接触阴影,在不付出完整光线追踪代价的情况下显著提升阴影细节。 - **更多 Feathers 控件**: Bevy 偏好的“编辑器工具”控件集合获得了大量新控件。它还被移植到了 BSN,使用起来更加愉快! - **文本输入**: Bevy UI *终于*通过新的 `EditableText` 组件获得了对文本输入的上游支持。 - **富文本**: Bevy 现在拥有更灵活的字体选择,支持“字体族”和可变字体属性等高级功能。 - **应用设置**: 我们添加了官方的“应用设置”框架,可以从文件加载和保存设置,并将其暴露为 ECS 资源。 - **后处理特效**: 我们添加了内置的“暗角”和“镜头畸变”后处理特效。 - **改进的蒙皮网格剔除**: 蒙皮网格现在在剔除时可以考虑它们的动画。 ## 下一代场景 # (https://bevy.org/news/bevy-0-19/#next-generation-scenes) **Bevy 0.19** 引入了我们全新、大幅改进的 Bevy 场景系统。我们已经为此工作了 *很长时间*(好几年了!),很高兴终于将其交到 Bevy 开发者手中。它使得在代码中(以及最终在即将推出的 Bevy Editor 生成的资源中)定义场景变得更加美好。它还将被用来 *构建* 即将到来的 Bevy Editor! ### BSN(Bevy Scene Notation) # (https://bevy.org/news/bevy-0-19/#bsn-bevy-scene-notation) BSN 是一种类似 Rust 的优雅场景语法,既可以在 Rust 代码中通过 `bsn!` (https://docs.rs/bevy_scene/0.19.0-rc.3/bevy_scene/macro.bsn.html) 宏定义,也可以在 `.bsn` 资源文件中使用。如果你曾经对在 Bevy 中生成复杂实体集合的冗长和复杂感到困扰,你可能会喜欢 BSN 所提供的。BSN 可用于在 ECS 中生成任何东西。这适用于所有场景,但值得特别指出的是,这使得 Bevy UI 代码的读写变得显著简单。一些快速说明:虽然 **Bevy 0.19** 技术上支持场景资源,但我们还没有发布官方的 `.bsn` 资源加载器。此次发布专注于代码驱动的工作流,我们计划在未来版本中推出资源驱动的工作流。此外,BSN 还是新鲜出炉的,我们可能需要几个版本来完善体验。它现在已经很实用了,但请期待一些粗糙的边缘和缺失的功能。在 Rust 中,`bsn!` (https://docs.rs/bevy_scene/0.19.0-rc.3/bevy_scene/macro.bsn.html) 表达式本质上是一个要添加到实体上的组件列表: `` bsn! { Player { score: 0 } Team::Blue } `` 到目前为止,这看起来和行为类似于 Bevy 现有的 `Bundle` (https://docs.rs/bevy/0.19.0-rc.3/bevy/ecs/bundle/trait.Bundle.html)(它*只是*组件的集合)。但是 BSN 拥有更多超能力! **点击此处查看 BSN 的所有功能!** ### 可选字段 # (https://bevy.org/news/bevy-0-19/#optional-fields) 在 BSN 中,你不需要指定每个字段,也不需要 `..Default::default()`。你只需要设置你关心的字段,其余字段将采用它们的默认值: `` #[derive(Component, Default, Clone)] struct Player { score: usize, coins: usize, } bsn! { Player { score: 0 } } `` 你也可以只写类型名称,如果你希望所有字段都取默认值: `` bsn! { Player } `` 字段值可以通过 `{}` 语法使用任意 Rust 表达式: `` bsn! { Player { score: {current_points + 10} } } `` ### BSN 关系 # (https://bevy.org/news/bevy-0-19/#bsn-relationships) BSN 对 ECS 关系提供了一流支持。你可以内联生成相关实体(如子实体): `` bsn! { Player Children [ Sword, Shield, ] } `` 这也适用于自定义关系: `` bsn! { Player Inventory [ Apple, Potion, ] } `` ### 场景函数 # (https://bevy.org/news/bevy-0-19/#scene-functions) `bsn!` (https://docs.rs/bevy_scene/0.19.0-rc.3/bevy_scene/macro.bsn.html) 返回一个实现了 `Scene` (https://docs.rs/bevy/0.19.0-rc.3/bevy/prelude/trait.Scene.html) trait 的类型,这意味着你可以像这样定义可复用的 BSN 函数: `` fn player() -> impl Scene { bsn! { Player Children [ Sword, Shield ] } } `` 这些函数可以接受并使用参数: `` fn player(name: &str) -> impl Scene { bsn! { Name(name) Player } } `` ### 场景是可组合的补丁 # (https://bevy.org/news/bevy-0-19/#scenes-are-composable-patches) BSN 表达式是一个“补丁”;它不会写入所定义每个类型的“完整”实例。这意味着你可以将场景层层叠放: `` fn button() -> impl Scene { bsn! { Button Node { width: px(100) } } } fn my_button() -> impl Scene { bsn! { button() Node { height: px(100) } } } `` `my_button` 将生成一个包含 `Node { width: px(100), height: px(100) }` 组件的实体。场景中的组件初始化为其默认值,每层额外的场景在其默认值之上写入自己的字段。 ### 场景资源和缓存 # (https://bevy.org/news/bevy-0-19/#scene-assets-and-caching) 虽然 **Bevy 0.19** 没有附带官方的 `.bsn` 资源加载器,但它*确实*已经功能上支持场景资源依赖。只是我们还没有包含任何内置的加载器: `` commands.queue_spawn_scene(bsn! { :"player.bsn" Transform { translation: Vec3 { x: 10. } } }) `` 这个(如果有 `.bsn` 资源加载器)将生成一个包含 `"player.bsn"` 场景资源并修补“x 位置”为 `10` 的场景。BSN 具有依赖感知能力:如果你使用 `queue_spawn_scene` 而不是 `spawn_scene`,它将等待所有依赖加载完成后再生成场景。`spawn_scene` 总是会立即尝试生成场景……如果它依赖的场景资源尚未加载,则会失败。另外注意 `:`,这是“缓存”语法。首次加载时,它将解析 `"player.bsn"` 场景并缓存结果以供重用。这使得生成场景的多个实例更加便宜,因为它只需要解析缓存的场景“之上”的内容。我们正在 (https://github.com/bevyengine/bevy/pull/23576) 开发一个官方的 `.bsn` 资源加载器,并且还计划将 Bevy 的 glTF 加载器移植到新的场景系统(这样你就可以像依赖 `my_scene.bsn` 文件一样依赖 `"my_scene.gltf"`)。`bsn!` 宏和生成系统已经支持场景资源,所以如果你喜欢冒险,可以在等待我们的官方格式时尝试实现自己的 Bevy 场景资源格式! ### 场景列表 # (https://bevy.org/news/bevy-0-19/#scene-lists) `bsn!` (https://docs.rs/bevy_scene/0.19.0-rc.3/bevy_scene/macro.bsn.html) / `Scene` (https://docs.rs/bevy/0.19.0-rc.3/bevy/prelude/trait.Scene.html) 对应于单个实体。`bsn_list!` (https://docs.rs/bevy/0.19.0-rc.3/bevy/prelude/macro.bsn_list.html) / `SceneList` (https://docs.rs/bevy/0.19.0-rc.3/bevy/prelude/trait.SceneList.html) 是相同的概念,但应用于实体列表: `` fn players() -> impl SceneList { bsn_list! [ (#Player1 Team::Blue), (#Player2 Team::Red), ] } `` `bsn_list!` (https://docs.rs/bevy/0.19.0-rc.3/bevy/prelude/macro.bsn_list.html) 中的实体用逗号分隔,用于视觉上指示实体边界的括号是可选的: `` fn players() -> impl SceneList { bsn_list! [ #Player1 Team::Blue, #Player2 Team::Red, ] } `` 上面看到的“BSN 关系语法”(例如:`Children []`)使用了 `SceneList` (https://docs.rs/bevy/0.19.0-rc.3/bevy/prelude/trait.SceneList.html)。这意味着你可以将场景列表作为参数传递给场景: `` fn widget(children: impl SceneList) -> impl Scene { bsn! { Widget Children [ {children} ] } } `` ### 观察事件 # (https://bevy.org/news/bevy-0-19/#observing-events) `bsn!` (https://docs.rs/bevy_scene/0.19.0-rc.3/bevy_scene/macro.bsn.html) 实体可以轻松观察事件,从而很容易在场景中嵌入“回调式”行为: `` fn button() -> impl Scene { bsn! { Node { width: px(100), height: px(50) } on(|press: On<Pressed>| { info!("button pressed!") }) } } `` ### 模板 # (https://bevy.org/news/bevy-0-19/#templates) BSN 表达式实际上为组件定义了“模板”,而不是组件本身。`Template` (https://docs.rs/bevy/0.19.0-rc.3/bevy/ecs/prelude/trait.Template.html) 本质上是一个类型的特殊构造器,它产生一个输出类型(如 Component)。关键的是,`Template` (https://docs.rs/bevy/0.19.0-rc.3/bevy/ecs/prelude/trait.Template.html) 可以访问 `World` (https://docs.rs/bevy/0.19.0-rc.3/bevy/ecs/prelude/struct.World.html)、当前实体以及“场景生成上下文”。这实现了强大的行为,例如从给定资源路径加载资源并生成资源句柄(例如 `Handle<Image>`)。旧的通过 Bundle 生成的方法需要将每个 ECS 依赖传入 bundle 函数,并手动使用该依赖生成最终值: `` fn player(asset_server: &AssetServer) -> impl Bundle { ( Player { score: 10, ..Default::default() }, children! [ Sprite { image: asset_server.load("player.png"), ..Default::default() } ] ) } fn setup(mut commands: Commands, asset_server: Res<AssetServer>) { commands.spawn(player(&asset_server)) } `` 当生成具有许多依赖的复杂嵌套场景时,这会变得*相当*糟糕。BSN 使这一切变得简单得多: `` fn player() -> impl Scene { bsn! { Player { score: 10 } Children [ Sprite { image: "player.png" } ] } } fn setup(mut commands: Commands) { commands.spawn_scene(player()); } `` 生成场景不再需要知道每个内部所需的小依赖,常见的操作如通过路径加载和分配资源变得简单!这确实意味着 BSN 要求类型具有 `Template` (https://docs.rs/bevy/0.19.0-rc.3/bevy/ecs/prelude/trait.Template.html)。这是通过 `FromTemplate` (https://docs.rs/bevy/0.19.0-rc.3/bevy/ecs/prelude/trait.FromTemplate.html) trait 实现的,它告诉 BSN 对于给定的 `Component` (https://docs.rs/bevy/0.19.0-rc.3/bevy/ecs/component/trait.Component.html) 应该使用哪个 `Template` (https://docs.rs/bevy/0.19.0-rc.3/bevy/ecs/prelude/trait.Template.html) 类型。`FromTemplate` (https://docs.rs/bevy/0.19.0-rc.3/bevy/ecs/prelude/trait.FromTemplate.html) 可以被派生,这将为你的类型生成一个 `Template` (https://docs.rs/bevy/0.19.0-rc.3/bevy/ecs/prelude/trait.Template.html) 类型。幸运的是,大多数类型*不需要*手动派生或实现 `FromTemplate` (https://docs.rs/bevy/0.19.0-rc.3/bevy/ecs/prelude/trait.FromTemplate.html)。这是因为 `FromTemplate` (https://docs.rs/bevy/0.19.0-rc.3/bevy/ecs/prelude/trait.FromTemplate.html) 和 `Template` (https://docs.rs/bevy/0.19.0-rc.3/bevy/ecs/prelude/trait.Template.html) 会自动为每个实现了 `Default` 和 `Clone` 的类型实现。这些类型是“自身的模板”并且只是“直接传递”。你只需要在需要模板特性时派生 `FromTemplate` (https://docs.rs/bevy/0.19.0-rc.3/bevy/ecs/prelude/trait.FromTemplate.html)(例如上面的 `Sprite` (https://docs.rs/bevy/0.19.0-rc.3/bevy/prelude/struct.Sprite.html) 用例,它使用 `Handle<Image>` 模板接受 `"player.png"`)。 ### 内联资源模板 # (https://bevy.org/news/bevy-0-19/#inline-asset-templates) BSN 通过 `asset_value` 模板支持“内联资源”: `` fn cube() -> impl Scene { bsn! { Mesh3d(asset_value(Cuboid::new(1., 1., 1.))) } } `` 与之前需要做的相比! `` fn setup(meshes: Res<Assets<Mesh>>) -> impl Bundle { let handle = meshes.add(Cuboid::new(1., 1., 1.)); Mesh3d(handle) } `` ### 实体引用语法 # (https://bevy.org/news/bevy-0-19/#entity-reference-syntax) BSN 有特殊的“实体引用语法”来定义实体的 `Name` (https://docs.rs/bevy/0.19.0-rc.3/bevy/ecs/name/struct.Name.html) 组件: `` bsn! { #FirstPlayer Player } `` 这基本上等同于: `` bsn! { Name("FirstPlayer") Player } `` 然而“实体引用语法”还允许在场景的其他地方引用该实体: `` #[derive(Component, FromTemplate)] struct Reference(Entity); bsn! { #Root Children [ Reference(#Root) ] } `` 你可以访问给定 `bsn! {}` 作用域中定义的*任何*实体引用,在该作用域的任何其他地方: `` bsn! { References { child: #Child, grandchild: #Grandchild, } Children [ #Child Children [ #Grandchild ] ] } `` 在 `bsn_list!` (https://docs.rs/bevy/0.19.0-rc.3/bevy/prelude/macro.bsn_list.html) 的上下文中,这启用了定义图结构: `` bsn_list! [ (#A PointsTo(#B)), (#B PointsTo(#A)), ] `` ### 隐式 Into # (https://bevy.org/news/bevy-0-19/#implicit-into) 大多数处于“字段位置”的值支持“隐式 `.into()`”。这意味着可以转换为其他类型的类型通常可以跳过手动转换: `` #[derive(Component, Default, Clone)] struct Foo(String); bsn! { Foo("hello") } `` 这是因为 `"hello"` 是 `&str`,有 `Into<String>` 实现。这在定义 Bevy UI 值时尤其好: `` // 原始 Rust Node { border: UiRect::all(Val::Px(2.0)), ..Default::default() } // BSN Node { border: px(2) } `` `px(2)` 只是一个产生 `Val::Px(2.0)` 的函数,而 `UiRect` 有 `From<Val>` 的实现,它会产生 `UiRect::all`(将值写入所有四个边框“侧”)。这里的语法在易用性上可以与 CSS 竞争,但它是完全静态类型的,并且源自普通的 Rust trait 转换(这些不是特例/硬编码的)。这意味着你可以构建自己的! ### 场景组件 # (https://bevy.org/news/bevy-0-19/#scene-components) 几乎已成为 Bevy 开发者必经的历程:定义一个类似 `Player` 的组件,该组件具有依赖于某个更大“场景”的复杂行为,然后问诸如“我如何一起生成这些?”以及“我如何编写可以安全地假设整个场景存在的代码?”之类的问题。Bevy 开发者已经以各种创造性的方式解决了这些问题,但一直没有一个简单推荐/惯用的上游解决方案。BSN 通过将 `Scene` (https://docs.rs/bevy/0.19.0-rc.3/bevy/prelude/trait.Scene.html) 与 `Component` (https://docs.rs/bevy/0.19.0-rc.3/bevy/ecs/component/trait.Component.html) 关联起来解决了这个问题。
相似文章
虚拟Bevy Meetup 13 录像现已上传至YouTube
Bevy Meetup #13 的录像现已在 YouTube 上提供,内容包括关于 bevy_ui 中的 VFX 编辑器、Bevy 在 iOS 上运行以及使用 Unbug 进行符合人体工学的运行时断言的演讲。
Blaise v0.10.0:本地后端、线程与增量编译
Blaise v0.10.0 通过 QBE 增加了本地后端支持、线程功能和增量编译,推动这款现代 Object Pascal 编译器向自托管和更广泛的平台支持迈进。
@0xSero: Qwen3.6-28B-REAP - BF16 (56GB)/4bit (14GB) 构建了一个地铁射击游戏 (vllm-studio),每会话150 tok/s。相对…
Qwen3.6-28B-REAP,一个全新的28B参数模型变体,已发布BF16(56GB)和4位(14GB)版本,能够使用vllm-studio以每会话150 tok/s的速度构建一个地铁射击游戏。
Bitsy
Bitsy 是一款小巧的游戏引擎,用于创建小型游戏、世界和故事。它提供了基于网页的编辑器和社区资源。
Show HN: 我花了一个周末用Rust重写了IDE中我唯一使用的部分
Kyde 是一个快速的原生Git客户端和代码编辑器,使用Rust基于Zed的gpui框架构建,具有GPU渲染、并排差异对比、tree-sitter语法高亮以及一个精心调校的深色主题。