Summary
AudioSource is the Unity component that plays audio. It is attached to a GameObject and references an AudioClip asset. For sound effects, the primary method is PlayOneShot, which plays a clip once without interrupting other sounds already playing on the same source. For background music, AudioSource.Play() combined with loop = true is standard. For transient world-positioned sounds (a coin collected, an enemy defeated), the static AudioSource.PlayClipAtPoint plays at a location without requiring an AudioSource on the emitting object.
Key ideas
AudioSource.Play() — plays the assigned clip from the beginning. If called again while playing, it restarts. Use for background music, ambient loops, and single persistent sounds.
AudioSource.PlayOneShot(clip) — plays the given clip once without replacing any currently playing sound on that source. Multiple calls layer on top of each other. Use for sound effects that may fire in rapid succession (coins, footsteps, hits).
AudioSource.PlayClipAtPoint(clip, worldPosition) — static method; no AudioSource component needed on the caller. Spawns a temporary GameObject at the given world position, plays the clip, then destroys itself. Use for pickups, explosions, and any transient world sound.
Looping background music: Set clip, loop = true, volume, then call Play(). Use a dedicated AudioSource component for music — separate from the one used for SFX — so volume can be controlled independently.
AudioListener.volume — a static property (0 to 1) that scales all audio in the game. Setting it to 0f mutes everything; 1f is full volume.
[Range(0f, 1f)] — an Inspector attribute that displays a float field as a slider constrained to the given range. Useful for volume controls.
Mathf.Clamp01(value) — shorthand for Mathf.Clamp(value, 0f, 1f). Use when accepting a volume value from outside code.
In practice
Looping background music:
[Header("Music")]
[SerializeField] private AudioSource musicSource;
[SerializeField] private AudioClip mainTheme;
[SerializeField] [Range(0f, 1f)] private float musicVolume = 0.4f;
private void StartMusic()
{
if (musicSource == null || mainTheme == null) return;
musicSource.clip = mainTheme;
musicSource.loop = true;
musicSource.volume = musicVolume;
musicSource.Play();
}SFX with PlayOneShot (layers, does not interrupt):
[Header("SFX")]
[SerializeField] private AudioSource sfxSource;
[SerializeField] private AudioClip coinClip;
[SerializeField] private AudioClip hitClip;
private void PlaySFX(AudioClip clip)
{
if (clip == null || sfxSource == null) return;
sfxSource.PlayOneShot(clip); // layered — rapid calls don't interrupt
}
// Usage
PlaySFX(coinClip);
PlaySFX(hitClip);PlayClipAtPoint — world-positioned sound, no AudioSource needed:
public void OnCoinCollected(Vector3 worldPosition)
{
if (coinClip != null)
AudioSource.PlayClipAtPoint(coinClip, worldPosition);
}Read this method as an event response, not as an audio loop. Something else in the game detects the coin collection, then passes the coin’s world position into OnCoinCollected. The method checks whether a clip was assigned, plays the sound at that position, and then returns. There is no Update here because sound effects are triggered by game events, not checked every frame.
Global mute toggle:
private bool isMuted = false;
public void ToggleMute()
{
isMuted = !isMuted;
AudioListener.volume = isMuted ? 0f : 1f;
}Adjustable music volume:
public void SetMusicVolume(float volume)
{
musicVolume = Mathf.Clamp01(volume);
if (musicSource != null)
musicSource.volume = musicVolume;
}Recommended setup
For a typical 2D game:
- Music AudioSource — on the FeedbackManager or a dedicated MusicManager.
Loop = true,Play On Awake = trueoptional. Volume set in script. - SFX AudioSource — same GameObject as above, or on the player. Used with
PlayOneShotonly. Clip field left empty. - Transient world sounds — handled by
AudioSource.PlayClipAtPoint; no component required on pickups or enemies.
There is no need for a separate AudioSource on every pickup or hazard. Centralising sound playback in a FeedbackManager keeps scene setup simple and makes volume control straightforward.
Debugging audio setup
Most beginner audio failures are setup failures:
| Symptom | Likely cause | First check |
|---|---|---|
| No sound at all | Missing AudioListener | Check the Main Camera has an AudioListener |
| Music does not start | musicSource or mainTheme is unassigned | Check the FeedbackManager Inspector |
| Coin sound cuts itself off | Using Play() for repeated SFX | Use PlayOneShot |
| Sound plays at start before event | Play On Awake enabled | Untick it on SFX sources |
| Volume slider behaves strangely | Value not clamped | Use Mathf.Clamp01 before assigning volume |
Gotchas
AudioSource.Play()restarts the clip from the beginning each call. If a coin collection sound is called multiple times per second, only the last call will be audible. UsePlayOneShotfor any effect that can trigger rapidly.PlayClipAtPointcreates a temporary GameObject. It is self-cleaning, but generates a small allocation per call. Acceptable for occasional events; avoid using it every frame.- If no
AudioListenerexists in the scene (usually on the Main Camera), Unity logs a warning and no sound plays. Check the Camera has anAudioListenercomponent. AudioSource.PlayOneShotdoes not support volume scaling beyond the source’s ownvolumeproperty. To play a specific clip at a different volume, pass the volume as the second argument:sfxSource.PlayOneShot(clip, 0.5f).
Related
- unity-particle-system-scripting — particles and audio are typically triggered together as game feedback
- unity-inspector-references — wiring AudioSource and AudioClip references
- monobehaviour-lifecycle —
Startfor initialising music;Updatefor volume fades if needed - audio-middleware-overview — where teams move when simple AudioSource playback is no longer enough for adaptive music or runtime mixing