Search Unity

Managing Short-lived Animation and Sound Effects

Discussion in 'Scripting' started by GenericEntity, May 29, 2015.

  1. GenericEntity

    GenericEntity

    Joined:
    May 29, 2015
    Posts:
    3
    Hello,

    This post is mainly regarding project structure. I'm new to the forums, so please let me know if this is the wrong place for this thread. I put it here because it is not specifically about animation or audio, but rather ways to manage them in a game.

    So, for example, if I am making a top-down aeroplane shooter and I have a few sound effects:
    1. Player bullet
    2. Enemy bullet
    3. Player explosion
    4. Enemy explosion
    5. Win sound

    And a few animations:
    1. Player Explosion
    2. Enemy Explosion

    Obviously, I only want these to play at certain times, and then stop. I will also want multiple ones to be able to play at once. As far as I know, to play more than one sound at once, you need to have more than one AudioSource.

    So far, I have been using one approach, and it has worked quite well but I have some reservations. Basically, I will do this:
    1. Create a new empty GameObject
    2. Add an AudioSource with desired audio track
    3. Add the following script:
      Code (CSharp):
      1. [RequireComponent(typeof(AudioSource))]
      2. public class DestroyAfterPlay : MonoBehaviour
      3. {
      4.     protected void Start()
      5.     {
      6.         Destroy(gameObject, GetComponent<AudioSource>().clip.length);
      7.     }
      8. }
    4. Prefab-ify it
    5. Instantiate this prefab every time a bullet is fired or explosion is needed
    If there is an animation, I'd probably use this instead (for step 3):
    Code (CSharp):
    1. public class DestroyAfterPlay : MonoBehaviour
    2. {
    3.     public void OnAnimationFinish()
    4.     {
    5.         AudioSource audioSource = GetComponent<AudioSource>();
    6.         if(audioSource != null && audioSource.isPlaying)
    7.             Destroy(gameObject, audioSource.clip.length - audioSource.time);
    8.         else
    9.             Destroy(gameObject);
    10.     }
    11. }
    And link OnAnimationFinish() to be run at the end of the animation, such as for an explosion.

    My reservations with this approach are mainly due to the Instantiate() and GetComponent() calls, which I am told are not things you want running many times a second. In the case of, say, a bullet firing, it will be a one-time sound instantiation many times a second, which sounds bad to me.

    So, my questions are as follows:
    • Does anyone know of a better way to handle this kind of situation? This is not for any specific project, so I'm looking for a general approach or general solution (if one exists), with detailed explanations on when certain approaches are recommended and why.
    • Does anyone know the implementation details of GetComponent() and Instantiate() so I can get an idea of how computationally expensive they are?

    Thanks for reading.
     
  2. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
    Hi

    You will have to make a sound manager script. In this script you must handle the creation, assigning and Playing of the sound clips. You should also let this script keep a list of the currently playing sound Sources so that it can automatically remove it when done. You can create your own type called "SoundClip" and add that to your list of clips that are playing. Plan the methods for this script carefully. I will see if I can find an example if you can get this to work.
     
  3. GenericEntity

    GenericEntity

    Joined:
    May 29, 2015
    Posts:
    3
    So, you are saying that a sound manager will create new audio sources with appropriate sounds when called? If so, then how can a link be established between all the Game Objects that want to play sounds and the sound manager so that the manager knows when to create and play sounds? I'd like to avoid having every item look for the sound manager, for example with
    Code (CSharp):
    1. GameObject.FindGameObjectWithTag("SoundManager");
    because it looks ugly and expensive.

    Anyway, thanks for replying. Please do post any example code you can find so I can get a better idea of what you mean.