Hi all
I wrote a singleton sound manager script and I have a problem
I keep a sound effect dictionary(enum to audioclip)-> example: ESoundEffect.creakyDoor-> creakyDoorClip.So I can call
CSoundManager.PlaySoundEffect(ESoundEffect.creakyDoor) //or
CSoundManager.PlaySoundEffect(clip,ESoundEffect.creakyDoor)
I have several scenes with different sounds
I can keep all sound effects inside a dictionary of the sound manager.(that is non-destroyable)
or create different soundmanager scripts for every scene. Because they have different enums (ESoundEffectEnumScene1,ESoundEffectEnumScene2,âŚ) I have to create other new soundmanager classes or you suggest I make one big enumsoundEffect
plz guide thx
public static class CSoundEffectStrings{
public const string CreakyDoor="CreakyDoor";
public const string BreakGlasses="BreakGlasses";
//...
I can use generics CSoundmanager or CSoundmanager with a sound effect dictionary(string to audioclip)
Mmm, why are you using strings at all? Just use the audio clip directly. Itâs faster, easier, less buggy, and less difficult to explain to newcomers that may join the project.
regarding your suggestion,so I need to drag and drop the audio clips one by one! and when I want to change them I need to do all works again. Also if I use audio clips several times like sound FX UI changing them will be unpleasant and awful.
I need a soundmanager, my question was about how we can have several soundmanagers for every scene or it is enough to have only one
Thatâs fair enough, though Iâd still like to reiterate that you might be digging yourself into a hole with this design. Generally speaking, anytime I see the word âManagerâ I start to cringe. But if you are confident in the design and its use then thatâs all that matters.
Youâve come across one of the first of many big issues with using Singletons - what happens when you need more than one of them Unfortunately, when it comes to Unity singletons often end up being an necessary evil.
In your case it really depends on how many sounds you plan on using this way. I canât honestly say what the memory footprint would be like to have so many live references to audio clips at one time but if you only intend to have a few hundred or less its probably negligible (at least on desktop). So in that case it might just be easiest to have one true singleton with every sound you plan on using. As long as itâs not too hard to handle this data structure during development then itâs probably the fastest, easiest, and least likely to break.
On the other hand, if you allow your manager to be destroyed between scenes and simply place one into each scene you do allow for some interesting possibilities where you can use the same string to reference a completely different sound which allows you to have âscene themedâ sound effects that are decoupled from the system that is playing them. Regardless, Iâd still say itâs probably just better to go with the one big enumed list unless you find a technical reason not to.
thank you. The only reason that I thought to separate audio clips for every scene (create different enums) was I have a lot of sounds (audio clips) with similar names but different sounds like creakydoor in scene1 is different from creakydoor in scene2
yes I can create one big enum sound effect and put all audio clips like creakyDoor1,creakyDoor2,âŚ
so I thought it is better to separate them
Is it suitable?
If this is your aim then itâs likely you would want to separate them and have a different table for each scene. That way you know that you are getting the correct sound for the context of that scene and you donât have a lot of extra sounds getting in the way.
The way we did until we switched to using wwise we also had a sound manager.
But it was repsonsiible as the singleton instance but it also managed our sound libraries.
Which were groups of audio clips.
These were setup on the sound manager in the scene. We then had trigger components that you could select one of the other sounds. We used custom inspectors to fill in a drop down of choices. So the string name was automatically filled in.
We had other functionality that a entry in the library could have one or more clips. If it had more than one it would randomly selected.
You could also load libraries at runtime too. Through another component. So as scenes weâre loaded or unloaded it would remove them.
The benefit of using strings or enums is your disconnected from the actual clip. This makes it easier to change clips and not have to change keys. Now your key is âexplosion bigâ but you can easily change the clip in the library from explosion "big a "to âbig bâ and nothing in your scene has to change. Plus you can do more things like the random etc.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "SoundEffect", menuName ="SoundEffect")]
public class CSoundEffectListData : ScriptableObject {
[System.Serializable]
public class CSoundEffectData {
public AudioClip clip;
public string type;
}
[Header("UI")]
public CSoundEffectData[] UISoundEffects;
[Header("Weapon")]
[Space]
public CSoundEffectData[] weaponSoundEffects;
[Header("Environment")]
[Space]
public CSoundEffectData[] environmentSoundEffects;
}
public static class CSoundEffectStrings {
public static class Environment {
public static class Car {
public static class BMWX6 {
public const string StartCar = "Car/BMWX6/StartCar";
public const string BreakCar = "Car/BMWX6/BreakCar";
public const string SteerCar = "Car/BMWX6/SteerCar";
public const string CrashCar = "Car/BMWX6/CrashCar";
public const string HornCar = "Car/BMWX6/HornCar";
}
public static class Peugeot207 {
public const string StartCar = "Car/Peugeot207/StartCar";
public const string BreakCar = "Car/Peugeot207/BreakCar";
public const string SteerCar = "Car/Peugeot207/SteerCar";
public const string CrashCar = "Car/Peugeot207/CrashCar";
public const string HornCar = "Car/Peugeot207/HornCar";
}
}
public static class Nature {
public const string Wind1 = "Nature/Wind1";
public const string Wind2 = "Nature/Wind2";
public const string Wind3 = "Nature/Wind3";
public const string Waterfall = "Nature/Waterfall";
}
public static class Human {
public const string Scream1 = "Human/Scream1";
public const string Scream2 = "Human/Scream2";
public const string Scream3 = "Human/Scream3";
public const string Battle = "Human/Battle";
}
}
public static class Weapon {
public static class AK47 {
public const string Shoot = "Weapon/Ak47/Shoot";
public const string Reload = "Weapon/Ak47/Reload";
}
public static class Pistol {
public const string Shoot = "Weapon/Pistol/Shoot";
public const string Reload = "Weapon/Pistol/Reload";
}
public static class Rifle {
public const string Shoot = "Weapon/Rifle/Shoot";
public const string Reload = "Weapon/Rifle/Reload";
}
public static class Shotgun {
public const string Shoot = "Weapon/Shotgun/Shoot";
public const string Reload = "Weapon/Shotgun/Reload";
}
public static class M16 {
public const string Shoot = "Weapon/M16/Shoot";
public const string Reload = "Weapon/M16/Reload";
}
public static class Uzi {
public const string Shoot = "Weapon/Uzi/Shoot";
public const string Reload = "Weapon/Uzi/Reload";
}
public static class Missle {
public const string Launch = "Weapon/Missle/Launch";
}
}
public static class UI {
public const string clickButton1 = "UI/ClickButton1";
public const string clickButton2 = "UI/ClickButton2";
public const string clickButton3 = "UI/ClickButton3";
public const string clickButton4 = "UI/ClickButton4";
public const string scrollbar = "UI/Scrolbar";
}
}
public class CSoundManager{
[SerializeField]
CSoundEffectListData m_soundEffectListData;
public static CSoundManager GetInstance(){ return _m_instance;}
Dictionary<string,AudioClip> m_dic=new Dictionary<string,AudioClip>();
void SetDic(){
//...
}
AudioClip GetDic(string _soundEffectName){
return m_dic[soundEffectName];
}
public void Play(string _soundEffectName,AudioSource _adc){
_adc.clip=GetDic(_soundEffectName);
_adc.Play();
}
}
public class Strings : MonoBehaviour {
// for test
// Use this for initialization
void Start() {
string str=CSoundEffectStrings.Environment.Car.Peugeot207.BreakCar;
CSoundmanager.GetInstance().Play(str,m_adc);
//CSoundEffectStrings.Weapon.M16.Shoot
// CSoundEffectStrings.UI.clickButton1
}
}
4 scripts:
1- scriptable object class to put audio clips with types
2- static class CSoundEffectStrings to handle different sound effect strings (like enum)
3- CSoundManager singleton class to play an audioclip and make a dictionary (string to audioclip)
4- test class
yes I think the way is suitable for general assets like UI audio clips used frequently and not special audio clips like certain weapon or car used only for one object(place)
perfect plz see my code too. yes custom editor is so helpful and useful
I prefer strings rather than enum because when you change an enum or add something to enum, you need to update your inspector