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);
}

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;
}

For a typical 2D game:

  • Music AudioSource — on the FeedbackManager or a dedicated MusicManager. Loop = true, Play On Awake = true optional. Volume set in script.
  • SFX AudioSource — same GameObject as above, or on the player. Used with PlayOneShot only. 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.


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. Use PlayOneShot for any effect that can trigger rapidly.
  • PlayClipAtPoint creates 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 AudioListener exists in the scene (usually on the Main Camera), Unity logs a warning and no sound plays. Check the Camera has an AudioListener component.
  • AudioSource.PlayOneShot does not support volume scaling beyond the source’s own volume property. To play a specific clip at a different volume, pass the volume as the second argument: sfxSource.PlayOneShot(clip, 0.5f).