- Home /
Syncing object's coordinate position with object's animation position.
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.
if the animation is based on bones or other child objects of a group FBX, and your axis is the axis of one of these objects, you could potentially set your prefab's transform position to that root bone; but I haven't really dealt with this much myself, sorry if it doesn't help
Answer by Ben 14 · Mar 07, 2011 at 07:33 PM
This is untested, but here's what I'd try:
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;
}
}
Nice, I'm going to try it out once I get home. $$anonymous$$y HD failed a couple of days ago.
This looks good. I tried it out. Not too sure about the line with transform.localRotation. The object snaps to a random position, albeit with the correct orientation. Any further insights?
Answer by anomalous_underdog · Mar 08, 2011 at 03:29 AM
I also wanted to make something like this. The asset store has something:
http://u3d.as/content/mixamo/root-motion-controller/1sM
The Root Motion Controller allows you to control the speed of the character controller with the movement speed of the character's root joint!
Thanks, I'm going to research this once I get home. $$anonymous$$y HD failed a couple of days ago.
Answer by Statement · Mar 10, 2011 at 06:27 PM
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;
}
I just tried this out myself and it seems to work fine, at least for my small setup. See full script http://www.unifycommunity.com/wiki/index.php?title=AnimationStepSync
I'm going to play with this once I get home. $$anonymous$$y HD failed a couple of days ago.