loading...
Play Button Pause Button

Cannon Toss - Going with a Bang

cpluta profile image Chris Pluta ・3 min read

It's been a minute since I last made an update. So, what better way to have an update than just do something.

I stacked the velocity and added some sound effects with background music.

Playing sound with Unity

When using sound affects you can normally Play on Awake or trigger them when you'd like.

By default, there is an AudioListener on your camera. This allows audio to be played and heard. You can attach listeners to other objects such as the player if you're in a 3D space and either have footsteps follow you or sounds being played from around corners. Since my game is 2D I'm good with leaving it on the camera.

To setup my background music first I had to find some. I used Storyblocks to find some neat audio.

Once I found something I liked, I used Audacity to trim up some audio since there was a long pause at the end to help generate a more consistent loop.

Once trimmed, I added the background music as a component to my camera. I made sure it played on awake and also it was to play in a loop.

Unity Destroy Object with Sound Effect

Since I am making an infinite scroll, at some point the obstacle is destroyed so there aren't infinite objects scrolling in space. However, if the ball hits one of these obstacles it should play a sound.

Playing an audio source is fairly straight forward. Reference the AudioSource by using GetComponent and call .Play().

Turns out, if you destroy the object before the audio plays, the sound just won't play.

There are a couple ways to compensate.

  • Delay the destroy of the object by the length of the audio clip so it can play fully.
    var audioSource = GetComponent<AudioSource>(); 

    audioSource.Play(); 
    Destroy(gameObject, audioSource.clip.length); 
  • Reference a global game object like a GameManager to play the sound and destroy the object. This is where you have your own class called GameManager to help handle game state.
    GameManager.PlaySoundEffect(); 
    Destroy(gameObject); 
  • Play the audio clip at a particular point in space using AudioSource.
    var mainCamera = Camera.main; 
    var audioSource = GetComponent<AudioSource>(); 

    AudioSource.PlayClipAtPoint(audioSource.clip, mainCamera.transform.position); 
    Destroy(gameObject); 

I'm sure there are plenty of other ways to solve this problem but this is what I came across.

I didn't like option 1 because I would need to deactivate the game object, and it would live longer than it should. I wasn't a fan of option 2 since I would manage my sounds elsewhere rather than just on the game object itself. So, by default I went with option 3.

Since the camera is globally accessible via Main, I am able to just place the position right on top of the listener so there is no variation in fade.

No more sound

Do you not like sound? Then Muting is the answer! Turns out this is a single line to make it happen.

First, I registered M on the keyboard to control mute.

Once registered I bound to the performed delegate. On Start and Destroy I am subscribing and unsubscribing to the action. Once this action is called, we can just pause the listener and boom! no more sound. 😄

    // This is my game input control with the new Unity Input System 
    private GameControls gameControls; 

    private void Start() 
    { 
        gameControls.Sound.Mute.performed += Mute_performed; 
    } 

    private void OnDestroy() 
    { 
        gameControls.Sound.Mute.performed -= Mute_performed; 
    } 

    private void Mute_performed(UnityEngine.InputSystem.InputAction.CallbackContext obj) 
    { 
        if (obj.ReadValueAsButton()) 
        { 
            AudioListener.pause = !AudioListener.pause; 
        } 
    } 

Instead of keeping track of a variable I am just negating the value of the pause to act as an on/off toggle of the sound.

You might be asking, why is there a condition around the pause?. The reason is because performed happens twice when a key is pushed, once for key down and another for key up. This was not very ideal. So, I am checking the button value, which is true for down and false for up.

How do you stack Velocity?

In the previous part, you saw the assignment of velocity to the Vector2. To stack this, I changed it from:

    // shortening it up Check out part 2 to see how this was done 
    ballBody.velocity = new Vector2(xVelocity, yVelocity); 

To

    ballBody.velocity += new Vector2(xVelocity, yVelocity); 

What's next?

I still have some rollover from the previous post, and some new goals:

  • Show player angle of cannon and make strength be more skill based rather than 100%
  • Come up with a scoring mechanism, maybe distance or airtime?
  • Come up with a theme

Is there anything you want me to dive more into? What kind of scoring would you like to see?

Thanks for following along!

Posted on by:

cpluta profile

Chris Pluta

@cpluta

Software developer by day, game maker by night. Co-Founder of Lets Build.

Discussion

markdown guide
 

You need to add a trap, like spikes or mud or something! I'm also a big fan of distance as a scoring mechanism.