there are alot of examples of the old animation.isplaying but not alot for the new system. this code just seems to end instantly before its done playing. I want the script to wait until the animation has finished playing.
IEnumerator playAnim()
{
int animLayer = 0;
anim.SetTrigger(Animationcall);
//Wait until Animator is done playing
while (anim.GetCurrentAnimatorStateInfo(animLayer).IsName(Animationcall) &&
anim.GetCurrentAnimatorStateInfo(animLayer).normalizedTime < 1.0f)
{
//Wait every frame until animation has finished
yield return null;
}
//Done playing. Do something below!
Debug.Log(“Done Playing”);
Okay, you should read this thread before you start posting:
What do you mean you want “the script” to wait until the animation finishes playing? Do you want specific lines of code to only work, or everything?
The code you posted should be a fine starting point. You could simply declare a boolean variable called something like isFinishedAnim and set it to false. Then at the end of the coroutine you posted, set isFinishedAnim to true. To “pause” all of your script, just put an if statement:
IEnumerator playAnim()
{
isFinishedAnim = false;
int animLayer = 0;
anim.SetTrigger(Animationcall);
//Wait until Animator is done playing
while (anim.GetCurrentAnimatorStateInfo(animLayer).IsName(Animationcall) &&
anim.GetCurrentAnimatorStateInfo(animLayer).normalizedTime < 1.0f)
{
//Wait every frame until animation has finished
yield return null;
}
//Done playing. Do something below!
Debug.Log("Done Playing");
isFinishedAnim = true;
}
I added a if (isFinishedAnim) {} after the coroutine but it still runs the rest of the script before the animation is finished. might be a problem with my while code? This type of function seemed easier in previous versions of unity.
I would like to pause the entire script, or just a few lines… either way… doesnt seem to be working.
Depending on whether this is a specific animation you’re playing, another approach is to use Animation Events. Basically, within the animation clip itself you can call methods as specific times. You might consider placing an animation event within your animation, towards the end of the animation, and have it call a method that resumes your script when it’s called.
To your original question, you probably just need to step through the code and see what the values are. A couple of things that might be an issue, worth checking on:
After your trigger, does the clip change immediately? Often animators have a transition period between two states, so your animation might not be in the state you expect immediately upon firing a trigger.
Have you confirmed you don’t have a typo in the trigger name, such that you’re not transitioning at all?
In any case, try putting a breakpoint, or a Debug statement, above and within your While loop, to inspect what the actually values are, to understand why you’re not remaining in your loop longer.
You need to look into the values in your code to understand why they aren’t what you expect. For example, here’s the code you posted earlier:
while (anim.GetCurrentAnimatorStateInfo(animLayer).IsName(Animationcall) &&
anim.GetCurrentAnimatorStateInfo(animLayer).normalizedTime < 1.0f)
So, in order to enter (and remain) in that while loop, two things need to be true. Are they true? Put a breakpoint on this line of code, and add entries to the Watch window for each. It will tell you which of the two is false.
One potentially obvious issue is that you’re calling SetTrigger to Animationcall, and you’re calling IsName on Animationcall. SetTrigger needs to pass in the name of a parameter, while IsName expects the name of an animation state. Those aren’t necessarily the same thing, though it’s possible you named your trigger exactly the same thing as your animation state.
Anyway, I think what you really need is to familiarize yourself with the debugging tools. You should be able to run the game and verify that your trigger has changed the animator’s state as expected. And you should be able to attach the debugger and verify the values of different variables in your code. If you don’t learn to do those kinds of things, you’ll just be guessing at what’s wrong, and that’s often very hard to do.
Sorry, what I mean’t was, put the if (isFinishedAnim) {} around the parts of your code that you want to pause, not in the coroutine. For example:
private IEnumerator PlayAnim () {
isPlayingAnim = true;
// Play animation here....
yield return new WaitForSeconds(1.0f);
isPlayingAnim = false;
}
// Called every frame
void Update () {
if (isFinishedAnim) {
// This code will only run when the animation finishes.
}
}
^^^ (Assuming PlayAnim coroutine is called/started from some other function.)
for some reason the “yield return new WaitForSeconds(1.0f);” just the statement alone in its own test scene does nothing. even if i set it for 4000, 4000f it just finished immediately.
I’m not familiar at all with the animation system but this coroutine is probably worth a shot i think…
IENumerator Routine()
{
// play the animation
while(!animationDone)
yield return new WaitForEndOfFrame();
// stuff to do when the animation finishes.
}
This will get stuck in the while loop while the animation is playing.
Each frame it will check again if the animation is finished yet, if it is the while loop will terminate, then you put your code you want to run once the animation is finished.
(Replace “animationDone” with whatever the code is to check that kind of thing)