I am experimenting with playing some kind of victory sound when all blocks are cleared and the game moves to the next scene.
Currently I have the following solution:
-
A separate SoundPlayer that plays different AudioClip sound objects using AudioSource.PlayClipAtPoint. The SoundPlayer.PlayVictory method looks like this:
/**
- Play victory sound and wait until it is done.
- The scene should be frozen (not switched to next scene) for this to work
- Should call it using StartCoroutine(thisObject.playVictory());
*/
public IEnumerator playVictory() {
yield return new WaitForEndOfFrame();
playClip(victorySound, Vector3.zero, victoryVolume);
}
private void playClip(AudioClip clip, Vector3 position, float volume) {
if (clip) {
AudioSource.PlayClipAtPoint(clip, position, volume);
}
} -
LevelManager which has a static method onLevelCompleted:
private static void onLevelCompleted() {
// Play Victory sound - the previous level was cleared
SoundPlayer soundPlayer = FindObjectOfType();
if (soundPlayer) {
soundPlayer.StartCoroutine(soundPlayer.playVictory());
}
LevelManager levelManager = getInstance();
// Call the “stop ball” later to avoid velocity recalculation due to bounce
levelManager.Invoke(“stopBall”, 0.01f);
// Switch to next level after 3 seconds, when the victory sound is done
levelManager.Invoke(“loadNextLevel”, 3); // Load next level after 3 seconds
}
The stopBall method stops the ball in the air so that we can play the sound and have the smoke effects:
// Stop ball movement
private void stopBall() {
Ball ball = FindObjectOfType<Ball>();
if (ball) {
ball.stopMovement();
}
}
In the Ball class:
// Stop the movement of the ball
public void stopMovement() {
// Set velocity to 0 and make it Kinematic
Rigidbody2D rigidBody = GetComponent<Rigidbody2D>();
if (rigidBody) {
rigidBody.velocity = Vector3.zero;
}
}
I find this code a bit of a hack - freezing the ball, waiting some delays, using Coroutines.
Is there any cleaner way to do this?