I wasn't really sure how to word the question, so bear with me here.
So, let's say I give a player objects this "climatic" attack animation that involves him doing something crazy like jumping in the air and flipping from one side of an area to another. By the end of that animation, you would suspect that the player would land where even the animation ends.
However, the player would just end up in the position that the first frame took place. The same thing would happen if the player were to get hit during that animation (which of course would look terrible.)
So for my question: How can I move the object around with an animation that was exported where they player isn't staying in once place, and have the object's actual position sync with where ever he is during the animation? Most action games (such as kingdom hearts) use these "special attacks" where the players does this.
public class RootMotion : MonoBehaviour
{
Vector3 m_storedPos = Vector3.zero;
Quaternion m_storedRot = Quaternion.identity;
Transform m_rootBone; // assuming this is set somewhere
// lateUpdate is run after the animation has evaluated
void LateUpdate()
{
// grab the local transform from the root bone as set by the animation
Vector3 newPos = m_rootBone.localPosition;
Quaternion newRot = m_rootBone.localRotation;
// zero-out the root bone local transform
m_rootBone.localPosition = Vector3.zero;
m_rootBone.localRotation = Quaternion.identity;
// apply the delta-transform to the player gameObject
transform.localPosition += newPos - m_storedPos;
transform.localRotation *= newRot * Quaternion.Inverse(m_storedRot); // not sure about the order
// store the new transform for the next frame
m_storedPos = m_rootBone.localPosition;
m_storedRot = m_rootBone.localRotation;
}
}
You could have a transform in your animation that you sample at the last frame of the animation, that is where the next position of the character will be placed. This code isn't tested and I guess I am too lazy to open up a new project to try the script out on the construction worker. I did try it out on some animations I created with the animation editor though. I added a fully working class to Unify Wiki.
void Start()
{
// Assume we have an AnimationClip called attackClip.
AnimationEvent syncEvent = new AnimationEvent();
syncEvent.time = attackClip.length;
syncEvent.functionName = "SyncAnimation";
attackClip.AddEvent(syncEvent);
}
void SyncAnimation()
{
// Assume feet is a transform in your animation
// that is placed where the character will be
// at end of the animation.
transform.position = feet.position;
transform.rotation = feet.rotation;
}