This is an updated version of #15530. Review comments were addressed. This commit changes the animation graph evaluation to be operate in a more sensible order and updates the semantics of blend nodes to conform to [the animation composition RFC]. Prior to this patch, a node graph like this: ``` ┌─────┐ │ │ │ 1 │ │ │ └──┬──┘ │ ┌───────┴───────┐ │ │ ▼ ▼ ┌─────┐ ┌─────┐ │ │ │ │ │ 2 │ │ 3 │ │ │ │ │ └──┬──┘ └──┬──┘ │ │ ┌───┴───┐ ┌───┴───┐ │ │ │ │ ▼ ▼ ▼ ▼ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │ │ │ │ │ │ │ 4 │ │ 6 │ │ 5 │ │ 7 │ │ │ │ │ │ │ │ │ └─────┘ └─────┘ └─────┘ └─────┘ ``` Would be evaluated as (((4 ⊕ 5) ⊕ 6) ⊕ 7), with the blend (lerp/slerp) operation notated as ⊕. As quaternion multiplication isn't commutative, this is very counterintuitive and will especially lead to trouble with the forthcoming additive blending feature (#15198). This patch fixes the issue by changing the evaluation order to postorder, with children of a node evaluated in ascending order by node index. To do so, this patch revamps `AnimationCurve` to be based on an *evaluation stack* and a *blend register*. During target evaluation, the graph evaluator traverses the graph in postorder. When encountering a clip node, the evaluator pushes the possibly-interpolated value onto the evaluation stack. When encountering a blend node, the evaluator pops values off the stack into the blend register, accumulating weights as appropriate. When the graph is completely evaluated, the top element on the stack is *committed* to the property of the component. A new system, the *graph threading* system, is added in order to cache the sorted postorder traversal to avoid the overhead of sorting children at animation evaluation time. Mask evaluation has been moved to this system so that the graph only has to be traversed at most once per frame. Unlike the `ActiveAnimation` list, the *threaded graph* is cached from frame to frame and only has to be regenerated when the animation graph asset changes. This patch currently regresses the `animate_target` performance in `many_foxes` by around 50%, resulting in an FPS loss of about 2-3 FPS. I'd argue that this is an acceptable price to pay for a much more intuitive system. In the future, we can mitigate the regression with a fast path that avoids consulting the graph if only one animation is playing. However, in the interest of keeping this patch simple, I didn't do so here. [the animation composition RFC]: https://github.com/bevyengine/rfcs/blob/main/rfcs/51-animation-composition.md # Objective - Describe the objective or issue this PR addresses. - If you're fixing a specific issue, say "Fixes #X". ## Solution - Describe the solution used to achieve the objective above. ## Testing - Did you test these changes? If so, how? - Are there any parts that need more testing? - How can other people (reviewers) test your changes? Is there anything specific they need to know? - If relevant, what platforms did you test these changes on, and are there any important ones you can't test? --- ## Showcase > This section is optional. If this PR does not include a visual change or does not add a new feature, you can delete this section. - Help others understand the result of this PR by showcasing your awesome work! - If this PR adds a new feature or public API, consider adding a brief pseudo-code snippet of it in action - If this PR includes a visual change, consider adding a screenshot, GIF, or video - If you want, you could even include a before/after comparison! - If the Migration Guide adequately covers the changes, you can delete this section While a showcase should aim to be brief and digestible, you can use a toggleable section to save space on longer showcases: <details> <summary>Click to view showcase</summary> ```rust println!("My super cool code."); ``` </details> ## Migration Guide > This section is optional. If there are no breaking changes, you can delete this section. - If this PR is a breaking change (relative to the last release of Bevy), describe how a user might need to migrate their code to support these changes - Simply adding new functionality is not a breaking change. - Fixing behavior that was definitely a bug, rather than a questionable design choice is not a breaking change. --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> |
||
---|---|---|
.cargo | ||
.github | ||
assets | ||
benches | ||
crates | ||
docs | ||
docs-template | ||
errors | ||
examples | ||
src | ||
tests | ||
tools | ||
.gitattributes | ||
.gitignore | ||
Cargo.toml | ||
clippy.toml | ||
CODE_OF_CONDUCT.md | ||
CONTRIBUTING.md | ||
CREDITS.md | ||
deny.toml | ||
LICENSE-APACHE | ||
LICENSE-MIT | ||
README.md | ||
rustfmt.toml | ||
typos.toml |
What is Bevy?
Bevy is a refreshingly simple data-driven game engine built in Rust. It is free and open-source forever!
WARNING
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.
MSRV: Bevy relies heavily on improvements in the Rust language and compiler. As a result, the Minimum Supported Rust Version (MSRV) is generally close to "the latest stable release" of Rust.
Design Goals
- Capable: Offer a complete 2D and 3D feature set
- Simple: Easy for newbies to pick up, but infinitely flexible for power users
- Data Focused: Data-oriented architecture using the Entity Component System paradigm
- Modular: Use only what you need. Replace what you don't like
- Fast: App logic should run quickly, and when possible, in parallel
- Productive: Changes should compile quickly ... waiting isn't fun
About
- Features: A quick overview of Bevy's features.
- News: A development blog that covers our progress, plans and shiny new features.
Docs
- Quick Start Guide: Bevy's official Quick Start Guide. The best place to start learning Bevy.
- Bevy Rust API Docs: Bevy's Rust API docs, which are automatically generated from the doc comments in this repo.
- Official Examples: Bevy's dedicated, runnable examples, which are great for digging into specific concepts.
- Community-Made Learning Resources: More tutorials, documentation, and examples made by the Bevy community.
Community
Before contributing or participating in discussions with the community, you should familiarize yourself with our Code of Conduct.
- Discord: Bevy's official discord server.
- Reddit: Bevy's official subreddit.
- GitHub Discussions: The best place for questions about Bevy, answered right here!
- Bevy Assets: A collection of awesome Bevy projects, tools, plugins and learning materials.
Contributing
If you'd like to help build Bevy, check out the Contributor's Guide. For simple problems, feel free to open an issue or PR and tackle it yourself!
For more complex architecture decisions and experimental mad science, please open an RFC (Request For Comments) so we can brainstorm together effectively!
Getting Started
We recommend checking out the Quick Start Guide for a brief introduction.
Follow the Setup guide to ensure your development environment is set up correctly. Once set up, you can quickly try out the examples by cloning this repo and running the following commands:
# Switch to the correct version (latest release, default is main development branch)
git checkout latest
# Runs the "breakout" example
cargo run --example breakout
To draw a window with standard functionality enabled, use:
use bevy::prelude::*;
fn main(){
App::new()
.add_plugins(DefaultPlugins)
.run();
}
Fast Compiles
Bevy can be built just fine using default configuration on stable Rust. However for really fast iterative compiles, you should enable the "fast compiles" setup by following the instructions here.
Bevy Cargo Features
This list outlines the different cargo features supported by Bevy. These allow you to customize the Bevy feature set for your use-case.
Thanks
Bevy is the result of the hard work of many people. A huge thanks to all Bevy contributors, the many open source projects that have come before us, the Rust gamedev ecosystem, and the many libraries we build on.
A huge thanks to Bevy's generous sponsors. Bevy will always be free and open source, but it isn't free to make. Please consider sponsoring our work if you like what we're building.
This project is tested with BrowserStack.
License
Bevy is free, open source and permissively licensed! Except where noted (below and/or in individual files), all code in this repository is dual-licensed under either:
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
at your option. This means you can select the license you prefer! This dual-licensing approach is the de-facto standard in the Rust ecosystem and there are very good reasons to include both.
Some of the engine's code carries additional copyright notices and license terms due to their external origins.
These are generally BSD-like, but exact details vary by crate:
If the README of a crate contains a 'License' header (or similar), the additional copyright notices and license terms applicable to that crate will be listed.
The above licensing requirement still applies to contributions to those crates, and sections of those crates will carry those license terms.
The license field of each crate will also reflect this.
For example, bevy_mikktspace
has code under the Zlib license (as well as a copyright notice when choosing the MIT license).
The assets included in this repository (for our examples) typically fall under different open licenses. These will not be included in your game (unless copied in by you), and they are not distributed in the published bevy crates. See CREDITS.md for the details of the licenses of those files.
Your contributions
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.