Breakout Clone 5: Adding Some Sound

2023-02-25

I often overlook the sound in games. I tend to notice things like the graphics, what the core gameplay is, or the writing, before I notice the sound. Imagine playing a game like last year's God of War: Ragnarok, but there are no sound effects when Kratos' axe smashes into an enemy. It would be weird!

So let's add some sound effects. I think I'll start with a component similar to the GameSession component that responsible for playing sounds.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SoundManager : MonoBehaviour
{
  public AudioSource sfxSource;
  public static SoundManager instance = null;

  [SerializeField] float lowPitchRange = 0.95f;
  [SerializeField] float highPitchRange = 1.05f;

  void Awake() {
    if (instance == null) {
      instance = this;
    } else if (instance != this) {
      Destroy(gameObject);
    }

    DontDestroyOnLoad(gameObject);
  }

  public void PlayRandomSFX(AudioClip[] clips) {
    int index = Random.Range(0, clips.Length);
    // slightly alter the pitch every time so that there
    // seems to be a little more variety than there actually is.
    float randomPitch = Random.Range(lowPitchRange, highPitchRange);

    sfxSource.pitch = randomPitch;
    sfxSource.clip = clips[index];
    sfxSource.Play();
  }
}

I want to play a sound whenever the ball hits a wall, a block, or the paddle. I'm already doing collision detection in Ball.cs anyways, so I may as wall add it there:

  [SerializeField] AudioClip[] collisionClips; // *NEW*

  void OnCollisionEnter2D(Collision2D collision) {
    string tag = collision.gameObject.tag;

    if (tag == "Block" || tag == "Wall" || tag == "Paddle") {
      Vector2 currentVelocity = rigidBody2D.velocity;

      // A vector perpendicular to the surface we're colliding with
      Vector2 normal = collision.GetContact(0).normal;

      // calculate the new, reflected velocity
      Vector2 newVelocity = Vector2.Reflect(currentVelocity, normal);

      rigidBody2D.velocity = newVelocity;

      SoundManager.instance.PlayRandomSFX(collisionClips); // *NEW*
    }

    if (tag == "Block") {
      collision.gameObject.GetComponent<Block>().TakeHit(1);
    }

    if (tag == "Bottom Wall") {
      BottomHit();
    }
  }

The collisionClips property is a list of audio clips that I'll associate through the Unity editor. I could have found some clips to use on OpenGameArt, but I decided to create my own using Audacity. If you're curious you can find the list of effects here: https://opengameart.org/content/blinksblonks.

I don't have a gif to show off this time since, well, gifs don't have sound. Next time I'm going to go a step further and add some music that plays while the game running.