Crates.io | bevy_tweening |
lib.rs | bevy_tweening |
version | 0.12.0 |
source | src |
created_at | 2021-12-24 11:19:29.181197 |
updated_at | 2024-12-07 20:43:48.804423 |
description | Tweening animation plugin for the Bevy game engine |
homepage | https://github.com/djeedai/bevy_tweening |
repository | https://github.com/djeedai/bevy_tweening |
max_upload_size | |
id | 502629 |
size | 994,188 |
Tweening animation plugin for the Bevy game engine.
Add to Cargo.toml
:
[dependencies]
bevy_tweening = "0.12"
This crate supports the following features:
Feature | Default | Description |
---|---|---|
bevy_asset |
Yes | Enable animating Bevy assets (Asset ) in addition of components. |
bevy_sprite |
Yes | Includes built-in lenses for some Sprite -related components. |
bevy_ui |
Yes | Includes built-in lenses for some UI-related components. |
bevy_text |
Yes | Includes built-in lenses for some Text -related components. |
Add the TweeningPlugin
to your app:
App::default()
.add_plugins(DefaultPlugins)
.add_plugins(TweeningPlugin)
.run();
This provides the basic setup for using 🍃 Bevy Tweening. However, additional setup is required depending on the components and assets you want to animate:
To ensure a component C
is animated, the component_animator_system::<C>
system must run each frame, in addition of adding an Animator::<C>
component to the same Entity as C
.
To ensure an asset A
is animated, the asset_animator_system::<A>
system must run each frame, in addition of adding an AssetAnimator<A>
component to any Entity. Animating assets also requires the bevy_asset
feature (enabled by default).
By default, 🍃 Bevy Tweening adopts a minimalist approach, and the TweeningPlugin
will only add systems to animate components and assets for which a Lens
is provided by 🍃 Bevy Tweening itself. This means that any other Bevy component or asset (either built-in from Bevy itself, or custom) requires manually scheduling the appropriate system.
Component or Asset | Animation system added by TweeningPlugin ? |
---|---|
Transform |
Yes |
Sprite |
Only if bevy_sprite feature |
ColorMaterial |
Only if bevy_sprite feature |
Node |
Only if bevy_ui feature |
TextColor |
Only if bevy_text feature |
All other components | No |
To add a system for a component C
, use:
app.add_systems(Update, component_animator_system::<C>.in_set(AnimationSystem::AnimationUpdate));
Similarly for an asset A
, use:
app.add_systems(Update, asset_animator_system::<A>.in_set(AnimationSystem::AnimationUpdate));
Animate the transform position of an entity by creating a Tween
animation for the transform, and adding an Animator
component with that tween:
// Create a single animation (tween) to move an entity.
let tween = Tween::new(
// Use a quadratic easing on both endpoints.
EaseFunction::QuadraticInOut,
// Animation time (one way only; for ping-pong it takes 2 seconds
// to come back to start).
Duration::from_secs(1),
// The lens gives the Animator access to the Transform component,
// to animate it. It also contains the start and end values associated
// with the animation ratios 0. and 1.
TransformPositionLens {
start: Vec3::ZERO,
end: Vec3::new(1., 2., -4.),
},
)
// Repeat twice (one per way)
.with_repeat_count(RepeatCount::Finite(2))
// After each iteration, reverse direction (ping-pong)
.with_repeat_strategy(RepeatStrategy::MirroredRepeat);
commands.spawn((
// Spawn a Sprite entity to animate the position of.
Sprite {
color: Color::RED,
custom_size: Some(Vec2::new(size, size)),
..default()
},
// Add an Animator component to control and execute the animation.
Animator::new(tween),
));
Bevy Tweening supports several types of tweenables, building blocks that can be combined to form complex animations. A tweenable is a type implementing the Tweenable<T>
trait.
Tween
- A simple tween (easing) animation between two values.Sequence
- A series of tweenables executing in series, one after the other.Tracks
- A collection of tweenables executing in parallel.Delay
- A time delay.Most tweenables can be chained with the then()
operator:
// Produce a sequence executing 'tween1' then 'tween2'
let tween1 = Tween { [...] }
let tween2 = Tween { [...] }
let seq = tween1.then(tween2);
A small number of predefined lenses are available for the most common use cases, which also serve as examples. Users are encouraged to write their own lens to tailor the animation to their use case.
The naming scheme for predefined lenses is "<TargetName><FieldName>Lens"
, where <TargetName>
is the name of the target Bevy component or asset type which is queried by the internal animation system to be modified, and <FieldName>
is the field which is mutated in place by the lens. All predefined lenses modify a single field. Custom lenses can be written which modify multiple fields at once.
Target Component | Animated Field | Lens | Feature |
---|---|---|---|
Transform |
translation |
TransformPositionLens |
|
rotation (Quat )¹ |
TransformRotationLens |
||
rotation (angle)² |
TransformRotateXLens |
||
rotation (angle)² |
TransformRotateYLens |
||
rotation (angle)² |
TransformRotateZLens |
||
rotation (angle)² |
TransformRotateAxisLens |
||
scale |
TransformScaleLens |
||
Sprite |
color |
SpriteColorLens |
bevy_sprite |
Node |
position |
UiPositionLens |
bevy_ui |
BackgroundColor |
UiBackgroundColorLens |
bevy_ui |
|
TextColor |
TextColorLens |
bevy_text |
There are two ways to interpolate rotations. See the comparison of rotation lenses for details:
Quat::slerp()
.Asset animation always requires the bevy_asset
feature.
Target Asset | Animated Field | Lens | Feature |
---|---|---|---|
ColorMaterial |
color |
ColorMaterialColorLens |
bevy_asset + bevy_sprite |
A custom lens allows animating any field or group of fields of a Bevy component or asset. A custom lens is a type implementing the Lens
trait, which is generic over the type of component or asset.
struct MyXAxisLens {
start: f32,
end: f32,
}
impl Lens<Transform> for MyXAxisLens {
fn lerp(&mut self, target: &mut Transform, ratio: f32) {
let start = Vec3::new(self.start, 0., 0.);
let end = Vec3::new(self.end, 0., 0.);
target.translation = start + (end - start) * ratio;
}
}
Note that the lens always linearly interpolates the field(s) of the component or asset. The type of easing applied modifies the rate at which the ratio
parameter evolves, and is applied before the lerp()
function is invoked.
The basic formula for lerp (linear interpolation) is either of:
start + (end - start) * scalar
start * (1.0 - scalar) + end * scalar
The two formulations are mathematically equivalent, but one may be more suited than the other depending on the type interpolated and the operations available, and the potential floating-point precision errors.
Custom components are animated via a lens like the ones described in Bevy Components.
#[derive(Component)]
struct MyCustomComponent(f32);
struct MyCustomLens {
start: f32,
end: f32,
}
impl Lens<MyCustomComponent> for MyCustomLens {
fn lerp(&mut self, target: &mut MyCustomComponent, ratio: f32) {
target.0 = self.start + (self.end - self.start) * ratio;
}
}
Then, in addition, the system component_animator_system::<CustomComponent>
needs to be added to the application, as described in System Setup. This system will extract each frame all CustomComponent
instances with an Animator<CustomComponent>
on the same entity, and animate the component via its animator.
The process is similar to custom components, creating a custom lens for the custom asset. The system to add is asset_animator_system::<CustomAsset>
, as described in System Setup. This requires the bevy_asset
feature (enabled by default).
See the examples/
folder.
menu
cargo run --example menu --features="bevy/bevy_winit"
sprite_color
cargo run --example sprite_color --features="bevy/bevy_winit"
transform_rotation
cargo run --example transform_rotation --features="bevy/bevy_winit"
transform_translation
cargo run --example transform_translation --features="bevy/bevy_winit"
colormaterial_color
cargo run --example colormaterial_color --features="bevy/bevy_winit"
ui_position
cargo run --example ui_position --features="bevy/bevy_winit"
sequence
cargo run --example sequence --features="bevy/bevy_winit"
Many ease functions are available from bevy_math
:
f(t) = t
f(t) = t²
f(t) = -(t * (t - 2.0))
Behaves as
EaseFunction::QuadraticIn
for t < 0.5 and asEaseFunction::QuadraticOut
for t >= 0.5
f(t) = t³
f(t) = (t - 1.0)³ + 1.0
Behaves as
EaseFunction::CubicIn
for t < 0.5 and asEaseFunction::CubicOut
for t >= 0.5
f(t) = t⁴
f(t) = (t - 1.0)³ * (1.0 - t) + 1.0
Behaves as
EaseFunction::QuarticIn
for t < 0.5 and asEaseFunction::QuarticOut
for t >= 0.5
f(t) = t⁵
f(t) = (t - 1.0)⁵ + 1.0
Behaves as
EaseFunction::QuinticIn
for t < 0.5 and asEaseFunction::QuinticOut
for t >= 0.5
f(t) = 1.0 - cos(t * π / 2.0)
f(t) = sin(t * π / 2.0)
Behaves as
EaseFunction::SineIn
for t < 0.5 and asEaseFunction::SineOut
for t >= 0.5
f(t) = 1.0 - sqrt(1.0 - t²)
f(t) = sqrt((2.0 - t) * t)
Behaves as
EaseFunction::CircularIn
for t < 0.5 and asEaseFunction::CircularOut
for t >= 0.5
f(t) = 2.0^(10.0 * (t - 1.0))
f(t) = 1.0 - 2.0^(-10.0 * t)
Behaves as
EaseFunction::ExponentialIn
for t < 0.5 and asEaseFunction::ExponentialOut
for t >= 0.5
f(t) = -2.0^(10.0 * t - 10.0) * sin((t * 10.0 - 10.75) * 2.0 * π / 3.0)
f(t) = 2.0^(-10.0 * t) * sin((t * 10.0 - 0.75) * 2.0 * π / 3.0) + 1.0
Behaves as
EaseFunction::ElasticIn
for t < 0.5 and asEaseFunction::ElasticOut
for t >= 0.5
f(t) = 2.70158 * t³ - 1.70158 * t²
f(t) = 1.0 + 2.70158 * (t - 1.0)³ - 1.70158 * (t - 1.0)²
Behaves as
EaseFunction::BackIn
for t < 0.5 and asEaseFunction::BackOut
for t >= 0.5
bouncy at the start!
bouncy at the end!
Behaves as
EaseFunction::BounceIn
for t < 0.5 and asEaseFunction::BounceOut
for t >= 0.5
n
steps connecting the start and the end
f(omega,t) = 1 - (1 - t)²(2sin(omega * t) / omega + cos(omega * t))
, parametrized by omega
The main
branch is compatible with the latest Bevy release.
Compatibility of bevy_tweening
versions:
bevy_tweening |
bevy |
---|---|
0.12 |
0.15 |
0.11 |
0.14 |
0.10 |
0.13 |
0.9 |
0.12 |
0.8 |
0.11 |
0.7 |
0.10 |
0.6 |
0.9 |
0.5 |
0.8 |
0.4 |
0.7 |
0.2 -0.3 |
0.6 |
0.1 |
0.5 |
Due to the fast-moving nature of Bevy and frequent breaking changes, and the limited resources to maintan 🍃 Bevy Tweening, the main
(unreleased) Bevy branch is not supported. However the bevy_tweening
crate is upgraded shortly after each new bevy
release to support the newly released version.
bevy_easings
The bevy_tweening
library started as a fork of the bevy_easings
library by François Mocker, with the goals to:
bevy_easings
does, and instead mutate the assets (and, by similarity, the components too) in-place without making a copy. The in-place mutation also allows a more optimal interpolation limited to modifying the fields of interest only, instead of creating a new copy of the entire component each tick.