Search code examples
c#unity-game-engineanimatornavmesh

How to Record Direction of NavMesh AI agents


I am wondering on a way on how I can grab the direction a Navmesh Agent is walking, with these values I planned on referencing them to a Blendtree to where certain animations would play depending on the AI direction, Using a 2D Free form Cartesian plane I planned on using those referenced direction values to play certain animations, with the X and Z directions both starting off at zero. so to walk forward the Z value would be 1, while the X value would be 0

Currently I have already tried using rigid body velocity and transform.forward (X and Z), while I received no values using velocity the transform.forward did give increasing values however it did not seem like the values I was looking for (these values need to be in a range from 0-1), as well as never had a starting position(Idle) of 0,0

void animationUpdate() {
        anim.SetFloat("Enemy Z", /* Unsure what to do*/);
        anim.SetFloat("Enemy X", /* Unsure what to do*/);

        if (/*transform.forward.x != 0 && transform.forward.z != 0*/) {
            anim.SetBool("isWalking", true);
        } else {
            anim.SetBool("isWalking", false);
        }
    }

My Cartesian Plane is the following Cartesian Plane

Any Help would be appreciated, thank you for reading


Solution

  • You can use desiredVelocity to find what direction it's moving, and then Vector3.Project to decompose that into how it's moving forward/right.

    Vector3 normalizedMovement = nav.desiredVelocity.normalized;
    
    Vector3 forwardVector = Vector3.Project(normalizedMovement, transform.forward);
    
    Vector3 rightVector = Vector3.Project (normalizedMovement, transform.right);
    

    Get the magnitude (which, because we projected the normalized movement, will be a float between -1 and 1) and use Vector3.Dot to determine the sign of the magnitude in each component:

    // Dot(direction1, direction2) = 1 if they are in the same direction, -1 if they are opposite
    
    float forwardVelocity = forwardVector.magnitude * Vector3.Dot(forwardVector, transform.forward);
    
    float rightVelocity = rightVector.magnitude * Vector3.Dot(rightVector, transform.right);
    

    Now, you can assign them to your animation, converting the range from [-1,1] to [0,1] using Mathf.InverseLerp:

    anim.SetFloat("Enemy Z", Mathf.InverseLerp(-1f, 1f, forwardVelocity));
    anim.SetFloat("Enemy X", Mathf.InverseLerp(-1f, 1f, rightVelocity));