5
\$\begingroup\$

How can I enable the SetActive() property of a game object after the audio has finished?

\$\endgroup\$
11
\$\begingroup\$

you need wait until audiosource.isPlaying == false

Suspends the coroutine execution until the supplied delegate evaluates to true. WaitUntil can only be used with a yield statement in coroutines.

https://docs.unity3d.com/ScriptReference/WaitUntil.html

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(AudioSource))]
public class AudioManager : MonoBehaviour
{
    public GameObject obj;
    public AudioClip audio;
    private AudioSource audiosource;

    void Start()
    {
        audiosource = GetComponent<AudioSource>();
        audiosource.clip = audio;
        audiosource.Play();
        StartCoroutine(WaitForSound(audio));
    }

    public IEnumerator WaitForSound(AudioClip Sound)
    {
       yield return new WaitUntil(() => audiosource.isPlaying == false);
       // or yield return new WaitWhile(() => audiosource.isPlaying == true);
    if(obj != null)
    obj.SetActive(true); //Do something
    }
}

perhaps you ask what is ()=> mark? this is Lambda Expression

A lambda expression is an anonymous function that you can use to create delegates or expression tree types. By using lambda expressions, you can write local functions that can be passed as arguments or returned as the value of function calls. Lambda expressions are particularly helpful for writing LINQ query expressions.

https://msdn.microsoft.com/en-us/library/bb397687.aspx

what is different between WaitUntil & WaitWhile? this post will help you:

The Mystery of WaitUntil & WaitWhile in Unity 5.3 Revealed!!


Update:I find simple way for do something after an audio has finished.each sound have length, so we can WaitForSound(duration).

using UnityEngine;
using System.Collections;
using UnityEngine.Events;

[RequireComponent(typeof(AudioSource))]
public class AudioFinish : MonoBehaviour
{
    public AudioClip audioclip;
    private AudioSource _audiosource;
    private float _duration;
    public UnityEvent onFinishSound;


    private void Awake()
    {
        Initialize();
        StartCoroutine(WaitForSound());
    }

    public void Initialize()
    {
        _audiosource = GetComponent<AudioSource>();
        _audiosource.clip = audioclip;
        _audiosource.Play();
        _duration = audioclip.length;
    }

    IEnumerator WaitForSound()
    {
        yield return new WaitForSeconds(_duration);
        print("FinishAudio");
        onFinishSound.Invoke();
    }
}
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ With regard to your second solution, why not use a coroutine with WaitForSeconds(duration) so you don't have to keep adjusting & checking your own timer every Update? (The engine may end up doing something similar to this anyway, or it may have a more sophisticated scheduling system that lets it handle it more efficiently. Using the built-in waiting methods puts the ball in the engine's court to deal with in the best way it can) \$\endgroup\$ – DMGregory Dec 24 '16 at 19:00
  • \$\begingroup\$ I have found many similar answers to this one online. These aproaches will not work well if the audio can be paused. AudioSource.isPlaying will be false and the WaitForSeconds will obviously miss the end of the clip. \$\endgroup\$ – Corcus Sep 20 '17 at 12:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.