[Solved] Issues knowing if an object is moving "forward" or "backwards" (C#)

Hello. I’m trying to have a character play a different animation when they move forwards, backwards, left, and right. in my code, i use

Vector3 localVelocity = transform.InverseTransformVector (_velocity);

where _velocity is the amount the player moves each update.

When I use localVelocity.z to get the forward velocity, I get 6 and negative 6 when i go forwards and backwards, which is correct. The problem is when I move left and right, I sometimes get values like 1.73265 or 2.736 or other weird numbers. This number goes into this part of my script,

if (localVelocity.z != 0) {

anim.SetBool ("isWalking", true);
Debug.Log ("true");

} else {

anim.SetBool ("isWalking", false);
Debug.Log ("false");

}

and plays a forward animation when i’m moving sideways. Any idea why this happens, and how to fix this?

I have also tried setting localVelocity equal to transform.InverseTransformDirection, and transform.InverseTransformPoint, but I get the same problem.

The problem is that you’re dealing with floating point values. Using “>0” and “<0” or “!=0” is never a good idea. The values you get is probably not “1.73265” but something like “1.73265E-10” so the actual number would be “0.000000000173265” which is “almost” 0

You have to test against a threshold:

if (Mathf.Abs(localVelocity.z) > 0.01f)
{
    anim.SetBool ("isWalking", true);
   // ...

or like this which would do the same:

if (localVelocity.z > 0.01f || localVelocity.z < -0.01f)
{
    anim.SetBool ("isWalking", true);
   // ...

I think you are using the wrong method in the firstplace. InverseTransformVector() transforms a vector from world to local space. This will not give you the data you want. All this is doing is converting your _velocity to local space

If you want to know where you are relative to where you were, you can use subtraction:

public Vector3 oldPosition;

void FixedUpdate() {
    Vector3 direction = transform.position - oldPosition;
    float forwardTest = Vector3.Dot(-direction.normalized, transform.position.normalized)

    if(forwardTest  > 0) {
        // forward
    } else if (forwardTest < 0) {
       // backward
    } else {
       // neither
    }

    float sideTest = Vector3.Dot(direction.normalized, Vector3.Cross(transform.forward, transform.up).normalized) ;
    if(sideTest > 0) {
        // right (maybe left?)
    } else if (sideTest < 0) {
        // left (maybe right?)
    } else {
        //neither
    }

    oldPosition = transform.position;
}

I forget which result will be right or left in the second test.

This will tell you raw direction. if your forward test is 1, and your side test is 0, you are just walking straight. If your side test is 1, and your forward test is 0, you are strafing. If you have a combination, then you are strafing while moving forward or back. If they are both 0 (or close to it), you didn’t move.

This is the general idea. Dot product of two normalized vectors gives a direction. The sign of the result tells you if you are forward or back (I might have swapped them).

The side test is similar, we just re-check it with a perpendicular vector created via a cross product.

There might be a simpler way to do this, but this is what came to mind.

EDIT: This is a handy tool to help understand how dot products work, and why it is useful for you:
http://www.falstad.com/dotproduct/