I did the 3D platformer tutorial and at one point they ask you to write a small piece of code to Load a different scene if the current scene’s audio has stopped playing. The code is:
function Update ()
{
if (!audio.isPlaying || Input.anyKeyDown)
Application.LoadLevel("StartMenu");
}
The problem is coming from audio.isPlaying. After having done some test, just outputing the value of isPlaying to the Log, I have seen that on the first Update call, isPlaying is false, and the following calls to Update have a isPlaying returning true. Why is the AudioSource.isPlaying variable not true on the first update call? The AudioSource has been checked as PlayOnWake.
I would appreciate any help on understanding this.
Thanks in advance.
I’m also having a problem with audiosource from doing the tutorial.
Mine is even more simple.
I’ve dragged the audio file onto the main camera. When ‘audio source’ and "play on awake’ are both checked I get the error AL_INVALID_VALUE in 'Main Camera'
I had the same problem when I went through the tutorial, and I haven’t gotten around to reporting it to anyone to be fixed. I fixed it by adding a boolean, like “startedPlaying”, which starts out as false. Then I had something like:
if (!startedPlaying) startedPlaying = audio.isPlaying;
and then I changed their ‘if’ statement to something like:
if ((!audio.isPlaying startedPlaying) || Input.anyKeyDown)
Note: Coded in a browser
My guess is that it’s a bug in the Tutorial’s script caused by having your computer run an Update() loop before the Audio has gotten a chance to start playing, so my solution is to check that isPlaying was true at least once. That fixed it for me.
I came across this last night in a project and reported it as a bug. Sometimes it’ll return true other times it won’t. Seems quite random. I also adopted a similar workaround, skipping the first iteration of the loop like you have. Seems to work fine.
You should certainly report it too. I think the more people who report a particular bug the happier the Unitoids are.
I’m not entirely certain it’s actually a bug though, at least, not in Unity. I say that because I haven’t read any documented behavior that’s being violated here. I think it’s just a bad assumption in the Tutorial script that an audio file checked to play on load will be playing immediately.
So say the scene loads, and Unity dutifully goes to load the sound resource from disk and meanwhile it starts running the normal Update() loops. It could plausibly make a pass or two through before the audio is all queued up, at which time it starts to play.
Since I don’t have source, I don’t know that’s what’s happening exactly, but it doesn’t seem unreasonable. I think that the Tutorial script is depending on a race condition; it might work, it might not.
I tend to see it as a bug. In my logic, as soon as the Play function of AudioSource is called, wether or not the song actually starts playing at that moment or not, the isPlaying variable should be set to true. If you all agree with me here, add to that the fact that in this case the AudioSource is called on ‘Wake’, which is a function which is called before any ‘Update’ function, and you have to conclude that it must be a bug.
PS: I have filled a bug report, I sent a mail with the description of the problem. Hopefully someone at Unity will have a look at it.
According to the docs, the wake() function is called when a script is first initialized not when a game object is instanced. I was using the same script to drive multiple audio sources (via temporary game objects) that were created to go along with particle effects in the following manner.
// Destroy self after playing SFX
function Update () {
if (!audio.isPlaying)
Destroy(gameObject);
}
It seems only the first SFX game object it was attached to was working, and the bool returned false for all the others.
It adds to the confusion in that if you don’t need a script to drive an audio source, what’s wake() got to do with it! Maybe a simple change to “Play on Start” behind the covers would resolve the bug and still keep grandfathered code working.
I think that’s making a few assumptions though which I can’t find supported by documentation. I’m not saying you’re wrong mind you, it’s certainly a defensible position to take and it makes sense.
But consider that an Audio clip can be loaded from a remote resource; note that they have an ‘isReadyToPlay’ attribute. What happens if you ask an AudioSource to Play a clip which is NOT ready to play? The documentation that I can find isn’t specific enough for me to draw a solid conclusion, but I would suspect that it would start playing only once isReadyToPlay is true. (although if it threw an exception instead I wouldn’t be surprised either.)
I’d also argue that it wouldn’t be logically flawed if they meant “isPlaying” to mean “The audio data from this source is now being produced”, which would mean that during any initial steps (Loading the data from source, beginning decoding and filling buffers etc) it wouldn’t technically be playing, but preparing to play.
I also suspect that audio playback may happen on a secondary thread, in which case its ‘readiness’ in relation to the script’s thread is undefined behavior. The thread may not even have started itself by the time you get to Update() on your thread, or it could have already gone through several iterations. It would produce ‘random’ behavior if one assumed that everything happened serially.
But this is all speculation because I don’t have anything better to go on.
Basically, I’m not saying I think you’re wrong about how you say it should work, or that you’re right. I’m just saying that I don’t feel like the documentation doens’t describe the expected behavior well enough for me to decide whether this is abnormal or not. I’d like to see much of the documentation expanded for reasons like this.