主要用 有道 翻译。
If you came here because you wanted to learn how to make 2D / 3D games, visualizations, user interfaces, or other graphical applications with Bevy ... you came to the right place! If not, stick around anyway. I promise it will be fun.
如果你来这里是因为你想学习如何用Bevy制作2D / 3D游戏、可视化、用户界面或其他图形应用程序……你来对地方了!如果没有,那还是留下来吧。我保证会很有趣。
what's a bevy?
A bevy is a group of birds!? ? ?bevy就是一群鸟!
But Bevy is also a refreshingly simple data-driven game engine built in Rust. It is?free and open-source?forever.
但Bevy也是一个用Rust构建的简单数据驱动的游戏引擎。它永远是免费和开源的。
Bevy has the following design goals:
Bevy的设计目标如下:
Bevy is?built in the open by volunteers?using the?Rust programming language. The code is free and open-source because we believe developers should fully own their tools. Games are a huge part of our culture and humanity is investing?millions?of hours into the development of games. Why are we continuing to build up the ecosystems of closed-source monopolies that take cuts of our sales and deny us visibility into the tech we use daily? We believe that the developer community can do so much better.
Bevy是由志愿者使用Rust编程语言公开构建的。代码是免费和开源的,因为我们相信开发人员应该完全拥有他们的工具。游戏是我们文化的重要组成部分,人类在游戏开发中投入了大量时间。为什么我们要继续建立封闭源垄断的生态系统,这些生态系统会削减我们的销售额,并让我们无法了解日常使用的技术?我们相信开发者社区可以做得更好。
For a more in-depth introduction, check out the?Introducing Bevy?blog post.
要了解更深入的介绍,请查看介绍Bevy博客文章。
Bevy is still in the early stages of development. Important features are missing. Documentation is sparse. A new version of Bevy containing breaking changes to the API is released?approximately once every 3 months. We provide?migration guides, but we can't guarantee migrations will always be easy. Use only if you are willing to work in this environment.
Bevy仍处于开发的早期阶段。缺少重要的功能。文档很少。Bevy的新版本包含对API的重大更改,大约每3个月发布一次。我们提供了迁移指南,但我们不能保证迁移总是很容易。只有当你愿意在这种环境中工作时才使用。
If you are currently trying to pick an engine for your Next Big Project?, we recommend that you check out?Godot Engine. It is currently much more feature-complete and stable. And it is also free, open-source, and?scriptable with Rust!
如果您目前正在尝试为您的Next Big Project?选择一个引擎,我们建议您选择Godot engine。它目前的功能更加完整和稳定。它也是免费的、开源的,并且可以用Rust编写脚本!
This official book is still very incomplete. It will help you get started with the setup and learning the basics, but it does not yet cover most of Bevy's features. See the?Next Steps?page for links to other, more exhaustive, learning resources you can use.
这本正式的书还很不完整。它将帮助您开始设置和学习基础知识,但它还没有涵盖Bevy的大部分功能。请参阅Next Steps页面,以获得可以使用的其他更详尽的学习资源的链接。
Phew! If you haven't been scared away yet, let's move on to learning some Bevy!
唷!如果你还没有被吓走,让我们继续学习一些贝弗!
This section will help you get started on your Bevy journey as quickly as possible. It will walk you through setting up your development environment and writing a simple Bevy app.
本节将帮助您尽快开始您的Bevy之旅。它将引导您设置开发环境并编写一个简单的Bevy应用程序。
If you want to dive in immediately and you already have a working Rust setup, feel free to follow this "quick start" guide. Otherwise, move on to the next page.
如果你想立即开始,并且你已经有了一个可以工作的Rust设置,请随意遵循这个“快速开始”指南。否则,转到下一页。
Note: the "fast compiles" setup is on the next page, so you might want to read that section first.
注意:“快速编译”设置在下一页,因此您可能需要先阅读该部分。
Clone the?Bevy repo:? ? ?克隆Bevy代码库:
gitclone https://github.com/bevyengine/bevy
Navigate to the new "bevy" folder? ? ?导航到新的“bevy”文件夹
cd bevy
Switch to the correct Bevy version (as the default is the git main development branch) 切换到正确的Bevy版本(默认是git主开发分支)
#use the latest Bevy release # 使用最新的Bevy版本
git checkout latest # 签出最新
#or a specific version # 或者一个特定的版本
git checkout v0.12.1 # 当前最新版本
Try the examples in the?examples folder? ? ? 尝试示例文件夹中的示例
cargo run --example breakout
Bevy is?available as a library on crates.io.
Bevy是一个库,可以在crate .io上找到。
The easiest way to add it to your project is to use?cargo add
:
将其添加到项目中最简单的方法是使用cargo add:
cargo add bevy
Alternatively, you can manually add it to your project's Cargo.toml like this:
或者,您可以手动将其添加到项目的Cargo.toml 中,象这样:
# 依赖关系
[dependencies]
bevy = "0.12" # make sure this is the latest version # 确保这是最新版本
Make sure to use the latest?bevy
?crate version
确保使用最新版本?bevy
crate ( Crate版本 0.12.1)
I know you are itching to start making games, but we need to do a?small?amount of setup first.
我知道你渴望开始制作游戏,但我们需要先做一些准备工作。
All Bevy app and engine code is written in Rust. This means that before we begin, we need to set up our Rust development environment.
所有Bevy应用程序和引擎代码都是用Rust编写的。这意味着在开始之前,我们需要设置Rust开发环境。
Bevy relies heavily on improvements in the Rust language and compiler. As a result, the Minimum Supported Rust Version (MSRV) is "the latest stable release" of Rust.
Bevy在很大程度上依赖于Rust语言和编译器的改进。因此,最小支持Rust版本(MSRV)是Rust的“最新稳定版本”。
Install Rust by following the?Rust Getting Started Guide.
按照Rust入门指南安装Rust。
Once this is done, you should have the?rustc
?compiler and the?cargo
?build system installed in your path.
完成此操作后,您应该在路径中安装了rustc编译器和cargo构建系统。
Follow the instructions at?Linux Dependencies?
按照Linux Dependencies中的说明进行操作
Desktop development with C++
?workload in the installer.? ? ? ? 为了便于安装,请在安装程序中选择使用C++工作负载的桌面开发。Individual components.? ??
在安装程序中,导航到Individual components 单个组件
MSVC
?for your architecture and version of Windows? ? 选择最新的 适用于您的体系结构和Windows版本的MSVC
Windows SDK
?for your version of Windows 用于您的Windows版本Windows SDK
?for your version of Windows? ? ?选择用于Windows组件的C++CMake工具Install the Xcode command line tools with?xcode-select --install
?or the?Xcode app
使用Xcode select--Install或Xcode应用程序安装Xcode命令行工具
You can use any code editor you want, but we highly recommend one that has a?rust-analyzer?plugin. It's still in development, but it already provides top-tier autocomplete and code intelligence.?Visual Studio Code?has an officially supported?rust-analyzer extension.
您可以使用任何您想要的代码编辑器,但我们强烈建议使用带有rust-analyzer rust分析器插件的代码编辑器。它仍在开发中,但它已经提供了顶级的自动补全和代码智能。Visual Studio Code有一个官方支持的rust分析器扩展。
The goal of this book is to learn Bevy, so it won't serve as a full Rust education. If you would like to learn more about the Rust language, check out the following resources:
这本书的目标是学习Bevy,所以它不会作为一个完整的Rust教育。如果您想了解更多关于Rust语言的信息,请查看以下资源:
Now we are ready to set up a Bevy project! Bevy is just a normal Rust dependency. You can either add it to an existing Rust project or create a new one. For completeness we will assume you are starting from scratch.
现在我们已经准备好创建一个Bevy项目了!Bevy只是一个普通的Rust依赖项。您可以将它添加到现有的Rust项目中,也可以创建一个新项目。为了完整起见,我们将假设您从头开始。
First, navigate to a folder where you want to create your new project. Then, run the following command to create a new folder containing our rust executable project:
首先,导航到要在其中创建新项目的文件夹。然后,运行以下命令创建一个包含rust可执行项目的新文件夹:
cargo new my_bevy_game
cd my_bevy_game
Now run?cargo run
?to build and run your project. You should see?Hello, world!
?printed to your terminal. Open the?my_bevy_game
?folder in your code editor of choice and take some time to look through the files.
现在运行cargo run来构建和运行项目。你应该看看Hello, world!打印到您的终端。在您选择的代码编辑器中打开my_bevy_game文件夹,并花一些时间查看这些文件。
main.rs
?is the entry point of your program:? ? ? ? ? ?main.rs
?是程序的入口点:
fn main() {
println!("Hello, world!");
}
Cargo.toml
?is your "project file". It contains metadata about your project such as its name, dependencies, and build configuration.
Cargo.toml
?是你的“project file 项目文件”。它包含有关项目的元数据,例如项目的名称、依赖项和构建配置。
[package]
name = "my_bevy_game"
version = "0.1.0"
edition = "2021"
[dependencies]
Bevy is?available as a library on crates.io, the official Rust package repository.
Bevy可以作为crates.io板条箱上的库使用。官方的Rust包存储库。
The easiest way to add it to your project is to use?cargo add
:
将其添加到项目中最简单的方法是使用cargo add:
cargo add bevy
Alternatively, you can manually add it to your project's Cargo.toml like this:
或者,您可以手动将其添加到项目的 Cargo.toml中,象这样:
[package]
name = "my_bevy_game"
version = "0.1.0"
edition = "2021" # this needs to be 2021, or you need to set "resolver=2"
# 这需要是2021,否则您需要设置“resolver=2”
[dependencies]
bevy = "0.12" # make sure this is the latest version # 确保这是最新版本
Make sure to use the latest??bevy
?crate version ( Crate版本0.12.1)
确保使用最新的?bevy?
板条箱版本(0.12.1)
If you are using?Cargo Workspaces, you will also need to add the resolver to your Cargo.toml file in the root directory:
如果您正在使用Cargo工作区,您还需要将解析器添加到根目录下的 Cargo.toml文件:
[workspace]
resolver = "2" # Important! wgpu/Bevy needs this!
# 重要!wgpu/Bevy需要这个!
While it may not be an issue for simple projects, debug builds in Rust can be?very slow?- especially when you start using Bevy to make real games.
虽然对于简单的项目来说这可能不是问题,但在Rust中调试构建可能非常缓慢——尤其是当你开始使用Bevy制作真正的游戏时。
It's not uncommon for debug builds using the default configuration to take multiple minutes to load large 3D models, or for the framerate for simple scenes to drop to near-unplayable levels.
使用默认配置的调试构建需要花费数分钟来加载大型3D模型,或者简单场景的帧率下降到几乎无法播放的水平,这并不罕见。
Fortunately, there is a simple fix, and we don't have to give up our fast iterative compiles! Add the following to your?Cargo.toml
:
幸运的是,有一个简单的修复方法,我们不必放弃快速迭代编译器!将以下内容添加到您的Cargo.toml中:
# Enable a small amount of optimization in debug mode
# 在调试模式下启用少量优化
[profile.dev]
opt-level = 1
# Enable high optimizations for dependencies (incl. Bevy), but not for our code:
# 为依赖项(包括Bevy)启用高度优化,但不为我们的代码启用:
[profile.dev.package."*"]
opt-level = 3
You might think to simply develop in release mode instead, but we recommend against this as it can worsen the development experience by slowing down recompiles and disabling helpful debug symbols and assertions.
您可能会认为只需在发布模式下进行开发,但我们不建议这样做,因为它会减慢重新编译的速度,并禁用有用的调试符号和断言,从而恶化开发体验。
Bevy can be built just fine using default configuration on stable Rust. However for maximally fast iterative compiles, we recommend the following configuration:
在稳定的Rust上使用默认配置可以很好地构建Bevy。然而,为了最大限度地快速迭代编译,我们建议使用以下配置:
Enable Bevy's Dynamic Linking Feature: This is the most impactful compilation time decrease! If?bevy
?is a dependency, you can compile the binary with the "dynamic_linking" feature flag (enables dynamic linking).?Important!?On Windows you?must?also enable the?perfomance optimizations?or you will get a?too many exported symbols?error.? ? ? ? ? ? ? ? ? ? ? ?启用Bevy的动态链接功能:这是最有效的编译时间减少的方法!如果bevy是一个依赖项,你可以编译带有"dynamic_linking"特性标志的二进制文件(启用动态链接)。重要!在Windows上,你还必须启用性能优化,否则你会得到太多的导出符号的错误。
cargo run --features bevy/dynamic_linking
If you don't want to add the?--features bevy/dynamic_linking
?to each run, this flag can permanently be set via?Cargo.toml
:? ? ? ? ?如果你不想在每次运行时都添加--features bevy/dynamic_linking,这个标志可以通过Cargo.toml永久设置:
[dependencies]
bevy = { version = "0.12.0", features = ["dynamic_linking"] }
NOTE: Remember to revert this before releasing your game! Otherwise you will need to include?libbevy_dylib
?alongside your game if you want it to run. If you remove the "dynamic" feature, your game executable can run standalone.? ? ? ? ? ? 注意:在发布游戏之前,请务必恢复此设置!否则,如果你想让游戏运行,你就需要在游戏中包含libbevy_dylib。如果你移除“动态”功能,你的游戏可执行文件就可以独立运行了。
LLD linker: The Rust compiler spends a lot of time in the "link" step. LLD is?much faster?at linking than the default Rust linker. To install LLD, find your OS below and run the given command:? ? ? ? ? ? ? ? ? LLD链接器:Rust编译器在“链接”步骤上花费了大量时间。LLD的链接速度比默认的Rust链接器快得多。要安装LLD,请找到下面的操作系统并运行给定的命令:
Ubuntu:?sudo apt-get install lld
Fedora:?sudo dnf install lld
?
Arch:?sudo pacman -S lld
?
Windows: Ensure you have the latest?cargo-binutils?as this lets commands like?cargo run
?use the LLD linker automatically.? ? ? ? ?Windows:确保您有最新的cargo-binutils,因为这允许像cargo run
这样的命令自动使用LLD链接器。
cargo install -f cargo-binutils
rustup component add llvm-tools-preview
MacOS: You can follow these?instructions?to install lld manually or install llvm through brew which includes lld:?brew install llvm
? ? ? ? ?MacOS:您可以按照以下说明手动安装lld或通过brew安装llvm,其中包括lld: brew install llvm
Alternative - mold linker: mold is?up to 5× (five times!) faster?than LLD, but with a few caveats like limited platform support and occasional stability issues. To install mold, find your OS below and run the given command:? ? ? ? ? ? ? ? 可选的模具连接器:模具比LLD快5倍(5倍!),但有一些注意事项,如有限的平台支持和偶尔的稳定性问题。要安装模具,找到下面的操作系统并运行给定的命令:
Ubuntu:?sudo apt-get install mold clang
Fedora:?sudo dnf install mold clang
Arch:?sudo pacman -S mold clang
?
Windows: currently not planned for support?See this tracking issue?for more information.? ? ? ? ? ? Windows:目前未计划支持,请参阅此跟踪问题以获取更多信息。
MacOS: is available commercially with?sold?MacOS:? ? ? ?已在市面上出售
You will also need to add the following to your Cargo config at?YOUR_WORKSPACE/.cargo/config.toml
:? ? ? ? ? ? ?您还需要在YOUR_WORKSPACE/.cargo/config.toml的Cargo配置中添加以下内容:
[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=/usr/bin/mold"]
NOTE: Disabling?bevy/dynamic
?may improve the performance of this linker.? ? ? ? ? ? 注意:禁用bevy/dynamic可以提高此链接器的性能。
Nightly Rust Compiler: This gives access to the latest performance improvements and "unstable" optimizations? ? ? ? ? 夜间版Rust编译器:这提供了访问最新的性能改进和“不稳定”优化
Create a?rust-toolchain.toml
?file in the root of your project, next to?Cargo.toml
.? ? ? ? ? ? ? ? ?在项目的根目录中,在Cargo.toml旁边创建一个rust-tolchain.toml文件。
[toolchain]
channel = "nightly"
For more information, see?The rustup book: Overrides.? ? ? ? ? ? ? 有关更多信息,请参阅rust手册:Overrides。
Generic Sharing: Allows crates to share monomorphized generic code instead of duplicating it. In some cases this allows us to "precompile" generic code so it doesn't affect iterative compiles. This is only available on nightly Rust.? ? ? ? ? ? ?泛型共享:允许crate共享单态泛型代码,而不是复制它。在某些情况下,这允许我们“预编译”泛型代码,这样它就不会影响迭代编译。这只适用于夜间版Rust。
To enable fast compiles, install the nightly rust compiler and LLD. Then copy the contents of?this file?to?YOUR_WORKSPACE/.cargo/config.toml
. For the project in this guide, that would be?my_bevy_game/.cargo/config.toml
.
要启用快速编译,请安装夜间版rust编译器和LLD。然后将该文件(上边的链接)的内容复制到YOUR_WORKSPACE/.cargo/config.toml。对于本指南中的项目,它将是my_bevy_game/.cargo/config.toml。
If something went wrong, check out our?troubleshooting section?or?ask for help on our Discord.
如果出现问题,请查看我们的故障排除部分或在我们的Discord上寻求帮助。
Now run?cargo run
?again. The Bevy dependencies should start building. This will take some time as you are essentially building an engine from scratch. You will only need to do a full rebuild once. Every build after this one will be fast!
现在再运行cargo run
。Bevy依赖项应该开始构建。这需要一些时间,因为你基本上是从零开始构建一个引擎。您只需要进行一次完整的重建。这之后的每一个构建都会很快!
Now that we have our Bevy project set up, we're ready to start making our first Bevy app!
现在我们已经设置了Bevy项目,我们准备开始制作我们的第一个Bevy应用程序!
Bevy programs are referred to as?Apps. The simplest Bevy app looks like this:
Bevy程序被称为应用程序。最简单的Bevy应用程序是这样的:
use bevy::prelude::*;
fn main() {
App::new().run();
}
Nice and simple right? Copy the code above into your?main.rs
?file, then run:
很简单,对吧?将上面的代码复制到main.rs
文件代码中,然后运行:
cargo run
in your project folder. You will notice that ... nothing happens. This is because we haven't told our app to do anything yet! Apps are just empty shells capable of running our application logic. Let's add some logic to our App using Bevy ECS.
在您的项目文件夹中。你会注意到……什么也不会发生。这是因为我们还没有告诉我们的应用做任何事情!应用程序只是能够运行我们的应用程序逻辑的空壳。让我们使用Bevy ECS向应用程序添加一些逻辑。
All app logic in Bevy uses the Entity Component System paradigm, which is often shortened to ECS. ECS is a software pattern that involves breaking your program up into?Entities,?Components, and?Systems.?Entities?are unique "things" that are assigned groups of?Components, which are then processed using?Systems.
Bevy中的所有应用逻辑都使用实体组件系统范式,通常简称为ECS。ECS是一种软件模式,它将程序分解为实体、组件和系统。实体是分配给组件组的唯一“事物”,然后使用系统处理组件组。
For example, one entity might have a?Position
?and?Velocity
?component, whereas another entity might have a?Position
?and?UI
?component. Systems are logic that runs on a specific set of component types. You might have a?movement
?system that runs on all entities with a?Position
?and?Velocity
?component.
例如,一个实体可能有位置和速度组件,而另一个实体可能有位置和UI组件。系统是运行在一组特定组件类型上的逻辑。你可能有一个运行在所有带有位置和速度组件的实体上的移动系统。
The ECS pattern encourages clean, decoupled designs by forcing you to break up your app data and logic into its core components. It also helps make your code faster by optimizing memory access patterns and making parallelism easier.
ECS模式通过强迫你将应用数据和逻辑分解到核心组件中,从而鼓励干净、解耦的设计。它还通过优化内存访问模式和简化并行性来帮助您的代码更快。
Bevy ECS is Bevy's implementation of the ECS pattern. Unlike other Rust ECS implementations, which often require complex lifetimes, traits, builder patterns, or macros, Bevy ECS uses normal Rust datatypes for all of these concepts:
Bevy ECS是Bevy对ECS模式的实现。与其他Rust ECS实现不同,这些实现通常需要复杂的生命周期、特征、构建器模式或宏,Bevy ECS使用普通的Rust数据类型来实现所有这些概念:
Components: Rust structs that implement the?Component
?trait? ? ? ? ? ? ? 组件:实现Component特性的Rust结构
#[derive(Component)]
struct Position { x: f32, y: f32 }
Systems: normal Rust functions? ? ? ? ? 系统:普通的Rust函数
fn print_position_system(query: Query<&Position>) {
for position in &query {
println!("position: {} {}", position.x, position.y);
}
}
Entities: a simple type containing a unique integer? ? ? 实体:包含唯一整数的简单类型
struct Entity(u64);
Now let's see how this works in practice!
现在让我们看看它在实践中是如何工作的!
Paste the following function into your?main.rs
?file:
将以下函数粘贴到main.rs文件中:
fn hello_world() {
println!("hello world!");
}
This will be our first system. The only remaining step is to add it to our?App
!
这是我们的第一个系统。唯一剩下的步骤是将其添加到我们的应用程序!
use bevy::prelude::*;
fn main() {
App::new()
.add_systems(Update, hello_world)
.run();
}
The?add_systems()?function adds the system to your App's?Update?Schedule, but we'll cover that more later.
add_systems()函数将系统添加到应用程序的Update Schedule中,但我们稍后会详细介绍。
Now run your app again using?cargo run
. You should see?hello world!
?printed once in your terminal.
现在使用cargo run再次运行应用程序。你应该看到hello world!在终端中打印一次。
Greeting the whole world is great, but what if we want to greet specific people? In ECS, you would generally model people as entities with a set of components that define them. Let's start simple with a?Person
?component.
和全世界的人打招呼很好,但如果我们想和特定的人打招呼呢?在ECS中,您通常会将人建模为具有一组定义他们的组件的实体。让我们从简单的Person组件开始。
Add this struct to your?main.rs
?file:
将这个结构体添加到main.rs
文件:
#[derive(Component)]
struct Person;
But what if we want our people to have a name? In a more traditional design, we might just tack on a?name: String
?field to?Person
. But other entities might have names too! For example, dogs should probably also have a name. It often makes sense to break datatypes up in to small pieces to encourage code reuse. So let's make?Name
?its own component:
但如果我们想让我们的人有个名字呢?在更传统的设计中,我们可能只是给Person添加一个name: String字段。但其他实体也可能有名字!例如,狗可能也应该有一个名字。将数据类型分解成小块以鼓励代码重用通常是有意义的。让我们让Name成为它自己的组件:
#[derive(Component)]
struct Name(String);
We can then add people to our?World?using a "startup system". Startup systems are just like normal systems, but they run exactly once, before all other systems, right when our app starts. Let's use?Commands?to spawn some entities into our?World:
然后我们可以使用“启动系统”向我们的World添加人员。启动系统就像普通系统一样,但它们只运行一次,在所有其他系统之前,就在我们的应用程序启动时。让我们使用命令来生成(spawn)一些实体到我们的世界:
fn add_people(mut commands: Commands) {
commands.spawn((Person, Name("Elaina Proctor".to_string())));
commands.spawn((Person, Name("Renzo Hume".to_string())));
commands.spawn((Person, Name("Zayna Nieves".to_string())));
}
Now register the startup system like this:
现在像这样注册启动系统:
fn main() {
App::new()
.add_systems(Startup, add_people)
.add_systems(Update, hello_world)
.run();
}
We could run this now and the?add_people
?system would run first, followed by?hello_world
. But our new people don't have anything to do yet! Let's make a system that properly greets the new citizens of our?World:
我们现在可以运行这个,add_people系统将首先运行,然后是hello_world。但是我们的新员工还没有任何事情可做!让我们建立一个系统,恰当地迎接我们世界的新公民:
fn greet_people(query: Query<&Name, With<Person>>) {
for name in &query {
println!("hello {}!", name.0);
}
}
The parameters we pass into a "system function" define what data the system runs on. In this case,?greet_people
?will run on all entities with the?Person
?and?Name
?component.
我们传递给“system function 系统函数”的参数定义了系统运行的数据。在本例中,greet_people将在具有Person和Name组件的所有实体上运行。
You can interpret the?Query
?above as: "iterate over every?Name
?component for entities that also have a?Person
?component".
您可以将上面的查询解释为:“遍历每个Name组件,以查找也具有Person组件的实体”。
Now we just register the system in our?App
. Note that you can pass more than one system into an?add_systems
?call by using a tuple!
现在我们只需在App中注册系统。注意,你可以通过使用元组将多个系统传递给add_systems调用!
fn main() {
App::new()
.add_systems(Startup, add_people)
.add_systems(Update, (hello_world, greet_people))
.run();
}
Running our app will result in the following output:
运行我们的应用程序将得到以下输出:
hello world!
hello Elaina Proctor!
hello Renzo Hume!
hello Zayna Nieves!
Marvelous!
不可思议的!
Quick Note: "hello world!" might show up in a different order than it does above. This is because systems run in parallel by default whenever possible.
快速提示:“hello world!”可能以与上面不同的顺序出现。这是因为系统在默认情况下尽可能并行运行。
If we want to change the names of some people (perhaps they got married!), for example, we can do this using a mutable query:
例如,如果我们想改变一些人的名字(也许他们结婚了!),我们可以使用一个可变查询:
fn update_people(mut query: Query<&mut Name, With<Person>>) {
for mut name in &mut query {
if name.0 == "Elaina Proctor" {
name.0 = "Elaina Hume".to_string();
break; // We don’t need to change any other names
// 我们不需要更改任何其他名称
}
}
}
We need to make?query
?mutable, and use a mutable reference (&mut
) to the components we want to change.
我们需要使可变查询,并对我们想要更改的组件使用可变引用(&mut)。
Don’t forget to add the system to the?Update?schedule:
不要忘记将系统添加到更新计划中:
fn main() {
App::new()
.add_systems(Startup, add_people)
.add_systems(Update, (hello_world, (update_people, greet_people).chain()))
.run();
}
Note that we have used?.chain()
?on the two systems. This is because we want them two to run in exactly the order they're listed in the code: with?update_people
?occurring before?greet_people
. If they weren’t, the name might change after we greet the people.
注意,我们在两个系统上使用了.chain()。这是因为我们希望它们两个按照代码中列出的顺序运行:update_people出现在greet_people之前。如果他们不喜欢,在我们和人们打招呼之后,名字可能会改变。
But we don’t add the?hello_world
?system to the chain, because it doesn’t matter when it runs. This way, Bevy can run?hello_world
?in parallel while the other systems are running.
但是我们没有将hello_world系统添加到链中,因为它何时运行并不重要。通过这种方式,Bevy可以在其他系统运行时并行运行hello_world。
One of Bevy's core principles is modularity. All Bevy engine features are implemented as plugins. This includes internal features like the renderer, but games themselves are also implemented as plugins! This empowers developers to pick and choose which features they want. Don't need a UI? Don't register the?UiPlugin. Want to build a headless server? Don't register the?RenderPlugin.
Bevy的核心原则之一是模块化。所有Bevy引擎功能都是作为插件实现的。这包括像渲染器这样的内部功能,但游戏本身也是作为插件实现的!这使开发人员能够挑选他们想要的特性。不需要UI?不要注册UiPlugin。想要构建一个无头服务器?不要注册RenderPlugin。
This also means you are free to replace any components you don't like. If you feel the need, you are welcome to build your own?UiPlugin, but consider?contributing it back to Bevy?if you think it would be useful!
这也意味着您可以自由更换任何您不喜欢的组件。如果你觉得有必要,欢迎你构建自己的UiPlugin,而且如果你认为它有用的话,可以考虑把它贡献给Bevy !
However, most developers don't need a custom experience and just want the "full engine" experience with no hassle. For this, Bevy provides a set of "default plugins".
然而,大多数开发者并不需要实现自定义的体验,他们只想要“完整的引擎”体验。为此,Bevy提供了一组“默认插件”。
Let's make our app more interesting by adding the "default Bevy plugins".?add_plugins(DefaultPlugins)
?adds the features most people expect from an engine, such as a 2D / 3D renderer, asset loading, a UI system, windows, and input.
让我们通过添加“默认Bevy插件”来使我们的应用程序更有趣。add_plugins(DefaultPlugins)添加了大多数人期望从引擎中获得的功能,如2D / 3D渲染器、资产加载、UI系统、窗口和输入。
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, add_people)
.add_systems(Update, (hello_world, greet_people))
.run();
}
Once again run?cargo run
.? ? ?
再次运行cargo run
。
You should hopefully notice two things:
你应该注意到两件事:
For better organization, let's move all of our "hello" logic to a plugin. To create a plugin we just need to implement the?Plugin?interface. Add the following code to your?main.rs
?file:
为了更好地组织,让我们将所有的“hello”逻辑移到一个插件中。要创建一个插件,我们只需要实现plugin接口。将以下代码添加到您的?main.rs
?文件:
pub struct HelloPlugin;
impl Plugin for HelloPlugin {
fn build(&self, app: &mut App) {
// add things to your app here
}
}
Then register the plugin in your App like this:
然后像这样在你的应用程序中注册插件:
fn main() {
App::new()
.add_plugins((DefaultPlugins, HelloPlugin))
.add_systems(Startup, add_people)
.add_systems(Update, (hello_world, greet_people))
.run();
}
Note?add_plugins
?can add any number of plugins (or plugin groups like?DefaultPlugins
) by passing in a tuple of them. Now all that's left is to move our systems into?HelloPlugin
, which is just a matter of cut and paste. The?app
?variable in our plugin's?build()
?function is the same builder type we use in our?main()
?function:
注意add_plugins可以通过传入一个元组来添加任意数量的插件(或像DefaultPlugins这样的插件组)。现在剩下的就是把我们的系统移到HelloPlugin中,这只是一个剪切和粘贴的问题。我们插件的build()函数中的app变量与main()函数中的构建器类型相同:
impl Plugin for HelloPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, add_people)
.add_systems(Update, (hello_world, greet_people));
}
}
fn main() {
App::new()
.add_plugins((DefaultPlugins, HelloPlugin))
.run();
}
Try running the app again. It should do exactly what it did before. In the next section, we'll fix the "hello" spam using Resources.
尝试再次运行应用程序。它应该像以前那样做。在下一节中,我们将使用参考资料修复“hello”垃圾邮件。
Entities?and?Components?are great for representing complex, query-able groups of data. But most Apps will also require "globally unique" data of some kind. In Bevy ECS, we represent globally unique data using?Resources.
实体和组件非常适合表示复杂的、可查询的数据组。但大多数应用程序也需要某种“全局唯一”的数据。在Bevy ECS中,我们使用资源表示全局唯一的数据。
Here are some examples of data that could be encoded as?Resources:
以下是一些可以编码为资源的数据示例:
Let's solve our App's "hello spam" problem by only printing "hello" once every two seconds. We'll do this by using the?Time?resource, which is automatically added to our App via?add_plugins(DefaultPlugins)
.
让我们通过每两秒钟打印一次“hello”来解决应用程序的“hello垃圾邮件”问题。我们将通过使用时间资源来做到这一点,它是通过add_plugins(DefaultPlugins)自动添加到我们的应用程序中的。
For simplicity, remove the?hello_world
?system from your App. This way we only need to adapt the?greet_people
?system.
为了简单起见,从应用程序中删除hello_world系统。这样我们只需要调整greet_people系统。
Resources are accessed in much the same way that we access components. You can access the?Time
?resource in your system like this:
访问资源的方式与访问组件的方式大致相同。你可以像这样访问系统中的时间资源:
fn greet_people(time: Res<Time>, query: Query<&Name, With<Person>>) {
for name in &query {
println!("hello {}!", name.0);
}
}
Res
?and?ResMut
?pointers provide read and write access (respectively) to resources.
Res和ResMut指针分别提供对资源的读和写访问。
The?delta
?field on?Time
?gives us the time that has passed since the last update. But in order to run our system once every two seconds, we must track the amount of time that has passed over a series of updates. To make this easier, Bevy provides the?Timer
?type. Let's create a new Resource for our system to track elapsed time with a?Timer
:
时间上的delta字段表示上次更新后经过的时间。但是为了每两秒钟运行一次系统,我们必须跟踪一系列更新所经过的时间。为了简化这一点,Bevy提供了Timer类型。让我们为我们的系统创建一个新的资源,用计时器来跟踪经过的时间:
#[derive(Resource)]
struct GreetTimer(Timer);
fn greet_people(
time: Res<Time>, mut timer: ResMut<GreetTimer>, query: Query<&Name, With<Person>>) {
// update our timer with the time elapsed since the last update
// 使用上次更新后经过的时间更新计时器
// if that caused the timer to finish, we say hello to everyone
// 如果这导致计时器结束,我们向所有人问好
if timer.0.tick(time.delta()).just_finished() {
for name in &query {
println!("hello {}!", name.0);
}
}
}
Now all that's left is adding a?GreetTimer
?Resource to our?HelloPlugin
. Use?TimerMode::Repeating
?to make the timer repeat.
现在剩下的就是在HelloPlugin中添加一个GreetTimer资源。使用TimerMode:: repeat使计时器重复。
impl Plugin for HelloPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(GreetTimer(Timer::from_seconds(2.0, TimerMode::Repeating)))
.add_systems(Startup, add_people)
.add_systems(Update, greet_people);
}
}
Now?cargo run
?the App. It should now greet people at a reasonable rate.
现在?cargo run
运行应用程序。它现在应该以合理的速度欢迎人们。
You have reached the end of The Bevy Book! And unfortunately, we haven't even scratched the surface of Bevy's features! Eventually this book will cover almost every facet of Bevy, but until then we recommend checking out:
你已经读到《The Bevy Book》的结尾了!不幸的是,我们甚至还没有触及到Bevy功能的表面!最终,本书将涵盖Bevy的几乎所有方面,但在此之前,我们建议您查看:
Bevy is built by volunteers. If you want to help us build the next great game engine,?please reach out! We need all the help we can get:
Bevy是由志愿者建立的。如果你想帮助我们构建下一个伟大的游戏引擎,请联系我们!我们需要所有能得到的帮助:
We want Bevy to be a vibrant developer community ... that's actually why we chose the name! A Bevy is a group of birds, just like we are a group of game developers. Join the Bevy!? ? ? ? ? ? ? ? ? ? ? 我们希望Bevy成为一个充满活力的开发者社区……这就是我们选择这个名字的原因!Bevy是一群鸟,就像我们是一群游戏开发者一样。加入bevy!
Would you like to contribute code to Bevy? Here's how!
你愿意为Bevy贡献代码吗?这里就是!
cargo run -p ci
. ? ? ? ?为了提高初次CI通过的几率,请考虑在本地运行cargo run -p ci
. You can run the commands manually: . 您可以手动执行以下命令:
--check
?to let the command fix found problems? 删除--check?
以使命令修复发现的问题)cargo test --all-targets --workspace
Remember to follow Bevy's?Code of Conduct, and thanks for contributing!
记得遵守Bevy的行为准则,感谢您的贡献!
*The same steps apply for any other repository in the?Bevy organization?that you would like to contribute to.
*同样的步骤适用于您想要贡献的Bevy组织中的任何其他存储库。
The Bevy Book is open source, along with the rest of this website. Check out the?Bevy Website repository on GitHub. The Bevy Book content is written in Markdown.
Bevy Book和这个网站的其他部分都是开源的。查看GitHub上的Bevy网站存储库。bevy书的内容是用Markdown写的。
The website is built using the?Zola static site generator. Download Zola, then do the following:
该网站是使用Zola静态网站生成器构建的。下载Zola,然后执行以下操作:
Clone the Bevy Website git repo and move to that directory:? ? ? ? 克隆Bevy网站的git repo并移动到该目录:
git clone https://github.com/bevyengine/bevy-website.git
cd bevy-website
Start the Zola server? ? ? 启动Zola服务器
zola serve
A local server should start and you should be able to access a local version of the website from there.
一个本地服务器应该启动,你应该能够从那里访问网站的本地版本。
We made an extension to the markdown syntax that makes linking to Rust API docs nicer. It also gives the links special formatting. Here are some examples:
我们对markdown语法做了一个扩展,使链接到Rust API文档变得更好。它还为链接提供了特殊的格式。下面是一些例子:
Full Type Path:?std::collections::HashMap? ? 完整类型路径:std::collections::HashMap
{{rust_type(type="struct" crate="std" mod="collections" name="HashMap")}}
Short Type:?HashMap? ? ?短类型:HashMap
{{rust_type(type="struct" crate="std" mod="collections" name="HashMap" no_mod=true)}}
Function:?HashMap::insert()? ? ?功能:HashMap:插入()
{{rust_type(type="struct" crate="std" mod="collections" name="HashMap" no_mod=true method="insert")}}
Module:?std::collections? ? ? 模块:std::集合
{{rust_mod(crate="std" mod="collections")}}?
Modules from?std?will link to?https://doc.rust-lang.org. Other modules (like?bevy_render::render_graph?) will link to?https://docs.rs.
来自std的模块将链接到https://doc.rust-lang.org。其他模块(如bevy_render::render_graph)将链接到https://docs.rs。
Bevy's Rust API Docs are automatically generated from the latest Bevy source code. If you add?Rust documentation comments?to the Bevy codebase, the API docs will be automatically updated.
Bevy的Rust API文档是从最新的Bevy源代码自动生成的。如果将Rust文档注释添加到Bevy代码库,API文档将自动更新。
Bevy's CI will check markdown files like Readmes using?markdownlint. If you contribute to markdown files consider installing?markdownlint-cli?to locally lint your changes. Running?markdownlint -f -c .github/linters/.markdown-lint.yml .
?in the root directory of the Bevy project will apply the same linting rules to your changes as the CI workflow.
Bevy的CI将使用markdownlint检查Readmes等markdown文件。如果您对标记文件做出了贡献,请考虑安装markdownlint-cli来本地检测您的更改。运行markdownlint -f -c .github/lint /. markdownlint。yml。在Bevy项目的根目录中,将对您的更改应用与CI工作流相同的检查规则。
Building Bevy's Ecosystem 构建bevy的生态系统
Bevy has a plug-and-play architecture, where you can easily add plugins for new features or use your own plugins instead of the built-in ones. You can also create third-party plugins that others may use in their applications.
Bevy有一个即插即用的架构,你可以很容易地为新功能添加插件,或者使用你自己的插件而不是内置的插件。您还可以创建其他人可能在其应用程序中使用的第三方插件。
With that in mind, this page provides some basic info that can be useful when authoring third-party plugins.
考虑到这一点,这个页面提供了一些在编写第三方插件时可能有用的基本信息。
You are free to use a?bevy_xxx
?name for your plugin, but please be reasonable. If you are about to claim a generic name like?bevy_animation
,?bevy_color
, or?bevy_editor
, please ask first. The rationale is explained?here.
您可以自由地为您的插件使用bevy_xxx名称,但请合理。如果您要声明一个通用名称,如bevy_animation、bevy_color或bevy_editor,请先询问。这里解释了其基本原理。
Bevy is dual licensed under?MIT or Apache 2.0, at your option. Most other Rust projects (including Rust itself) also use this dual-license approach. MIT-only is very popular, and you might be tempted to just use that (Bevy also used to be MIT-only), but there are?very good reasons?to include both licenses. We highly recommend using the dual MIT / Apache 2.0 license for your Bevy Plugins and crates:
Bevy是MIT或Apache 2.0的双重许可,由您选择。大多数其他Rust项目(包括Rust本身)也使用这种双许可方法。MIT-only非常受欢迎,您可能会想使用它(Bevy也曾经是MIT-only),但是有很好的理由包括这两种许可。我们强烈建议使用双重MIT / Apache 2.0许可证为您的Bevy插件和板条箱:
While they are only guidelines, it can be useful for you to look at and consider the?Rust API guidelines?and?Cargo SemVer compatibility conventions?for recommendations on how to write your API and what to consider a breaking or compatible change.? ? ? ? ? ? ?虽然它们只是指导方针,但您可以查看并考虑Rust API指导方针和Cargo SemVer兼容性约定,以获得关于如何编写API以及如何考虑破坏或兼容更改的建议。
It can be useful to allow your users to supply generic types to your plugins. It can enable them to write custom logic for components to be used; give your plugin a marker component to note an entity it should do some logic to; add events that your plugin should listen for; or a resource your plugin should use (which is useful if you want to apply your plugin to multiple resources of the same type via type aliases.)
允许用户为插件提供泛型类型是很有用的。它可以使他们为要使用的组件编写自定义逻辑;给你的插件一个标记组件来标记一个它应该做一些逻辑处理的实体;添加插件应该监听的事件;或者你的插件应该使用的资源(如果你想通过类型别名将你的插件应用于相同类型的多个资源,这很有用)。
You can define a generic plugin like so:
你可以这样定义一个泛型插件:
// example with a generic type that implements Component
// 具有实现Component的泛型类型的示例
pub struct YourPlugin<T: Component> {
pub phantom_t: PhantomData<T>,
}
impl<T: Component> Plugin for YourPlugin<T> {
fn build(&self, app: &mut App) {
app.add_systems(Startup, example_function::<T>);
}
// ... your other logic ...
// …你的另一个逻辑。。。
}
// example function using your generics
// 使用泛型的示例函数
pub fn example_function<T: Component>(mut commands: Commands) {
commands.spawn(T);
// ... any other logic here ...
// ...这里的任何其他逻辑。。。
}
A prime example of generic plugins in use is the?Bevy Cellular Automaton Plugin.
通用插件的一个典型例子是Bevy细胞自动机插件。
To avoid long build times in your plugin and in projects using it, you should aim for a small crate size:
为了避免在你的插件和使用它的项目中长时间的构建,你应该瞄准一个小的crate大小:
Only include the Bevy features you absolutely need.? ? ? ? 只包括你绝对需要的Bevy功能。
Features are additive — Bevy features enabled in your plugin cannot be disabled by someone using your plugin.? ? ? ? ? ?特性是附加的——插件中启用的特性不能被使用插件的人禁用。
You should add?default-features = false
?to the Bevy dependency in your?Cargo.toml
?and manually specify the features you need.? ? ? ? ?您应该将default-features = false添加到Cargo中的Bevy依赖项中。tom和手动指定您需要的特性。
You can find a list of Bevy's features?here.? ? ? ? 您可以在这里找到Bevy的功能列表。
Avoid large new dependencies.? ? ? ? 避免大型的新依赖项。
Make sure your dependencies are not duplicated, using?cargo tree?or?cargo-deny.? ? ? ? ?使用cargo tree或cargo-deny,确保您的依赖项没有重复。
Put optional functionality and dependencies behind a?cargo feature.? ? ? ? ? ?将可选的功能和依赖项放在cargo feature后面。
Tests are always good! For CI, you can check out?this example?for a quick start using GitHub Actions. As Bevy has additional Linux dependencies, you should install them before building your project (here is how Bevy is doing it). Even if you don't have many (or any) tests, setting up CI will compile check your plugin and ensure a basic level of quality.
测试总是好的!对于CI,您可以查看这个示例,以快速开始使用GitHub Actions。由于Bevy有额外的Linux依赖项,您应该在构建项目之前安装它们(Bevy是这样做的)。即使你没有很多(或任何)测试,设置CI也会对你的插件进行编译检查,并确保基本的质量水平。
Indicating which version of your plugin works with which version of Bevy can be helpful for your users. Some of your users may be using an older version of Bevy for any number of reasons. You can help them find which version of your plugin they should use. This can be shown as a simple table in your README with each version of Bevy and the corresponding compatible version of your plugin.
指出哪个版本的插件可以与哪个版本的Bevy一起工作,这对您的用户很有帮助。由于各种原因,您的一些用户可能正在使用旧版本的Bevy。你可以帮助他们找到他们应该使用的插件版本。这可以在README中显示为一个简单的表格,其中包含每个版本的Bevy和相应的插件兼容版本。
| bevy | bevy_awesome_plugin |
|-------|---------------------|
| 0.12 | 0.3 |
| 0.11 | 0.1 |
Bevy is evolving very fast. There are often new features on the main branch but have not yet been released. Your plugin might depend on Bevy Main or the latest release. You can also do both on different branches (e.g., have a?bevy_main
?branch).
bevy发展得很快。通常在主分支上有新特性,但尚未发布。您的插件可能依赖于Bevy Main或最新版本。你也可以在不同的分支上同时做这两件事(例如,有一个bevy_main分支)。
If you intend to track Bevy's main branch, you can specify the latest commit you support in your?Cargo.toml
?file:
如果您打算跟踪Bevy的主分支,您可以在Cargo中指定您支持的最新提交?Cargo.toml
文件:
bevy = { version = "0.5", git = "https://github.com/bevyengine/bevy", rev = "9788b386c7846c99978ab5c1a33698ec5a471d84", default-features = false }
You can specify the dependency?both as a version and with git. The version will be used if the dependency is pulled from?crates.io. Otherwise, the git dependency will be used.
你既可以指定版本,也可以使用git指定依赖项。如果从crate .io中提取依赖,则将使用该版本。否则,将使用git依赖项。
You can use one of these badges to communicate to your users how closely you intend to track Bevy's main branch.
您可以使用这些徽章之一来告知您的用户您打算如何密切跟踪Bevy的主要分支。
???
[ (![ !Following released Bevy versions 以下是已发布的Bevy版本] ]( (https://img.shields.io/badge/Bevy%20tracking-released%20version-lightblue) )] ]( (https://bevyengine.org/learn/book/plugin-development/#main-branch-tracking) )
???
[ (![ !Following Bevy's main branch 跟随bevy的主要分支] ]( (https://img.shields.io/badge/Bevy%20tracking-main-lightblue) )] ]( (https://bevyengine.org/learn/book/plugin-development/#main-branch-tracking) )
Documentation and examples are very useful for a crate.? ? ?文档和示例对crate非常有用。
In the case of a Bevy plugin, a few screenshots or movies / animated GIFs from your examples can really help to understand what your plugin is capable of.
在使用Bevy插件的情况下,你的例子中的一些截图或电影/ gif动画可以真正帮助理解你的插件的功能。
Additionally, it can be helpful to list:
此外,列出以下内容也会有所帮助:
There are some?extra fields?that you can add to your?Cargo.toml
?manifest in the?[package]
?section:
您可以将一些额外的字段添加到Cargo中。在[package]部分中显示:
assets
?folder that you may have is a good idea, as well as any large files that are not needed by the plugin.? ? 要从发布包中排除的文件。排除掉你可能有的assets文件夹以及插件不需要的大文件是个好主意。Once a crate is published to?crates.io, there are two badges that you can add to your?README.md
?for easy links: 一旦一个crate被发布到crate中。io中,有两个徽章可以添加到自述文件中。浏览网页连结:
???
[ (![ !crates.io] ]( (https://img.shields.io/crates/v/bevy_awesome_plugin) )] ]( (https://crates.io/crates/bevy_awesome_plugin) )
???
[ (![ !docs.rs] ]( (https://docs.rs/bevy_awesome_plugin/badge.svg) )] ]( (https://docs.rs/bevy_awesome_plugin) )` `
You can promote your plugin in Bevy's?communities:
你可以在Bevy的社区中推广你的插件:
#crates
?channel.? ? ?在Discord的#crates频道上宣布。Is something in Bevy not working as expected? Maybe one of these will resolve your problem:
bevy是不是有什么地方不像预期的那样好用?也许其中一个可以解决你的问题:
thread 'main' panicked at 'Unable to find a GPU! Make sure you have installed required drivers!'
// 主线程“无法找到GPU!”确保你已经安装了所需的驱动程序!
This error message means that bevy is unable to draw to your screen. Causes include:
此错误信息表示无法绘制到屏幕上。原因包括:
vulkan-intel
?or 或vulkan-radeon
. .The program '[10184] my-game.exe' has exited with code -1073741515 (0xc0000135).
// 程序'[10184]my-game.exe'退出,代码为-1073741515 (0xc0000135)。
Whilst?cargo run
?may load the application successfully, running via the debugging UI in VSCode may yield the above error. This error means that the required libraries were not loaded correctly (likely due to a pathing quirk with VSCode debug extensions on Windows).
虽然cargo run可以成功加载应用程序,但在VSCode中通过调试UI运行可能会产生上述错误。此错误意味着所需的库没有正确加载(可能是由于Windows上VSCode调试扩展的路径怪异)。
Edit your launch configurations in?.vscode/launch.json
?so that the rust libraries are found correctly.
在.vscode/launch中编辑你的启动配置。Json以便正确找到rust库。
For?cppvsdbg
: cppvsdbg:
"environment": [
{"name":"PATH", "value":"%USERPROFILE%/.rustup/toolchains/nightly-x86_64-pc-windows-msvc/bin;${workspaceFolder}/target/debug/deps;%PATH%"}
// Switch `nightly` to `stable` if you're using Rust stable
// 如果您使用的是Rust-stable,请将“夜间”切换为“稳定”
],
Or for?codelldb
:? ? ?对于codelldb来说:
"env": {
"PATH": "${env:USERPROFILE}/.rustup/toolchains/nightly-x86_64-pc-windows-msvc/bin;${workspaceFolder}/target/debug/deps;${env:PATH}",
// Switch `nightly` to `stable` if you're using Rust stable
// 如果您使用的是Rust-stable,请将“夜间”切换为“稳定”
},
(全文结束了,谢谢观看)