Search Unity

Find the Active AudioListener

Discussion in 'Audio & Video' started by Morgenstern_1, Apr 15, 2016.

  1. Morgenstern_1

    Morgenstern_1

    Joined:
    Jul 1, 2013
    Posts:
    34
    [EDIT: Title should read AudioListener, not AudioSource]

    Hi guys,

    I was wondering (hoping) if there was an easy way to find the currently active AudioListener in the scene? e.g. A static function somewhere that would return the AudioListener that is currently being used. Does such a thing exist? I expected so given that Unity knows (and spews out warnings) when there are multiple, or none, but I can't seem to find anything.

    Thanks in advance.
     
    Last edited: Apr 15, 2016
  2. aihodge

    aihodge

    Joined:
    Nov 23, 2014
    Posts:
    163
    Audio Source or Audio Listener? The title of the post refers to Audio Sources, but the post body refers to Audio Listeners...

    If it's Audio Sources, you could pool all of the Audio Sources in your scene and check the isPlaying flag on each of them to find the active (currently playing) ones. If it's Audio Listeners, typically there is only one of those per scene.
     
  3. Morgenstern_1

    Morgenstern_1

    Joined:
    Jul 1, 2013
    Posts:
    34
    Apologies, I was having two conversations at once ;-) I meant AudioListener. I don't seem to be able to edit the post title but I had added an amendment to the text. I am changing the active camera at various points over time and rather than having to track that I'd much rather just know where the enabled AudioListener is.
     
  4. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    You can edit the title with "thread tools" not by editing the OP. I thought you could only have one Audio Listener? Has this changed?

    A normal:

    var listener = GameObject.FindObjectOfType<AudioListener>();

    should do the trick. Make your own static method. And cache this result, since it's not likely to change ever unless you load a different scene. GameObject.Find can be an expensive operation.
     
  5. Morgenstern_1

    Morgenstern_1

    Joined:
    Jul 1, 2013
    Posts:
    34
    Thanks jerotas, title now updated :)

    You *shouldn't* ever have more than 1, but you can do it, Unity will just warn you constantly about it. I'm switching between Camera game objects, each with their own AudioListener, only having one active at a time. I was hoping there would be a useful static function e.g. AudioListener.GetActiveListener() so I didn't need to keep track of the active camera but it looks like I'll just need to do it myself - FindObjectOfType is WAY too expensive.
     
  6. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    No, there is no built-in function. It doesn't matter if FindObjectOfType is expensive if you only call it during Scene startup, and store what it returns for all future calls.

    You can also have a script with a list of AudioListeners so you can just drag them into the script and not need to look them up - unless they are created at runtime.
     
  7. Morgenstern_1

    Morgenstern_1

    Joined:
    Jul 1, 2013
    Posts:
    34
    Yes but as I said I'm switching the active audio listener multiple times at runtime, so I can't simply cache the result of FindObjectOfType. Even if I could, it would add to the load times which are already above what we'd like. I try to avoid it at all costs.

    I'm now just doing a single GetComponent<AudioListener> call each time I switch to a new camera and keeping track of it manually.
     
  8. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    That's infinitely better, if they're always on cameras. Some projects I've worked on, they were not. You should be totally fine with that approach.
     
  9. CaseyHofland

    CaseyHofland

    Joined:
    Mar 18, 2016
    Posts:
    613
    5 years too late, but you may also use this:

    Code (CSharp):
    1. private static AudioListener _activeAudioListener;
    2. public static AudioListener activeAudioListener
    3. {
    4.     get
    5.     {
    6.         if (!_activeAudioListener
    7.             || !_activeAudioListener.isActiveAndEnabled)
    8.         {
    9.             var audioListeners = FindObjectsOfType<AudioListener>(false);
    10.             _activeAudioListener = Array.Find(audioListeners, audioListener => audioListener.enabled); // No need to check isActiveAndEnabled, FindObjectsOfType already filters out inactive objects.
    11.         }
    12.  
    13.         return _activeAudioListener;
    14.     }
    15. }
    This caches the active audio listener and only searches again after it becomes inactive.

    This is still not as good as doing it manually like you did, but for the better part of games, with a single AudioListener that is never disabled, this 'is' as good.