#动画 #bevy #缓动 #补间 #游戏引擎

bevy_tweening

Bevy游戏引擎的补间动画插件

14个版本 (破坏性更新)

0.11.0 2024年7月8日
0.10.0 2024年2月27日
0.9.0 2023年11月7日
0.8.0 2023年7月12日
0.1.0 2021年12月24日

#14 in 游戏开发

Download history 552/week @ 2024-04-27 472/week @ 2024-05-04 411/week @ 2024-05-11 455/week @ 2024-05-18 405/week @ 2024-05-25 437/week @ 2024-06-01 365/week @ 2024-06-08 386/week @ 2024-06-15 341/week @ 2024-06-22 271/week @ 2024-06-29 438/week @ 2024-07-06 333/week @ 2024-07-13 400/week @ 2024-07-20 739/week @ 2024-07-27 824/week @ 2024-08-03 690/week @ 2024-08-10

2,689 下载/月
4 包 中使用

MIT/Apache

800KB
3K SLoC

🍃 Bevy Tweening

License: MIT/Apache Doc Crate Build Status Coverage Status Bevy tracking

Bevy游戏引擎的补间动画插件。

功能

  • 可以动画化任何组件或资源的任何字段,包括自定义的。
  • 可以并行地对每个组件/资源运行多个补间(动画)。
  • 可以一个接一个地链式多个补间(动画),以创建复杂的动画。
  • 当补间完成时,可以触发一个Bevy事件或调用一个回调函数。

用法

依赖项

添加到 Cargo.toml

[dependencies]
bevy_tweening = "0.11"

此包支持以下功能

功能 默认 描述
bevy_asset 启用对组件(以及资源)进行动画化。
bevy_sprite 包括一些与 Sprite 相关组件的内置透镜。
bevy_ui 包括一些与UI相关组件的内置透镜。
bevy_text 包括一些与 Text 相关组件的内置透镜。

系统配置

TweeningPlugin 添加到您的应用程序中

App::default()
    .add_plugins(DefaultPlugins)
    .add_plugins(TweeningPlugin)
    .run();

这提供了使用 🍃 Bevy Tweening 的基本设置。但是,根据您想要动画化的组件和资源,可能还需要进行额外的设置。

  • 为了确保组件 C 被动画化,必须在每帧运行 component_animator_system::<C> 系统并添加一个 Animator::<C> 组件到与 C 相同的实体。

  • 为了确保资源 A 被动画化,必须在每帧运行 asset_animator_system::<A> 系统并添加一个 AssetAnimator<A> 组件到任何实体。动画资源还需要启用 bevy_asset 功能(默认启用)。

默认情况下,🍃 Bevy Tweening 采用极简主义方法,TweeningPlugin 将仅添加用于动画组件和资产的系统,前提是 🍃 Bevy Tweening 本身提供了 Lens。这意味着任何其他 Bevy 组件或资产(无论是来自 Bevy 本身的内置组件,还是自定义组件)都需要手动安排适当的系统。

组件或资产 TweeningPlugin 添加的动画系统?
变换
精灵 仅当启用 bevy_sprite 功能时
颜色材质 仅当启用 bevy_sprite 功能时
样式 仅当启用 bevy_ui 功能时
文本 仅当启用 bevy_text 功能时
所有其他组件

要为组件 C 添加系统,使用

app.add_systems(Update, component_animator_system::<C>.in_set(AnimationSystem::AnimationUpdate));

类似地,对于资产 A,使用

app.add_systems(Update, asset_animator_system::<A>.in_set(AnimationSystem::AnimationUpdate));

动画组件

通过为变换创建一个 Tween 动画来动画化实体的变换位置,并添加一个带有该缓动的 Animator 组件

// 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.
    SpriteBundle {
        sprite: Sprite {
            color: Color::RED,
            custom_size: Some(Vec2::new(size, size)),
            ..default()
        },
        ..default()
    },
    // Add an Animator component to control and execute the animation.
    Animator::new(tween),
));

动画链

Bevy Tweening 支持几种类型的 可缓动 构建块,这些构建块可以组合成复杂的动画。可缓动是一种实现 Tweenable<T> 特性的类型。

  • Tween - 两个值之间的简单缓动(缓和)动画。
  • Sequence - 一系列依次执行的缓动。
  • Tracks - 一系列并行执行的缓动。
  • Delay - 时间延迟。

大多数缓动都可以通过 then() 操作符进行链式调用

// Produce a sequence executing 'tween1' then 'tween2'
let tween1 = Tween { [...] }
let tween2 = Tween { [...] }
let seq = tween1.then(tween2);

预定义的镜头

对于最常用的用例,提供了一些预定义的镜头,这些镜头也作为示例。强烈建议用户编写自己的镜头,以便根据他们的用例调整动画。

预定义镜头的命名方案为 "<TargetName><FieldName>Lens",其中 <TargetName> 是要修改的内部动画系统查询的目标 Bevy 组件或资产类型的名称,而 <FieldName> 是由镜头就地修改的字段。所有预定义的镜头都修改单个字段。可以编写修改多个字段的自定义镜头。

Bevy 组件

目标组件 动画字段 镜头 功能
变换 平移 TransformPositionLens
rotationQuat)¹ TransformRotationLens
rotation (角度)² TransformRotateXLens
rotation (角度)² TransformRotateYLens
rotation (角度)² TransformRotateZLens
rotation (角度)² TransformRotateAxisLens
缩放 TransformScaleLens
精灵 颜色 SpriteColorLens bevy_sprite
样式 位置 UiPositionLens bevy_ui
背景颜色 UiBackgroundColorLens bevy_ui
文本 文本样式::颜色 TextColorLens bevy_text

¹ 通过 Quat::slerp() 使用最短路径插值在两个旋转之间。

² 基于角度的插值,适用于超过半圈的旋转。

有关旋转镜头的比较,请参阅 详情

Bevy 资产

资产动画始终需要 bevy_asset 功能。

目标资产 动画字段 镜头 功能
颜色材质 颜色 颜色材质颜色透镜 bevy_asset + bevy_sprite

自定义透镜

自定义透镜允许动画化 Bevy 组件或资产的任何字段或字段组。自定义透镜是实现 Lens 特质的类型,它是组件或资产类型的泛型。

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;
    }
}

请注意,透镜始终以 线性 的方式插值组件或资产的字段。应用的缓动类型会改变 ratio 参数演变的速率,并在调用 lerp() 函数之前应用。

lerp(线性插值)的基本公式可以是以下两种之一

  • 开始+ (结束-开始) *标量
  • 开始* (1.0 -标量) +结束*标量

这两种公式在数学上是等价的,但根据要插值的类型、可用的操作以及潜在的浮点精度误差,其中一种可能比另一种更适合。

自定义组件支持

自定义组件通过类似于 Bevy 组件 中描述的自定义透镜进行动画化。

#[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;
    }
}

然后,还需要添加 component_animator_system::<CustomComponent> 系统到应用程序中,如 系统设置 中所述。此系统将提取每个帧上具有相同实体的所有 CustomComponent 实例,并通过其动画器对其组件进行动画化。

自定义资产支持

过程与自定义组件类似,为自定义资产创建自定义透镜。需要添加的系统是 asset_animator_system::<CustomAsset>,如 系统设置 中所述。这需要 bevy_asset 功能(默认启用)。

示例

请参阅 examples/ 文件夹。

菜单

cargo run --example menu --features="bevy/bevy_winit"

menu

精灵颜色

cargo run --example sprite_color --features="bevy/bevy_winit"

sprite_color

变换旋转

cargo run --example transform_rotation --features="bevy/bevy_winit"

sprite_color

变换平移

cargo run --example transform_translation --features="bevy/bevy_winit"

sprite_color

颜色材质颜色

cargo run --example colormaterial_color --features="bevy/bevy_winit"

colormaterial_color

UI 位置

cargo run --example ui_position --features="bevy/bevy_winit"

ui_position

序列

cargo run --example sequence --features="bevy/bevy_winit"

sequence

缓动函数

提供了许多 缓动函数

  • 二次内
  • 二次外
  • 二次内外
  • 三次内
  • 三次外
  • 三次内外
  • 四次内
  • 四次外
  • 四次内外
  • 五次内
  • 五次外
  • 五次内外
  • 正弦内
  • 正弦外
  • 正弦内外
  • 圆形内
  • 圆形外
  • 圆形内外
  • 指数内
  • 指数外
  • 指数内外
  • 弹性内
  • 弹性外
  • 弹性内外
  • 回弹内
  • 回弹外
  • 回弹内外
  • 弹跳内
  • 弹跳外
  • 弹跳内外

兼容的 Bevy 版本

main 分支与最新的 Bevy 版本兼容。

bevy_tweening 版本的兼容性

bevy_tweening bevy
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

由于 Bevy 发展迅速且经常进行破坏性更改,以及维护 🍃 Bevy Tweening 的资源有限,因此不支持(未发布)的 main Bevy 分支。然而,每次新的 bevy 发布后,都会升级 bevy_tweening crate 以支持新发布的版本。

bevy_easings 的比较

bevy_tweening 库最初是 François Mocker 的 bevy_easings 库的分支,目的是

  • 探索基于透镜而不是通用类型的替代设计,以用于每个easer/animator。这减少了所需的通用类型数量,并有望减少代码大小,以及执行插值所需系统的数量。
  • 改进资产插值以避免像bevy_easings那样创建许多副本,而是原地修改资产(以及,通过相似性,组件)而不进行复制。原地修改还允许更优化的插值,仅修改感兴趣的领域,而不是在每帧创建整个组件的新副本。

依赖项

~19–58MB
~1M SLoC