Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Total NOOB Q time! Any help appreciated - Scripting Dynamic Audio in Space Shooter

Discussion in 'Audio & Video' started by Playa1, Jul 9, 2015.

  1. Playa1

    Playa1

    Joined:
    Jul 9, 2015
    Posts:
    5
    Hi there.. 'name's Jim. Just getting into Unity and really enjoying it so far. I'm a complete newbie so please excuse my ignorance.

    I'm modifying the Space Shooter demo in Unity 5 just to explore a few basic ideas, but my C# and working knowledge of Unity is pretty sparse so, if it's not too much trouble, maybe you could help me code and integrate a few basic ideas? That would be amazing : )

    So, ideas are :

    1. Add more laser & explosion sounds and cycle through them, either sequentially or randomly. Some degree of control here would be good.. for instance if I wanted to alternate between 3 sounds but have one of the sounds play more often that the others, that would be cool.
    2. Slightly adjust the pitch & EQ of these sounds randomly.
    3. Add ship noise and have it doppler and increase in volume when the ship is moved, returning to a low level volume when stationary.
    4. Play different musical elements at different stages in the game. (@ high score, X amount of baddies killed, X amount of time has elapsed, and @ Game Over). I intend to create several stem tracks from a composition of mine and bring in drums, horns, strings at different stages to keep it sounding interesting.
    5. A complete change in music at a certain point from what was an intense cinematic score to an eerie ambience, and then back again after a certain amount of time.

    That should do it. I'm hoping to get this done over the weekend and it's kind important so if you could help me directly or even help steer me towards a solution I would really very grateful. First posts like this in any discipline always feel a bit cheeky : ) but I do hope that in the years to come I'll be in a position to give back more and more to these forums as my skills develop.

    Much appreciated,

    Jim
     
  2. aihodge

    aihodge

    Joined:
    Nov 23, 2014
    Posts:
    163
    I had a very similar goal for a recent game jam project...here is a basic outline of my approach:

    - Curate my selection of sound effect files, sort, and add them to /Resources/
    - Create a basic prefab for a one shot sound effect through an Audio Source, with a script that checks if the source is playing (in Update()). If it isn't, tell the instance to destroy itself.
    - Duplicate this prefab (if required) to route different sound effects through different groups on my Audio Mixer. The mixer is where you can get creative with adjusting the pitch and EQ on the fly using Unity's audio plugins and mixer.SetFloat("parameter", value). For the ship movement sounds, you could have the constant stationary sound playing through a group on the mixer, and fade in/out the second mixer group handling the ship noise based on the ship's velocity.
    - Write an audio manager script that my other game scripts can call, and which instantiates the desired sound effect prefab. This script was also responsible for getting the contents of the subfolders in /Resources/, loading the file names into an ArrayList, and playing a (sometimes) random selection.

    The music component was a bit more challenging. Here's what I'd recommend:

    - Pay special attention to the stems being cut up perfectly, and ensure they are all at the same BPM. Start playing them all at the same time, and fade in and out of mixer groups corresponding to the several musical tracks that make up the complete piece in order to get the transitions you want.
    - Musical changes in my game jam project were tied to the number of ships on screen at any time (it was an 8-player space brawl). I had another script managing the musical changes which was keeping track of this integer value and selecting from musical stems that had previously been sorted according to perceived intensity/mood.

    Hope this gives you some ideas for you game!
     
  3. Playa1

    Playa1

    Joined:
    Jul 9, 2015
    Posts:
    5
    Hey aihodge, thanks so much for the reply. I actually think the second part I'll find easier coming from a music background. The code though is where I'm weak. Don't suppose you can show me some code? I wouldn't know where to start.. cracking on with some tutorials but I'd love to get a script together that simply alternates through an array of different shooter sounds to begin with... : )
     
    Last edited: Jul 9, 2015
  4. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    It might be worth your while (depending how much you value your time) to just buy Master Audio on the Asset Store, which is 75% off for another 15 hours. Mostly you won't have to write code to do any of that.

    Other than that, good advice above :)
     
  5. aihodge

    aihodge

    Joined:
    Nov 23, 2014
    Posts:
    163
    Sure, here are parts of the AudioManager and AudioInstance classes. I actually used a List, not an ArrayList.

    Code (CSharp):
    1.  
    2. //AudioManager.cs
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6. public enum WeaponSoundType{
    7.     SimpleProjectile,
    8.     ExplosiveProjectile,
    9.     SteerableProjectile,
    10.     SteerableExplosiveProjectile,
    11.     Cluster,
    12.     Gravity
    13. }
    14.  
    15. public enum LoopableWeaponSoundType{
    16.     Beam
    17. }
    18.  
    19. public enum ShipSoundType
    20. {
    21.     Takeoff
    22. }
    23.  
    24. public enum LoopableShipSoundType
    25. {
    26.     Engine
    27. }
    28.  
    29. public class AudioManager : PersistentSingleton<AudioManager> {
    30.  
    31.     public GameObject myLoopableWeaponSound;
    32.     public GameObject myWeaponSound;
    33.  
    34.     public GameObject myLoopableShipSound;
    35.     public GameObject myShipSound;
    36.  
    37.     public Camera myCamera;  
    38.  
    39.     void Start () {
    40.  
    41.     }
    42.  
    43.     // Update is called once per frame
    44.     void Update () {
    45.  
    46.     }
    47.  
    48.     float scaleRange(float oldMin, float oldMax, float newMin, float newMax, float oldValue)
    49.     {
    50.         float oldRange = (oldMax - oldMin);
    51.         float newRange = (newMax - newMin);
    52.         float newValue = (((oldValue - oldMin) * newRange) / oldRange) + newMin;
    53.  
    54.         return newValue;
    55.     }
    56.  
    57.     public void PlayWeaponOneShotWithParameters(int intensity, Vector3 position, WeaponSoundType type)
    58.     {
    59.         GameObject audioInstance;
    60.         string soundPath = "Path/To/Audio/";
    61.  
    62.         Vector3 screenPos = myCamera.WorldToViewportPoint(position);
    63.         float panPos = scaleRange(0.0f, 1.0f, -1.0f, 1.0f, screenPos.x);
    64.  
    65.         switch (type)
    66.         {
    67.             case WeaponSoundType.SimpleProjectile:
    68.              
    69.                 audioInstance = Instantiate(myWeaponSound);
    70.                 soundPath += "Weapons/SimpleProjectile/";
    71.                 audioInstance.SendMessage("SetPan", panPos);
    72.                 audioInstance.SendMessage("SetPath", soundPath);
    73.                 break;
    74.  
    75.             case WeaponSoundType.ExplosiveProjectile:
    76.                 audioInstance = Instantiate(myWeaponSound);
    77.                 soundPath += "Weapons/ExplosiveProjectile/";
    78.                 audioInstance.SendMessage("SetPan", panPos);
    79.                 audioInstance.SendMessage("SetPath", soundPath);
    80.                 break;
    81.  
    82.             case WeaponSoundType.SteerableProjectile:
    83.                 audioInstance = Instantiate(myWeaponSound);
    84.                 soundPath += "Weapons/SteerableProjectile/";
    85.                 audioInstance.SendMessage("SetPan", panPos);
    86.                 audioInstance.SendMessage("SetPath", soundPath);
    87.                 break;
    88.  
    89.             case WeaponSoundType.SteerableExplosiveProjectile:
    90.                 break;
    91.  
    92.             case WeaponSoundType.Cluster:
    93.                 audioInstance = Instantiate(myWeaponSound);
    94.                 soundPath += "Weapons/Cluster/";
    95.                 audioInstance.SendMessage("SetPan", panPos);
    96.                 audioInstance.SendMessage("SetPath", soundPath);
    97.                 break;
    98.  
    99.             case WeaponSoundType.Gravity:
    100.                 audioInstance = Instantiate(myWeaponSound);
    101.                 soundPath += "Weapons/Gravity/";
    102.                 audioInstance.SendMessage("SetPan", panPos);
    103.                 audioInstance.SendMessage("SetPath", soundPath);
    104.                 break;
    105.         }
    106.     }
    107.  
    108.     public GameObject PlayWeaponLoopWithParameters(int intensity, Vector3 position, LoopableWeaponSoundType type)
    109.     {
    110.         GameObject audioInstance;
    111.         string soundPath = "Path/To/Audio/";
    112.  
    113.         Vector3 screenPos = Camera.main.WorldToViewportPoint(position);
    114.         float panPos = scaleRange(0.0f, 1.0f, -1.0f, 1.0f, screenPos.x);
    115.      
    116.         switch(type)
    117.         {
    118.         case LoopableWeaponSoundType.Beam:
    119.             audioInstance = Instantiate(myLoopableWeaponSound);
    120.             soundPath += "Weapons/Beam/";
    121.             audioInstance.SendMessage("SetPan", panPos);
    122.             audioInstance.SendMessage("SetPath", soundPath);
    123.             return audioInstance;
    124.             break;
    125.         }
    126.  
    127.         return null;
    128.     }
    129.  
    130.     public void PlayShipOneShotWithParameters(int intensity, Vector3 position, ShipSoundType type)
    131.     {
    132.         GameObject audioInstance;
    133.         string soundPath = "Path/To/Audio/";
    134.  
    135.         Vector3 screenPos = Camera.main.WorldToViewportPoint(position);
    136.         float panPos = scaleRange(0.0f, 1.0f, -1.0f, 1.0f, screenPos.x);
    137.      
    138.         switch (type)
    139.         {
    140.         case ShipSoundType.Takeoff:
    141.          
    142.             audioInstance = Instantiate(myShipSound);
    143.             soundPath += "Ships/Engine/Takeoff/";
    144.             audioInstance.SendMessage("SetPan", panPos);
    145.             audioInstance.SendMessage("SetPath", soundPath);
    146.             break;
    147.  
    148.         }
    149.     }
    150.  
    151.     public GameObject PlayShipLoopWithParameters(int intensity, Vector3 position, LoopableShipSoundType type)
    152.     {
    153.         GameObject audioInstance;
    154.         string soundPath = "Path/To/Audio/";
    155.  
    156.         Vector3 screenPos = Camera.main.WorldToViewportPoint(position);
    157.         float panPos = scaleRange(0.0f, 1.0f, -1.0f, 1.0f, screenPos.x);
    158.  
    159.      
    160.         switch(type)
    161.         {
    162.         case LoopableShipSoundType.Engine:
    163.             audioInstance = Instantiate(myLoopableShipSound);
    164.             soundPath += "Ships/Engine/";
    165.             audioInstance.SendMessage("SetPan", panPos);
    166.             audioInstance.SendMessage("SetPath", soundPath);
    167.             return audioInstance;
    168.             break;
    169.         }
    170.      
    171.         return null;
    172.     }
    173.  
    174. }
    175.  
    Code (CSharp):
    1.  
    2. //AudioInstance.cs
    3. using UnityEngine;
    4. using System.Collections;
    5. using System.IO;
    6. using System.Collections.Generic;
    7.  
    8. public class AudioInstance : MonoBehaviour {
    9.  
    10.     AudioSource source;
    11.     AudioClip clip;
    12.  
    13.     bool hasStarted = false;
    14.  
    15.     List<string> mySoundsList;
    16.  
    17.     float pan = 0.0f; // Default pan is center (0.0f). -1.0f corresponds to panning hard left, 1.0f corresponds to panning hard right
    18.  
    19.     void Awake() {
    20.         source = GetComponent<AudioSource>();
    21.         mySoundsList = new List<string>();
    22.     }
    23.  
    24.     // Use this for initialization
    25.     void Start () {
    26.  
    27.     }
    28.  
    29.     // Update is called once per frame
    30.     void Update () {
    31.         if(hasStarted == true)
    32.         {
    33.             if(!source.isPlaying)
    34.             {
    35.                 Destroy(gameObject);
    36.  
    37.             }
    38.         }
    39.     }
    40.  
    41.     void SetPan (float myPan)
    42.     {
    43.         pan = myPan;
    44.     }
    45.  
    46.     void SetPath (string myPath)
    47.     {
    48.  
    49.  
    50.         string directory = "Assets/Resources/" + myPath;
    51.         //Debug.Log("checking contents of: " + directory);
    52.         if(Directory.Exists(directory))
    53.         {
    54.             DirectoryInfo dir = new DirectoryInfo(directory);
    55.             FileInfo[] info = dir.GetFiles("*.wav");
    56.  
    57.             foreach(FileInfo f in info)
    58.             {
    59.                 //Debug.Log("found a sound in: "+ directory + " called: " + f.Name);
    60.                 mySoundsList.Add(f.Name);
    61.             }
    62.  
    63.             int file = Random.Range(0, mySoundsList.Count);
    64.  
    65.             string filename = mySoundsList[file];
    66.             filename = filename.Substring(0, filename.Length - 4);
    67.  
    68.  
    69.             if(File.Exists(directory+filename+".wav"))
    70.             {
    71.                 source.panStereo = pan;
    72.                 source.clip = (AudioClip)Resources.Load(myPath + filename, typeof(AudioClip));
    73.                 source.Play();
    74.                 hasStarted = true;
    75.  
    76.             } else {
    77.  
    78.                 Debug.LogError("Audio file not found!");
    79.  
    80.             }
    81.         } else {
    82.             Debug.LogError("Audio directory not found!");
    83.         }
    84.     }
    85. }
    86.  
     
    Last edited: Jul 10, 2015
  6. Playa1

    Playa1

    Joined:
    Jul 9, 2015
    Posts:
    5
    You're a gentleman thank you : ) I can get stuck into getting my head around that for today and should learn a few things along the way. Thanks again.