What is the right way to run code that would normally run on (fixed) update when time scale is set to zero?

Hey!
I have a case where a game is paused using Time.timeScale = 0.0f;, but various pieces of code that are usually run on update (code related to rendering) and fixed update (code related to physics) should still run.

  • What would be a correct way to achieve this?
  • Is there a way to make physics work with timeScale set to 0? (see example 2. below)

So far I have been trying to do this using coroutines, here are 2 examples for Update and FixedUpdate:

  1. Here is an example of a coroutine that sets a light’s intensity from 0 to 1 in 10s in sync with the frame rate (which would usually be achieved by running code in Update or in a coroutine using Time.deltaTime and yield return null):
private IEnumerator MyCustomUpdate()
{
    // Initialize
    Light light = GetComponent<Light>();
    float timer = 0.0f;
    float duration = 10.0f;

    // Run animation
    while (timer < duration)
    {
        light.intensity = timer / duration;
        timer += Time.unscaledDeltaTime;
        yield return new WaitForEndOfFrame();
    }
}
  1. The same could be done with code related to physics, but there I doubt this would actually work as physics updates are no longer performed since Time.timeScale is 0? So this piece of code would allow my rigidbody to be moved while the game is paused, but no physics interaction (OnCollisionEnter, OnTriggerEnter, etc.) would occur, right?
private IEnumerator MyCustomFixedUpdate()
{
    // Initialize
    Rigidbody myRigidbody = GetComponent<Rigidbody>();
    float movingSpeed = 1.0f;

    // Run animation
    while (Time.timeScale == 0.0f)
    {
        Vector3 force = Time.fixedUnscaledDeltaTime * movingSpeed * movingInput; // Assuming that movingInput is a vector set somewhere else using the input system
        myRigidbody.AddForce(force);
        yield return new WaitForEndOfFrame();
    }
}

Thanks for your help!

Physics doesn’t run while Time.timeScale is 0. The internal physics update method is not invoked at all.

In your second example, what happens is that you’re calling AddForce a bunch of times, which just accumulates the force values internally. Nothing at all happens in the physics world. No rigidbodies moving, no phsyics interactions. The next time the physics update method is invoked, it will encounter a huge force value accumulated, and will apply it to the rigidbody in a single physics update.

Moving a Rigidbody while Time.timeScale is 0 could be done by updating the physics world manually. You can do so by setting Physics.simulationMode to SimulationMode.Script, and then calling Physics.Simulate.

That would affect the entire physics world: all rigidbodies, OnCollision events, etc. However, FixedUpdate won’t be invoked while Time.timeScale is zero! Calling Physics.Simulate in that situation would update the physics world, but any physics-related or physics-dependent code in FixedUpdate wouldn’t be executed.

My advice would be rethinking the design to figure out some way to allow either not setting Time.timeScale to zero, or avoid the need to physically simulate Rigidbodies when it’s zero.

2 Likes