Quick answer: Unity multiplies AudioSource.pitch by Time.timeScale. Compensate by setting AudioSource.pitch = 1 / Time.timeScale for sounds you want unaffected, or use AudioMixer snapshots for proper cinematic slow-motion audio.
Here is how to fix Unity Time.timeScale affecting audio pitch. You build a bullet-time ability that drops Time.timeScale to 0.3 during a boss fight. The visuals look great. The audio sounds underwater — every footstep, gunshot, and piece of dialogue plays at a third of the speed with the pitch dropped an octave. You set up a pause menu with Time.timeScale = 0 and all audio stops entirely. The menu music should keep playing but it does not. Both problems have the same root cause.
The Symptom
Audio pitch and playback speed change with Time.timeScale. At timeScale = 0.5, audio plays at half speed and half pitch. At timeScale = 0, audio stops. At timeScale = 2, audio plays at double speed (chipmunks). This affects every AudioSource in the scene — gameplay, UI, music — because Unity applies the scaling globally.
In the editor, you can confirm by opening the Audio settings and watching the AudioSource inspector during play. The effective pitch displayed is your set pitch multiplied by timeScale.
What Causes This
Unity deliberately scales audio with timeScale. This is a feature, not a bug, and it is useful for many games. A slow-motion replay with audio that slows to match looks correct. A fast-forward montage with audio that speeds up matches the visual tempo. For these use cases, the default behavior is what you want.
But the scaling applies to everything. UI beeps, menu music, narrator voiceover, pause-menu sounds — all affected. If you want some sounds to follow the time scale and others to ignore it, you have to opt out explicitly per AudioSource.
AudioListener.pause on timeScale = 0. When timeScale is 0, the effective audio pitch becomes 0 and audio essentially pauses. If you have a pause menu music track that should keep playing while the game is paused, it stops along with everything else.
The Fix
Step 1: Compensate pitch on individual sources. For AudioSources that should play at normal speed regardless of timeScale, multiply their pitch by the inverse of timeScale.
using UnityEngine;
[RequireComponent(typeof(AudioSource))]
public class UnscaledAudio : MonoBehaviour
{
private AudioSource audioSrc;
private float basePitch;
void Awake()
{
audioSrc = GetComponent<AudioSource>();
basePitch = audioSrc.pitch;
}
void Update()
{
float scale = Time.timeScale;
if (scale > 0.001f)
audioSrc.pitch = basePitch / scale;
}
}
This works for slow-down and speed-up but not for timeScale = 0 (division by zero would make pitch infinite). For the paused case, either guard against zero or rely on AudioListener.pause control.
Step 2: Use AudioMixer with snapshots for cinematic slow-mo. The pitch-compensation hack produces audio that sounds correct but lacks the atmospheric quality of true slow-motion audio. Games like Max Payne and Superhot use heavy low-pass filtering and bass emphasis during bullet time. You get this with AudioMixer snapshots.
Create an AudioMixer asset. Add a Low Pass Filter to the Master group. Create two snapshots: “Normal” (filter cutoff 22000, default) and “BulletTime” (filter cutoff 800, volume -6 dB). In code, transition between them.
using UnityEngine;
using UnityEngine.Audio;
public class BulletTimeController : MonoBehaviour
{
[SerializeField] private AudioMixerSnapshot normal;
[SerializeField] private AudioMixerSnapshot bulletTime;
public void EnterBulletTime()
{
Time.timeScale = 0.3f;
bulletTime.TransitionTo(0.2f);
}
public void ExitBulletTime()
{
Time.timeScale = 1f;
normal.TransitionTo(0.5f);
}
}
This decouples audio mood from time scale entirely. Slow-mo now sounds like slow-mo (muffled, dreamy) without the warbly pitch distortion.
Step 3: Handle paused audio with AudioListener.pause. For a pause menu that should stop gameplay sounds but allow menu music, set AudioListener.pause = true instead of Time.timeScale = 0. For the music AudioSource, set ignoreListenerPause = true.
public void PauseGame()
{
Time.timeScale = 0f;
AudioListener.pause = true;
// Music AudioSource has ignoreListenerPause = true,
// so it keeps playing
}
public void ResumeGame()
{
Time.timeScale = 1f;
AudioListener.pause = false;
}
Note that AudioListener.pause freezes the audio clock for non-ignoring sources, so positional sound and 3D attenuation stay correct when resumed.
UI Audio and TimeScale
UI button click sounds suffer the most from this problem — during pause or slow-mo, they sound wrong. Route all UI AudioSources through a dedicated AudioMixer group and set their group’s pitch override to 1. Alternatively, attach UnscaledAudio from the script above to every UI audio source. A global “UI audio” prefab with this behavior baked in prevents the issue from reappearing.
Alternative: Audio Timeline Separate From Game Timeline
For games that frequently manipulate time scale, consider a separate audio time tracker. Update audio-driven systems with Time.unscaledDeltaTime instead of Time.deltaTime. This keeps audio timing decoupled from gameplay timing, which is usually more desirable than the default “everything slows together.”
“The default is ‘everything follows timeScale.’ Cinematic slow-mo does not actually want that. Audio, UI, and ambient layers usually want their own clock.”
Related Issues
For audio mixer transitions, see Audio Mixer Snapshot Not Transitioning. For general audio issues, Unity AudioSource Not Playing covers basic AudioSource debugging.
AudioMixer snapshots make slow-motion sound cinematic. Pitch compensation keeps it clean.