Search Unity

How to handle SoudManager Script?

Discussion in 'Game Design' started by mahdiii, Dec 2, 2017.

  1. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    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

    Code (CSharp):
    1. public static class CSoundEffectStrings{
    2.     public const string CreakyDoor="CreakyDoor";
    3.     public const string BreakGlasses="BreakGlasses";
    4. //...
    5.  
    I can use generics :/ CSoundmanager<ESoundEffect1> or CSoundmanager with a sound effect dictionary(string to audioclip)
     
    Last edited: Dec 3, 2017
  2. Sluggy

    Sluggy

    Joined:
    Nov 27, 2012
    Posts:
    982
    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.
     
  3. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    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
     
  4. Sluggy

    Sluggy

    Joined:
    Nov 27, 2012
    Posts:
    982
    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.
     
    mahdiii likes this.
  5. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    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?
     
  6. Sluggy

    Sluggy

    Joined:
    Nov 27, 2012
    Posts:
    982
    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.
     
    mahdiii likes this.
  7. starikcetin

    starikcetin

    Joined:
    Dec 7, 2017
    Posts:
    340
    Sorry for hijacking your thread, but I think this question might interest you too:

    Is there a third way of doing this asset-script connection that is as secure as drag-and-drop and as easy as using strings?
     
  8. daxiongmao

    daxiongmao

    Joined:
    Feb 2, 2016
    Posts:
    412
    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.
     
    mahdiii likes this.
  9. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [CreateAssetMenu(fileName = "SoundEffect", menuName ="SoundEffect")]
    6. public class CSoundEffectListData : ScriptableObject {
    7.     [System.Serializable]
    8.     public class CSoundEffectData {
    9.         public AudioClip clip;
    10.         public string type;
    11.     }
    12.     [Header("UI")]
    13.     public CSoundEffectData[] UISoundEffects;
    14.     [Header("Weapon")]
    15.     [Space]
    16.     public CSoundEffectData[] weaponSoundEffects;
    17.     [Header("Environment")]
    18.     [Space]
    19.     public CSoundEffectData[] environmentSoundEffects;
    20. }
    21.  
    22.  
    23. public static class CSoundEffectStrings {
    24.     public static class Environment {
    25.         public static class Car {
    26.             public static class BMWX6 {
    27.                 public const string StartCar = "Car/BMWX6/StartCar";
    28.                 public const string BreakCar = "Car/BMWX6/BreakCar";
    29.                 public const string SteerCar = "Car/BMWX6/SteerCar";
    30.                 public const string CrashCar = "Car/BMWX6/CrashCar";
    31.                 public const string HornCar = "Car/BMWX6/HornCar";
    32.             }
    33.             public static class Peugeot207 {
    34.                 public const string StartCar = "Car/Peugeot207/StartCar";
    35.                 public const string BreakCar = "Car/Peugeot207/BreakCar";
    36.                 public const string SteerCar = "Car/Peugeot207/SteerCar";
    37.                 public const string CrashCar = "Car/Peugeot207/CrashCar";
    38.                 public const string HornCar = "Car/Peugeot207/HornCar";
    39.             }
    40.         }
    41.         public static class Nature {
    42.             public const string Wind1 = "Nature/Wind1";
    43.             public const string Wind2 = "Nature/Wind2";
    44.             public const string Wind3 = "Nature/Wind3";
    45.             public const string Waterfall = "Nature/Waterfall";
    46.         }
    47.         public static class Human {
    48.             public const string Scream1 = "Human/Scream1";
    49.             public const string Scream2 = "Human/Scream2";
    50.             public const string Scream3 = "Human/Scream3";
    51.             public const string Battle = "Human/Battle";
    52.         }
    53.     }
    54.     public static class Weapon {
    55.         public static class AK47 {
    56.             public const string Shoot = "Weapon/Ak47/Shoot";
    57.             public const string Reload = "Weapon/Ak47/Reload";
    58.         }
    59.         public static class Pistol {
    60.             public const string Shoot = "Weapon/Pistol/Shoot";
    61.             public const string Reload = "Weapon/Pistol/Reload";
    62.         }
    63.         public static class Rifle {
    64.             public const string Shoot = "Weapon/Rifle/Shoot";
    65.             public const string Reload = "Weapon/Rifle/Reload";
    66.         }
    67.         public static class Shotgun {
    68.             public const string Shoot = "Weapon/Shotgun/Shoot";
    69.             public const string Reload = "Weapon/Shotgun/Reload";
    70.         }
    71.         public static class M16 {
    72.             public const string Shoot = "Weapon/M16/Shoot";
    73.             public const string Reload = "Weapon/M16/Reload";
    74.         }
    75.         public static class Uzi {
    76.             public const string Shoot = "Weapon/Uzi/Shoot";
    77.             public const string Reload = "Weapon/Uzi/Reload";
    78.         }
    79.         public static class Missle {
    80.             public const string Launch = "Weapon/Missle/Launch";
    81.  
    82.         }
    83.     }
    84.     public static class UI {  
    85.         public const string clickButton1 = "UI/ClickButton1";
    86.         public const string clickButton2 = "UI/ClickButton2";
    87.         public const string clickButton3 = "UI/ClickButton3";
    88.         public const string clickButton4 = "UI/ClickButton4";
    89.         public const string scrollbar = "UI/Scrolbar";
    90.     }
    91. }
    92. public class CSoundManager{
    93.    [SerializeField]
    94.    CSoundEffectListData m_soundEffectListData;
    95.    public static CSoundManager GetInstance(){ return _m_instance;}
    96.    Dictionary<string,AudioClip> m_dic=new    Dictionary<string,AudioClip>();
    97.    void SetDic(){
    98.       //...
    99.    }
    100.    AudioClip GetDic(string _soundEffectName){
    101.       return m_dic[soundEffectName];
    102.    }
    103.    public void Play(string _soundEffectName,AudioSource _adc){
    104.       _adc.clip=GetDic(_soundEffectName);
    105.       _adc.Play();
    106.    }
    107. }
    108. public class Strings : MonoBehaviour {
    109.     // for test
    110.     // Use this for initialization
    111.     void Start() {
    112.        string str=CSoundEffectStrings.Environment.Car.Peugeot207.BreakCar;
    113.         CSoundmanager.GetInstance().Play(str,m_adc);
    114.         //CSoundEffectStrings.Weapon.M16.Shoot
    115.        // CSoundEffectStrings.UI.clickButton1
    116.     }
    117. }
    118.  
    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) :)
     
    Last edited: Dec 5, 2017
    ktpttd and CheekySparrow78 like this.
  10. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    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
     
    Last edited: Dec 5, 2017