I liked this WaitWhile thing so I put in this coroutine that will take a lambda expression and I think it would provide a versatile way of running any stuff after any audio source has stopped playing:
//...
audioSource.Play();
StartCoroutine(AfterPlayed(audioSource, ()=>{
//Whatever you want to run after the sound's done playing goes here
subject2Animator.SetTrigger("Appear");
}));
saving the previous audioSource.time then subtracting it from the new audioSource.time and checking if it is less than 0 is working for me, though I have my clips on loop:
Yup. I am missing out detections where ( audioSource.time >= audioSourceClipLength ) and also (!audioSource.isPlaying) because it is not frame dependent. I tried it in LateUpdate, with the same luck… none.
I tried ( audioSource.time >= audioSourceClipLength * 0.999 ) which kind of worked, but I am trying to count the number of repeats, and this would often return 4 or 5 counts, knocking my system out of whack.
I guess my easiest option from here is to subtract the previous audioSource.time from the current audioSource.time, and if it is negative, that means the clip restarted.
Somehow, the audioSource must know when to restart the clip, so we should be able to get that too, somehow.
Why can’t Unity provide a callback on Audio Source when it finished playing? What I don’t like about using audio length as a solution is because if it already started playing then the length of audio file is going to overshoot it.
@ecv80 thanks for the code snippet, it’s probably the cleanest solution for this
While I fixed my issue, it would still really be nice to have a way to know if the AudioSource has ended. Even without Loop turned on, the source’s time will revert to 0 once it reached the end. This is good enough if we already know if the source has started playing, but that may not always the case. As of now, there’s no way of knowing whether the source has ended or has never even started… unless we use coroutines or have a HasPlayed boolean or something.
Anyway, my issue was about “!source.isPlaying” returning true for a frame or two when the window loses focus. This is because !isPlaying detects pauses as well as stops. I was overlapping two AudioSources to make a seamless loop and this got in the way.
The quickest and easiest fix which seems to cover all base is to check if the source time is above zero. So “!source.isPlaying && source.time == 0.0f” returns false even when the window loses focus. Losing focus only pauses the audio which keeps the time.
Hope this helps someone, it wasn’t too hard to fix but I still feel like this kind of thing shouldn’t have consumed my time in the first place.
Works perfect, but if your audio clip is smaller than 1 sec, for ex.: if using one step sound for walking, it’s better to use:
if (audioSource.time == Mathf.Epsilon) { //then do your staff }
I am not sure if this will solve any problem.
As far as I know, when the audio is over, time is set to zero, I mean EXACTLY zero, and any decimal is by definition the audio playing again.