diff --git a/CHANGELOG.md b/CHANGELOG.md
index ce467c56fd61253a0b5575f578fcd579318dbe77..3604dc7521e46740603483497b70ab621585c1ac 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 - Add `is_forward()` and `is_backward()` convenience helpers to `TweeningDirection`.
 - Add `Tween::set_direction()` and `Tween::with_direction()` which allow configuring the playback direction of a tween, allowing to play it backward from end to start.
+- Support dynamically changing an animation's speed with `Animator::set_speed`
 
 ## [0.4.0] - 2022-04-16
 
diff --git a/examples/transform_rotation.rs b/examples/transform_rotation.rs
index 6eab8618d1202279a1ebc8e8d713bf3b174877f5..cd100ff868ab0928ae237ca8ec0b257e61e2aee0 100644
--- a/examples/transform_rotation.rs
+++ b/examples/transform_rotation.rs
@@ -1,7 +1,9 @@
 use bevy::prelude::*;
+use bevy_inspector_egui::{Inspectable, InspectorPlugin};
+
 use bevy_tweening::{lens::*, *};
 
-fn main() -> Result<(), Box<dyn std::error::Error>> {
+fn main() {
     App::default()
         .insert_resource(WindowDescriptor {
             title: "TransformRotationLens".to_string(),
@@ -12,10 +14,22 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
         })
         .add_plugins(DefaultPlugins)
         .add_plugin(TweeningPlugin)
+        .add_plugin(InspectorPlugin::<Options>::new())
         .add_startup_system(setup)
+        .add_system(update_animation_speed)
         .run();
+}
 
-    Ok(())
+#[derive(Copy, Clone, PartialEq, Inspectable)]
+struct Options {
+    #[inspectable(min = 0.01, max = 100.)]
+    speed: f32,
+}
+
+impl Default for Options {
+    fn default() -> Self {
+        Self { speed: 1. }
+    }
 }
 
 fn setup(mut commands: Commands) {
@@ -96,3 +110,13 @@ fn setup(mut commands: Commands) {
         }
     }
 }
+
+fn update_animation_speed(options: Res<Options>, mut animators: Query<&mut Animator<Transform>>) {
+    if !options.is_changed() {
+        return;
+    }
+
+    for mut animator in animators.iter_mut() {
+        animator.set_speed(options.speed);
+    }
+}
diff --git a/examples/transform_translation.rs b/examples/transform_translation.rs
index 007373f4e7aaf939e7bbaf83ced98f9116ac2f37..a1e996b7228adb1744f92f4272fd5fa4edda1a91 100644
--- a/examples/transform_translation.rs
+++ b/examples/transform_translation.rs
@@ -1,7 +1,9 @@
 use bevy::prelude::*;
+use bevy_inspector_egui::{Inspectable, InspectorPlugin};
+
 use bevy_tweening::{lens::*, *};
 
-fn main() -> Result<(), Box<dyn std::error::Error>> {
+fn main() {
     App::default()
         .insert_resource(WindowDescriptor {
             title: "TransformPositionLens".to_string(),
@@ -12,10 +14,22 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
         })
         .add_plugins(DefaultPlugins)
         .add_plugin(TweeningPlugin)
+        .add_plugin(InspectorPlugin::<Options>::new())
         .add_startup_system(setup)
+        .add_system(update_animation_speed)
         .run();
+}
 
-    Ok(())
+#[derive(Copy, Clone, PartialEq, Inspectable)]
+struct Options {
+    #[inspectable(min = 0.01, max = 100.)]
+    speed: f32,
+}
+
+impl Default for Options {
+    fn default() -> Self {
+        Self { speed: 1. }
+    }
 }
 
 fn setup(mut commands: Commands) {
@@ -84,3 +98,13 @@ fn setup(mut commands: Commands) {
         x += size * spacing;
     }
 }
+
+fn update_animation_speed(options: Res<Options>, mut animators: Query<&mut Animator<Transform>>) {
+    if !options.is_changed() {
+        return;
+    }
+
+    for mut animator in animators.iter_mut() {
+        animator.set_speed(options.speed);
+    }
+}
diff --git a/examples/ui_position.rs b/examples/ui_position.rs
index 16503cf658fe0d5ea88cd9a6994450b52c0a983c..1778b58eec16463283de0618da4b0a4edeaa7dc3 100644
--- a/examples/ui_position.rs
+++ b/examples/ui_position.rs
@@ -1,7 +1,9 @@
 use bevy::prelude::*;
+use bevy_inspector_egui::{Inspectable, InspectorPlugin};
+
 use bevy_tweening::{lens::*, *};
 
-fn main() -> Result<(), Box<dyn std::error::Error>> {
+fn main() {
     App::default()
         .insert_resource(WindowDescriptor {
             title: "UiPositionLens".to_string(),
@@ -12,10 +14,22 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
         })
         .add_plugins(DefaultPlugins)
         .add_plugin(TweeningPlugin)
+        .add_plugin(InspectorPlugin::<Options>::new())
         .add_startup_system(setup)
+        .add_system(update_animation_speed)
         .run();
+}
 
-    Ok(())
+#[derive(Copy, Clone, PartialEq, Inspectable)]
+struct Options {
+    #[inspectable(min = 0.01, max = 100.)]
+    speed: f32,
+}
+
+impl Default for Options {
+    fn default() -> Self {
+        Self { speed: 1. }
+    }
 }
 
 fn setup(mut commands: Commands) {
@@ -105,3 +119,13 @@ fn setup(mut commands: Commands) {
         x += offset_x;
     }
 }
+
+fn update_animation_speed(options: Res<Options>, mut animators: Query<&mut Animator<Style>>) {
+    if !options.is_changed() {
+        return;
+    }
+
+    for mut animator in animators.iter_mut() {
+        animator.set_speed(options.speed);
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 75624386088df1d65903310cecde4dff2f0bb057..587e67ba8300f4a6b1f24c361b6b86df2927a651 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -147,6 +147,7 @@
 //! [`Transform`]: https://docs.rs/bevy/0.7.0/bevy/transform/components/struct.Transform.html
 
 use bevy::{asset::Asset, prelude::*};
+use std::time::Duration;
 
 use interpolation::Ease as IEase;
 pub use interpolation::EaseFunction;
@@ -304,6 +305,7 @@ pub struct Animator<T: Component> {
     /// Control if this animation is played or not.
     pub state: AnimatorState,
     tweenable: Option<Box<dyn Tweenable<T> + Send + Sync + 'static>>,
+    speed: f32,
 }
 
 impl<T: Component + std::fmt::Debug> std::fmt::Debug for Animator<T> {
@@ -319,6 +321,7 @@ impl<T: Component> Default for Animator<T> {
         Animator {
             state: Default::default(),
             tweenable: None,
+            speed: 1.,
         }
     }
 }
@@ -338,6 +341,20 @@ impl<T: Component> Animator<T> {
         self
     }
 
+    /// Set the initial speed of the animator. See [`Animator::set_speed`] for details.
+    pub fn with_speed(mut self, speed: f32) -> Self {
+        self.speed = speed;
+        self
+    }
+
+    /// Set the animation speed. Defaults to 1.
+    ///
+    /// A speed of 2 means the animation will run twice as fast while a speed of 0.1 will result in
+    /// a 10x slowed animation.
+    pub fn set_speed(&mut self, speed: f32) {
+        self.speed = speed;
+    }
+
     /// Set the top-level tweenable item this animator controls.
     pub fn set_tweenable(&mut self, tween: impl Tweenable<T> + Send + Sync + 'static) {
         self.tweenable = Some(Box::new(tween));
@@ -395,6 +412,21 @@ impl<T: Component> Animator<T> {
         }
     }
 
+    /// Ticks the tween, if present. See [`Tweenable::tick`] for details.
+    pub fn tick(
+        &mut self,
+        delta: Duration,
+        target: &mut T,
+        entity: Entity,
+        event_writer: &mut EventWriter<TweenCompleted>,
+    ) -> Option<TweenState> {
+        if let Some(tweenable) = &mut self.tweenable {
+            Some(tweenable.tick(delta.mul_f32(self.speed), target, entity, event_writer))
+        } else {
+            None
+        }
+    }
+
     /// Stop animation playback and rewind the animation.
     ///
     /// This changes the animator state to [`AnimatorState::Paused`] and rewind its tweenable.
@@ -420,6 +452,7 @@ pub struct AssetAnimator<T: Asset> {
     pub state: AnimatorState,
     tweenable: Option<Box<dyn Tweenable<T> + Send + Sync + 'static>>,
     handle: Handle<T>,
+    speed: f32,
 }
 
 impl<T: Asset + std::fmt::Debug> std::fmt::Debug for AssetAnimator<T> {
@@ -436,6 +469,7 @@ impl<T: Asset> Default for AssetAnimator<T> {
             state: Default::default(),
             tweenable: None,
             handle: Default::default(),
+            speed: 1.,
         }
     }
 }
@@ -456,6 +490,20 @@ impl<T: Asset> AssetAnimator<T> {
         self
     }
 
+    /// Set the initial speed of the animator. See [`Animator::set_speed`] for details.
+    pub fn with_speed(mut self, speed: f32) -> Self {
+        self.speed = speed;
+        self
+    }
+
+    /// Set the animation speed. Defaults to 1.
+    ///
+    /// A speed of 2 means the animation will run twice as fast while a speed of 0.1 will result in
+    /// a 10x slowed animation.
+    pub fn set_speed(&mut self, speed: f32) {
+        self.speed = speed;
+    }
+
     /// Set the top-level tweenable item this animator controls.
     pub fn set_tweenable(&mut self, tween: impl Tweenable<T> + Send + Sync + 'static) {
         self.tweenable = Some(Box::new(tween));
@@ -513,6 +561,21 @@ impl<T: Asset> AssetAnimator<T> {
         }
     }
 
+    /// Ticks the tween, if present. See [`Tweenable::tick`] for details.
+    pub fn tick(
+        &mut self,
+        delta: Duration,
+        target: &mut T,
+        entity: Entity,
+        event_writer: &mut EventWriter<TweenCompleted>,
+    ) -> Option<TweenState> {
+        if let Some(tweenable) = &mut self.tweenable {
+            Some(tweenable.tick(delta.mul_f32(self.speed), target, entity, event_writer))
+        } else {
+            None
+        }
+    }
+
     /// Stop animation playback and rewind the animation.
     ///
     /// This changes the animator state to [`AnimatorState::Paused`] and rewind its tweenable.
diff --git a/src/plugin.rs b/src/plugin.rs
index 4e68d66fcbbbef8e692dbdb465d254e10601248d..ff98803a91f601e297e5f4015b4b26e91ffb29dc 100644
--- a/src/plugin.rs
+++ b/src/plugin.rs
@@ -57,9 +57,7 @@ pub fn component_animator_system<T: Component>(
 ) {
     for (entity, ref mut target, ref mut animator) in query.iter_mut() {
         if animator.state != AnimatorState::Paused {
-            if let Some(tweenable) = animator.tweenable_mut() {
-                tweenable.tick(time.delta(), target, entity, &mut event_writer);
-            }
+            animator.tick(time.delta(), target, entity, &mut event_writer);
         }
     }
 }
@@ -76,9 +74,7 @@ pub fn asset_animator_system<T: Asset>(
     for (entity, ref mut animator) in query.iter_mut() {
         if animator.state != AnimatorState::Paused {
             if let Some(target) = assets.get_mut(animator.handle()) {
-                if let Some(tweenable) = animator.tweenable_mut() {
-                    tweenable.tick(time.delta(), target, entity, &mut event_writer);
-                }
+                animator.tick(time.delta(), target, entity, &mut event_writer);
             }
         }
     }