Playing sounds between scenes
In adventure games, the heroes explore many different locations. For instance, while walking in the forest, they could emerge in a magical clearing. In horror games, it is common for a door to slowly open and make a creaking sound as the player moves into the next room.
However, if the clearing or the next room are designed as different scenes in Unity, the audio object assuring the playback will be released when switching to the next scene, and the audio continuity will be lost. In the case of the creaking door, the sound will be cut off midway!
In this article, we will demonstrate how we can keep that creepy door sound playing without interruption.
Basically, this is achieved by selecting the “Don’t Destroy On Load” option for sound playback objects such as the CRIWARE Library Initializer and CRIWARE Error Handler, prefabricating them, and using them in multiple game scenes.
In this example, we created a DoorSoundManager singleton to help us keep the door sound playing between the rooms/scenes.
Here are the details:
Singleton implementation
- The DoorSound class is designed as a singleton and can be accessed from anywhere via the Instance property.
- The Awake method manages instances and destroys duplicate objects.
CriAtomSource component
- The AttachCriAtomSource method dynamically adds a CriAtomSource component and sets the CueSheet and Cue names.
Sound playback
- The PlayDoorSound method can be used to play the sound with the specific CueSheet and Cue names.
using CriWare;
using UnityEngine;
public class DoorSound : MonoBehaviour
{
// Singleton instance
public static DoorSound Instance { get; private set; }
private CriAtomSource criAtomSource;
void Awake()
{
// Initialize singleton
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject); // Make the object persistent
}
else
{
Destroy(gameObject); // Destroy duplicate instance
return; // Do not execute further
}
// Dynamically attach CriAtomSource
AttachCriAtomSource();
}
private void AttachCriAtomSource()
{
// Add CriAtomSource component
criAtomSource = gameObject.AddComponent();
if (criAtomSource != null)
{
Debug.Log("CriAtomSource has been successfully attached.");
// Set default settings if needed (e.g., specify CueSheet name)
criAtomSource.cueSheet = "";
criAtomSource.cueName = "";
}
else
{
Debug.LogError("Failed to attach CriAtomSource!");
}
}
public void PlayDoorSound(string cueSheet, string cueName)
{
if (criAtomSource != null)
{
// Set CueSheet
criAtomSource.cueSheet = cueSheet;
// Play with the specified CueName
criAtomSource.Play(cueName);
}
else
{
Debug.LogError("CriAtomSource is not set.");
}
}
}
As for the door itself, here is how it is handled:
- We gave the door object an opening animation
- When you click on the door on the game screen, the sound playback function of the DoorSoundManager singleton is called, and after one second, the game transitions to the next room/scene.
Below is the part of the audio code attached to the door object:
// cueSheet and cueName in the Inspector
public string cueSheet;
public string cueName;
……
// calling the DoorSound playback
DoorSound.Instance.PlayDoorSound(cueSheet, cueName);
By calling DoorSound.Instance.PlayDoorSound, the game object creates the singleton that can be accessed from any scene, and all that is left to do is to pass the right CueSheet names and Cue names to the PlayDoorSound function. For example, you could prepare several sounds for doors of various sizes and materials, and select the right one based on the player’s location.
To learn more about maintaining sound continuity when switching between scenes, we recommend referring to these two pages of the official documentation for further details: