- Home /
Turn off root motion for a specific animation
Hi Guys!
I've had this question for a while now, but I can never seem to find an answer. Is there a way to turn off root motion for a specific animation? I know you can turn off root motion for an entire character (animator.applyRootMotion = false), but can you turn off root motion for just one animation?
For example, I'm prototyping a 3rd person combat game, and I use root motion for walking, running etc. But I don't like the root motion that comes with the attack animations I have, and I don't want the character to move while attacking. I'd rather his feet just slide on the floor and his transform stay the same place.
In the inspector, they have to option of "Bake root transform position (XZ) into pose", but that doesn't seem to work. While the animation is player, the character will still step off his transform spot while playing the animation. Then after the animation is played, the transform moves to where the character now is. It effectively does nothing.
Thanks for the help guys. This has been bugging me for for a while. There has to be a check box to turn off root animation on a per animation basis.
I am wondering the same thing. Wish this was on a per-animation basis.
Answer by jwinn · Sep 13, 2015 at 09:29 AM
I think I've found the solution, which lies in the Animator function "ApplyBuiltinRootMotion". Since writing a custom "OnAnimatorMove" will control your root motion by script, you can then do a test for the animation states that you want to apply root motion to. Here's a simple example, where I'm only applying root motion to my TurnToLeft state:
// Callback for processing animation movements for modifying root motion.
void OnAnimatorMove()
{
Animator anim = GetComponent<Animator>();
AnimatorStateInfo stateInfo = anim.GetCurrentAnimatorStateInfo(0);
// APPLY DEFAULT ROOT MOTION, ONLY WHEN IN THESE ANIMATION STATES
if (stateInfo.fullPathHash == Animator.StringToHash("Base.Grounded.TurnToLeft"))
{
anim.ApplyBuiltinRootMotion();
}
}
SIDE NOTE: If you're using an animator on a child object of a main parent container object, root motion may move your parent and child away from each other. In that case, check out this solution: http://forum.unity3d.com/threads/getting-mecanim-root-motion-translation.241312/#post-1710537 This would be used in place of anim.ApplyBuiltinRootMotion(). Using that code and its "anim.deltaPosition.x" and "anim.deltaPosition.y" etc, is also helpful if you only want to ever apply root motion on one axis (like a sidescroller). If your char is going through walls, use charControllerRef.Move(newPosition); rather than changing the transform directly with those delta values.
It's working for me!
I know this reply is years old, but just wanted to mention that you should never call GetComponent<> every frame. That's going to kill your performance and it creates a lot of garbage for collection. Do that once in a Start or some other initialize process and cache it.
You should also cache your AnimatorHash to an integer at the same time you get a reference to the animator. StringHash compares are extremely slow.
Answer by Mad_Joker_Games · Feb 20, 2018 at 11:21 PM
This script was written to solve the exact issue described, that is, wanting root motion on all animations except attack animations :
Animator _animator;
AnimatorStateInfo _stateInfo;
void Awake () {
_animator = this.gameObject.GetComponent<Animator> ();
}
void OnAnimatorMove () {
_stateInfo = _animator.GetCurrentAnimatorStateInfo (0);
if (!_stateInfo.IsTag ("Attack")) {
_animator.ApplyBuiltinRootMotion ();
}
}
Note: you will obviously have to tag all animations as "Attack" in the animator for this to work. To do this, simply click the animator, click on the specific animation state, and under the animations name you should see the entry spot for tag in the inspector. I hope this helps anyone else with a similar problem.
Answer by meat5000 · Aug 07, 2014 at 06:48 PM
You can cheat, perhaps. I've not confirmed, I'm guessing. Using GCAS in conjunction with .IsName("StateName") you can detect the animation in question.
Draw some techniques from this page, which details adding root motion to in-place animation, using OnAnimatorMove() function.
Detect the Root motion velocity. I can't help with this step, never tried it. But I know its possible as its listed in the Animation preview.
Negate this velocity by adding the inverse.
Perhaps there is an easier way, like temporarily applying 0 velocity to the rigidbody, in any case, GCAS will help you.
Answer by rohit1997 · Jun 23, 2019 at 11:53 AM
but how to have root motion only while attacking and script motion while movement
Animator _animator;
AnimatorStateInfo _stateInfo;
void Awake () {
_animator = this.gameObject.GetComponent<Animator> ();
}
void OnAnimator$$anonymous$$ove () {
_stateInfo = _animator.GetCurrentAnimatorStateInfo (0);
if (stateInfo.IsTag ("Attack")) {
_animator.ApplyBuiltinRoot$$anonymous$$otion ();
}
}
like the $$anonymous$$ad_Joker_Games code, if u just remove the "!" before the condition u will have this above, it means that u will apply root motion only to animations that are tagged has Attack, and every other animation will move from script motion. read the comment above yours to more information.
Your answer
Follow this Question
Related Questions
Is there a way to Scale Root Motion with the model? 0 Answers
Mecanim root motion 1 Answer
force rotation on root motion node 0 Answers
Root motion not working in-game 0 Answers