I’m trying to assign animations (for the first time! gulp!) to my third-person player character, but am stumped as to how I would determine the speed of the character.
My Player character uses a rigidbody and uses AddRelativeForce to propel him along.
I understand that if I want to assign, say, a walk animation when he’s moving slowly, and a run animation when he’s moving fast, I just need to calculate his speed and test against that (ie. if speed < 1, use “walk” animation; if speed > 1, use “run” animation; if speed = 0, use “idle” animation).
However, I’m at a lost as to how to calculate speed using my movement method. Any suggestions and/or helpful pointers to determine a character’s speed (even if it is a simple boolean “Is he moving? Yes/No”) would be much appreciated!
Here’s my movement code:
public void FixedUpdate()
{
//Calculate and normalize movement vector
Vector3 movement = new Vector3(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"), 0);
if(movement.sqrMagnitude > 1)
movement.Normalize();
//Add force in the direction of movement
rigidBody.AddRelativeForce(movement.y * Vector3.forward * ((onGround) ? groundSpeed : airSpeed));
rigidBody.AddRelativeForce(movement.x * Vector3.right * ((onGround) ? groundSpeed : airSpeed));
}
Heya Petey, your suggestion seems to be pointing towards the right direction (no pun intended…) - using your thinking of measuring the velocity of the Player, I’ve added the following lines of code to determine which state the character’s in (which can then be matched with an animation):
Using the above logic as a starting point, the major issue I’m getting is when the Player does a 180 degree turn and starts moving in the opposite direction - the velocity reading along the z-axis returns as negative, so he ends up walking, even though he’s moving at full speed. Ditto if he turns 90 degrees and starts moving along the negative x-axis.
Hmm, is there a way to test against his velocity relative his root transform? Or is my logic unsound?
If you really want to get fancy, you can lerp the animation speeds of the walking/running animations when they’re playing, with the (1/desiredVelocity) as the t: var in the mathf.lerp, so when hes walking slow, the animation is slow, and as he speeds up the animation speeds up.
Use rigidbody.velocity.magnitude for an absolute measurement of velocity.
If you want the forward velocity, relative to your character, you can multiply the rigidbody’s velocity with the characters rotation. it’ll rotate the vector so that you get a velocity vector relative to the player.
As in: Vector3 relVelocity = rigidbody.velocity * transform.rotation;
And yes, you can multiply a Vector3 with a Quaternion… These classes have operator overloads for that
Or better yet, use transform.TransformDirection(rigidbody.velocity)… haven’t tested, but it might work
I’m only working on a prototype at the moment, so a simple CrossFade from the walk animation into the run animation does the job for now - I’ll definitely keep in mind your suggestion for lerping the animations when I get round to actually making good animations.
@ HarvesteR, Jesse Anders
Testing against rigidbody.velocity.magnitude to calculate absolute velocity does the trick for my simple prototype - big thanks for pointing me in the right direction!
I am quite interested in applying your relative velocity method to allow for, say, a “backpedal” or “sidestep” animation as well as the usual “walk” and “run” forwards animations.
Problem for me is, I am unsure of how to test against the Vector3 value derived from relVelocity. As in, can I test against a value of relVelocity using if/else statements? Speaking of which, is this how I would write it using an inverse transform?
I’m guessing using this method is ‘better’ than using rigidbody.velocity * transform.rotation because we don’t have to muck around with operator overloads ('cos operator overloads are seriously melting my brains at the moment…)?
Once you have the velocity in local space, there are various ways you can extract information about its direction relative to the object’s orientation. For example, let’s say you wanted to determine whether the forward, backward, left sidestep, or right sidestep animation should be played. For this purpose you could create a ‘virtual circle’ in the object’s local space, divided into quadrants (‘pie slices’) offset by 45 degrees, so one of the quadrants would be directly in front of you. Figuring out in which of these quadrants the velocity vector lies just involves a little trivial vector math, and the result will tell you which animation should be played.
Yes, that’s right.
Well, you can’t compare those two bits of code directly, because they do different things (You’d have to multiply by the inverse/conjugate of the quaternion for them to be equivalent.) But yes, I’d use InverseTransformDirection(), if only for the sake of clarity.