- Home /
How to stop animated character returning to starting position after animation is complete
Hi,
I'm animating an intro to a level where my Player starts off standing on a box and then jumps off and begins a running stance. I will CrossFade a running animation and a translation forwards to move him and begin the game.
Now, to ensure that the animations are not looping, they are all set to WrapMode.Once and the loop is activated using a key press.
The problem I'm having is that while I can successfully CrossFade the animation from Standing on the box -> Jumping off of box onto ground and beginning to run, the Player always seems to return to his starting position on the box after this. The running animation that follows this then takes place at this starting position, and if I also translate him forward, it will occur at that elevated height.
I'm wondering how to get around this, do I have to reset his position or something similar?
Thanks
//-- Continuing from comments below;
void Start ()
{
// PLAYER
PlayerObj.animation[Player_start_idle.name].wrapMode = WrapMode.Once;
PlayerObj.animation[Player_start_escape.name].wrapMode = WrapMode.Once; // Tried; ClampForever, Clamp
PlayerObj.animation[Player_run.name].wrapMode = WrapMode.Loop;
// Also tried adding the run animation into a higher layer
//PlayerObj.animation[Player_run.name].layer = 2;
}
void update()
{
StartCoroutine(PlayEscapeAnimations());
}
IEnumerator PlayEscapeAnimations()
{
PlayerObj.animation.CrossFade(Player_start_escape.name, 0.2f);
yield return new WaitForSeconds(Escape_lights_delay);
if (PlayerObj.animation.IsPlaying(Player_start_escape.name))
//PlayerObj.animation.CrossFade(Player_run.name, 0.2f);
{
// Let this animation finish
}
else
{
PlayerObj.animation.Play(Player_run.name);
}
}
Answer by Yoerick · Jul 11, 2012 at 09:11 AM
In my eyes, this could be because of 1 of these 2 things:
You don't apply gravity to your object, or you don't translate it's y position. So your character will not fall down but stays at the height it starts at.
Your animation might be wrong. Did you change the character's position animation wise? Like, when he jumps, the character's y position changes in the animation itself? Because you need to change the y position of the character gameObject, not the animation. In the animation itself, your character's position should remain more or less the same.
Explanation: the character model has a prefab, which turns into a gameObject when you place it in your game. This gameObject has a certain position in the world. An animation is played, relatively to this point as it is a child/component of this gameObject. When you reposition the character inside the jump animation it will look like it moves but the parent gameObject doesn't change position, only the mesh itself. When you then return to the running animation, which probably has no position offset, it will play this animation relatively to the position of the gameObject again, which didn't move. Resulting in your character swapping back to it's starting position. At least, that's what seems to happen.
I hope this answer doesn't confuse you too much, if it does I'm sorry but I don't think I can explain it any better.
Hope it helps ;)
Thanks for the suggestion,
I've now modified it so that the Y position doesn't change.
Now at the end of the jumping animation, the run animation that I try to CrossFade in doesn't start at all. The Player just freezes.
I tried $$anonymous$$ike's suggestion too and used Wrap$$anonymous$$ode.ClampForever and this freezes the animation at the end too. In fact it's also freezing/stopping when I use Wrap$$anonymous$$ode.Once.
I'll paste the script above, hopefully you can spot what going wrong.
Thanks
When looking at your code, it seems logical he only plays the "escape" animation as you're calling the coroutine every single frame (in Update) and the first thing this coroutine does, is play the escape animation.
So I think the if statement in the coroutine never gets to the "else" part? Because when the compiler comes to "if (PlayerObj.animation.IsPlaying(Player_start_escape.name))" it will always be true, as you just started the animation 2 lines before that if statement.
I posted a new answer to be able to post the code that I think it should be ;)
Hi,
I have now resolved this problem. It was initially an issue with the Y-position as you mentioned, Yoerick. So animated the jumping on the Player without the change in the Y-position and used Unity's animation tool to create the arc to the lower Y-position. The latter issue was one involving the structure of an if-else statement.
$$anonymous$$any Thanks to everyone for their suggestions. The ClampForever suggestion by whydoidoit, also came in handy :)
Answer by whydoidoit · Jul 11, 2012 at 09:16 AM
You want to use WrapMode.ClampForever to stop it from automatically resetting to the starting frame.
Hi $$anonymous$$ike, thanks for the suggestion, please see the comment above.
How annoying! Perhaps try testing that the animation.normalizedTime is = 1 to see if the sequence is complete with ClampForever?
Answer by Yoerick · Jul 12, 2012 at 11:23 AM
I adjusted your script so it doesn't always trigger the escape animation in the coroutine. I'm not sure about what the "`Escape_lights_delay`" is supposed to do but I assume it's some sort of delay you apply after the escape animation?
What did I change? I put the escape animation in the Start function as I understand it needs to play immediately? Now the coroutine is still called every frame but doesn't start an animation by default. It just checks if the escape animation is playing and if not, start the run animation after the "`Escape_lights_delay`". Is this kinda what you're looking for?
void Start ()
{
// PLAYER
PlayerObj.animation[Player_start_idle.name].wrapMode = WrapMode.Once;
PlayerObj.animation[Player_start_escape.name].wrapMode = WrapMode.Once; // Tried; ClampForever, Clamp
PlayerObj.animation[Player_run.name].wrapMode = WrapMode.Loop;
//start the escape animation at the beginning
PlayerObj.animation.CrossFade(Player_start_escape.name, 0.2f);
}
void update()
{
StartCoroutine(PlayEscapeAnimations());
}
IEnumerator PlayEscapeAnimations()
{
//PlayerObj.animation.CrossFade(Player_start_escape.name, 0.2f); -> deleted because otherwise, this animation will always be playing
if (PlayerObj.animation.IsPlaying(Player_start_escape.name))
{
// Let this animation finish
}
else
{
yield return new WaitForSeconds(Escape_lights_delay);
PlayerObj.animation.Play(Player_run.name);
}
}
Your answer
Follow this Question
Related Questions
Problem with animations, How to blend them?? 0 Answers
Animation.Play blends previous animation 1 Answer
Animation.CrossFade help please 3 Answers
CrossFade to Specific Animation Time (Coordinate Animations) 1 Answer
Animation.CrossFade Lag 1 Answer