Smooth slow motion in Unity with physics

Perfectly smooth slow-motion effects in Unity without stuttering

Smooth slow motion in Unity with physics

This short guide will show you how to create a perfectly smooth slow-motion effect in Unity without stuttering or lagging.

You can control the speed of time in Unity with the Time.timeScale variable. Setting it to 0.5f makes time twice go as slow and setting it to 2f makes time go (you guessed it) twice as fast.

Changing it then should solve all our slow-motion needs, right? Here I have a sample project where the player is controlling a ball and I have set Time.timeScale = 0.25f to achieve the desired slow-motion effect.

As you can see, the result is rather unpleasant to look at. The problem is that the ball is using Unity's physics system to simulate movement and gravity. Setting timeScale  to a lower value than 1f does indeed produce technically correct slow motion, but it will look really bad.

This is because the physics system runs on its own timer - 50 frames per second by default. To get rid of the stuttering movement, we have to manipulate the physics timer and timeScale at the same time.

Time.timeScale = 0.25f;
Time.fixedDeltaTime = 0.25f * 0.02f;

To make it more modular, we can use a variable for the new time scale.

Time.timeScale = newTimeScale;
Time.fixedDeltaTime = Time.timeScale * 0.02f;

Now our slow-motion effect looks a lot better:

And here is the comparison:

Optional steps

If you just wanted a simple slow-motion effect, you are done here. However, if you intend to change the time scale at multiple places in your code, there is a possibility that you forget to change timeScale and fixedDeltaTime at the same time. This can result in frustrating debugging sessions (speaking from experience).

I solved this problem by creating a dedicated TimeManager class that handles everything time-related. I have a function that sets the timescale for the slow-motion effect, and I use it every time I'd like to manipulate time. Don't forget to create an empty GameObject and add this script to it as a component!

public class TimeManager : MonoBehaviour {
    // static reference so the class is always accessible
	public static TimeManager instance;

    void Awake() {
		// set the reference to itself
        instance = this;
    }

	// use this function every time you change the time scale like this:
    // Timemanager.instance.ChangeTimeScale(0.5f);
    public void ChangeTimeScale(float newTimeScale) {
		Time.timeScale = newTimeScale;
		Time.fixedDeltaTime = Time.timeScale * 0.02f;
    }
}

If you have any questions or have found any errors in the guide, please send an e-mail to contact@gamedevbrew.com