- Home /
Mecanim transitions sometimes don't work
I'm making a 2.5d platformer brawler in the style of super smash bros and I will need to use either the root motion in mecanim or something similar hacked onto the legacy system. I have tried quite a few different ways of getting root motion to work with the legacy system, but none of them seemed to work particularly well. I'm using non kinematic rigidbody physics by the way. I've found that the mecanim animation system's Root Motion works quite well, but the mecanim state machine seems mortally opposed to doing what its told.
What I've done is set up my animator controller with a single Int parameter (called State) so that every state has a single transition coming out of Any State under the condition that the State parameter is equal to a specific number. Instead of calling CrossFade("animation") like I used to, now I call SetInteger(stateParameterHash, index) where index is the number that will trigger that transition (then I set State back to -1 in LateUpdate).
My problem is that the animations don't always play when I tell them to. I can be falling and touch the ground, but it will still be playing the falling animation. Or I can be standing idle and start moving but it won't play the idle animation, no matter how much I start and stop moving until I jump and hit the ground again. Its definitely not a problem with my state machine because literally the only thing that has changed is the way I tell it what animation to play.
I've set all of the transitions to be non-atomic which should mean they can be interrupted, but I'm a little unclear on that. I read a post somewhere that it only lets them be interrupted by a transition higher in the list, which would make it entirely useless for what I want.
If I'm falling, land, start running, crouch and then jump all in quick succession, why can't mecanim go falling->land->idle->run->crouch->jump exactly as I tell it to? Either I'm doing something astoundingly wrong or mecanim really is as bad as I make it out to be. I sincerely hope its the first option because I don't fancy having to go back to the legacy system and dicking around to get root motion working, so can anyone think of what I might be doing wrong?
I only read your rant section. You can still use the old animation system in Unity4.
Why would you only read the part that I specifically marked as not being necessary to understand my problem? From my post: "I have tried quite a few different ways of getting root motion to work with the legacy system, but none of them seemed to work particularly well."
Silent, I'm the first one to add jokes, etc, to the site. But headlines that do not simply, clearly state the problem, are usually just deleted.
Could you click Edit and make the headline state in as few words as possible ytour exact. precise problem. Or some mod will just delete the question
I also truly suggest you make the question as short as possible - if you want help on it. (It's a universal on here that long questions are just never read, ever.)
Answer by citizen_rafiq · Oct 04, 2013 at 11:13 AM
In my case I first Draw the movement State machine diagram then apply it on mecanim
->FSM
->http://www.voidinspace.com/2013/05/a-simple-finite-state-machine-with-c-delegates-in-unity/
I've attached a screenshot of my animation state machine to my original post.
given link could be helpful
http://video.unity3d.com/video/7362044/unity-40-mecanim-animation-tutorial
I originally had my state machine set up "normally", but I found it even less conducive to my needs than what I have now.
Answer by meat5000 · Oct 04, 2013 at 12:32 PM
You transitions are not set up correctly, looking at the picture. If your parameters are empty I'm assuming they all work on Exit Time. This will mean that the default time is played in the animation then it'll jump back to Any State and most likely play again. Add new transitions from your animations to the next state and add parameters to control when this happens.
Sigh.
I explained it in my post and you can see in the screenshot that the parameters are not empty.
There is 1 parameter: State, an int that defaults to 0.
The transition to Fall is triggered by State being 0. The transition to Land is triggered by 1. Idle is triggered by 2. And so on, down the list.
Whenever I want to play an animation, I set State to that number then I set it back to -1 in LateUpdate so it doesn't keep triggering the transition.
This system actually works about half of the time, but the rest of the time it just does nothing and stays in whatever state its in.
I find "Any State" to be very tricky. I'd set Idle to be you Default animation and link your transitions from there.
If you put the animations of separate layers then using weighting system you can override states completely or even mix them.
Try to find out which states do not work properly. It could just be ti$$anonymous$$g issue.
Answer by hirok · Jan 28, 2014 at 02:28 PM
I'm also trying to do the same, but I went with bools for each animation. it won't play well between idle and walking if I keep hitting forward forward forward forward forward forward forward. the mecanim will cease to blend to the next "while blending".
now think I might need to put most of'em in different layers and manually control the blend by weight.
Answer by Ultroman · Nov 19, 2014 at 12:11 PM
I know this doesn't fix your exact problem, but I'm trying to do the same thing you are, and I fixed it.
I've built my statemachine using a trigger for each animation in it. Kind of like your "state" integer, but spread out. I found out that there is a problem with Mechanim, if you try to trigger the same animation that is already running. I don't think it is built for that. It is a state-machine after all, so it makes sense that it should never trigger an animation that is already running.
You "simply" have to check if the animation you're starting is already running.
I've done these steps to ease my life:
Made one trigger for each of my animations, with the same name as the animation I want to trigger! (this is important, if you want to use the simple functions below)
Made a transition from "Any State" to each of my animations, and the only condition for each transition, is the matching trigger.
Then I made a PlayAnimation function, which checks if the animation is already running: u
public void PlayAnimation(string animationName){ if (!_animator.GetCurrentAnimatorStateInfo(0).IsName(animationName)) _animator.SetTrigger(animationName); }
...and here's one where you can control the layer you're checking:
public void PlayAnimation(string animationName, int layer){
if (!_animator.GetCurrentAnimatorStateInfo(layer).IsName(animationName))
_animator.SetTrigger(animationName);
}
The IsName() function checks if the string you pass it, is the name of the currently playing animation. If it isn't, I use the trigger with the same name. Simple.
This works for me.
The animations trigger instantly, though.
I don't know if this interrupts non-atomic animations.
EDIT: I have to test one thing myself, though. We may be able to interrupt and force-play the animation from the beginning, if it is already running, by triggering another (idle?) animation first, and then immediately trigger the animation again.
public void PlayAnimation(string animationName, int layer, bool forceRestart){
if(_animator.GetCurrentAnimatorStateInfo(layer).IsName(animationName)){
if(forceRestart){
_animator.SetTrigger("Idle");
_animator.SetTrigger(animationName);
}
}
else
_animator.SetTrigger(animationName);
}
I'm going to try it out.
EDIT: Tried it. It plays a bit of the Idle animation, before changing to the other animation :( No go. Maybe if you add an animation with just 1 frame?
Perhaps I should just buy 2Dtoolkit...
LAST EDIT: Since doing this, I somehow got my Animator working normally, so now I can just do:
_animator.Play(animationName);
It doesn't screw up anymore, and I don't need to use triggers at all. And also, I can do this to restart the running animation from scratch, even if it is the same animation:
_animator.Play(animationName, 0, layer, 0.0f);
I don't know why, but this wasn't working yesterday. _animator.Play() just didn't do anything.
Don't know if I'm wrong here, but in animator, doesn't it become
_animator.Play(StateName, Layer, NormalisedTime);
Your answer
Follow this Question
Related Questions
Combining two animations to be one 0 Answers
Why do legacy & humanoid animations look different on the same character? 1 Answer
Mecanim transition between animation help 0 Answers
Object disappears when animation starts in generic mode, but not in legacy mode 1 Answer
Mecanim mysterious curve 2 Answers