Search Unity

How to rotate an agent in navmesh on the z axis?

Discussion in 'Navigation' started by iarkumar644, May 23, 2022.

  1. iarkumar644

    iarkumar644

    Joined:
    Dec 2, 2021
    Posts:
    1
    In short, I started using navmesh in 2d and I don't understand how to make the agent turn in the direction of movement along the z axis, I'll say right away that “transform.rotation = Quaternion.LookRotation(agent.velocity.normalized);” here is a code that rotates along the x and y axes. Still have an idea on the screenshot, the blue arrow indicates the direction, maybe it can be used somehow?
     
  2. SOICGeek

    SOICGeek

    Joined:
    Jun 25, 2019
    Posts:
    78
    I actually posted on this some years ago on this forum, but I can't seem to find it now (although it was under my personal profile, not this one). I do still have the code, though. This is what I use:
    Code (CSharp):
    1.  
    2.        /// <summary>
    3.        /// Given an object at X1, Y1, returns the angle an object needs to
    4.        /// rotate to on the Y-axis in order to face an object at X2, Y2.  This
    5.        /// was originally intended for characters facing certain points or
    6.        /// events.
    7.        /// </summary>
    8.        /// <returns>The angle needed to rotate to in order to face the given
    9.        /// X and Y coordinates.</returns>
    10.        /// <param name="X1">The facing object's X-coordinate.</param>
    11.        /// <param name="Y1">The facing object's Y-coordinate.</param>
    12.        /// <param name="X2">The target object's X-coordinate.</param>
    13.        /// <param name="Y2">The target object's Y-coordinate.</param>
    14.        [MethodImpl(MethodImplOptions.AggressiveInlining)]
    15.        public static float getAngle(float X1, float Y1, float X2, float Y2) {
    16.      
    17.            // take care of special cases - if the angle
    18.            // is along any axis, it will return NaN,
    19.            // or Not A Number.  This is a Very Bad Thing(tm).
    20.            if (Y2 == Y1) {
    21.                return (X1 < X2) ? 90 : 270;
    22.            }
    23.            if (X2 == X1) {
    24.                return (Y2 < Y1) ? 180 : 0;
    25.            }
    26.      
    27.            float tangent = (X2 - X1) / (Y2 - Y1);
    28.            // convert from radians to degrees
    29.            double ang = (float) Mathf.Atan(tangent) * 57.2958;
    30.            // the arctangent function is non-deterministic,
    31.            // which means that there are two possible answers
    32.            // for any given input.  We decide which one here.
    33.            if (Y2-Y1 < 0) ang -= 180;
    34.      
    35.      
    36.            // NOTE that this does NOT need to be normalised.  Arctangent
    37.            // always returns an angle that is within the 0-360 range.
    38.      
    39.      
    40.            // barf it back to the calling function
    41.            return (float) ang;
    42.      
    43.        }
    44.  
    And here's a convenience wrapper to just pass in a transform instead of puttering about with x and y values:

    Code (CSharp):
    1.  
    2.        /// <summary>
    3.        /// Returns the angle in degrees that we need to set the Y-axis of the
    4.        /// given Transform to, in order for it to be facing the given Transform.
    5.        /// Basically a "face this object" method, but you will need to set the
    6.        /// Y-rotation to what this returns.
    7.        /// </summary>
    8.        /// <returns>The angle we need to set the facing object to in order to
    9.        /// face the other object.</returns>
    10.        /// <param name="a">The Transform that will be rotated.</param>
    11.        /// <param name="b">The Transform to face towards.</param>
    12.        [MethodImpl(MethodImplOptions.AggressiveInlining)]
    13.        public static float getAngle(this Transform a, Transform b) {
    14.            return getAngle(a.position.x, a.position.z, b.position.x, b.position.z);
    15.        }
    16.  
    You might use it like this:

    Code (CSharp):
    1.  
    2.  
    3. Transform giantShark;
    4. Transform player;
    5.  
    6. float facing = getAngle(giantShark, player);
    7. // EDIT: If you're using 2D, it should be
    8. // giantShark.eulerAngles = new Vector3(0, 0, facing);
    9. giantShark.eulerAngles = new Vector3(0, facing, 0);
    10. giantShark.GetComponent<Teeth>().eat(player);
    11.  
    The [MethodImpl(MethodImplOptions.AggressiveInlining)] can help reduce function call overhead, although it depends on the circumstances. I put the two methods on a static class and call it off of that.
     
  3. Inxentas

    Inxentas

    Joined:
    Jan 15, 2020
    Posts:
    278
    I might be mistaken but I remember that by default, a NavMeshAgent will point "forward" by default in accordance to it's angularSpeed, unless you turn that behavior off with agent.updateRotation = false;

    Are you sure your code only runs when agent.updateRotation = false? Because if you don't turn that off you might get weird results when you change the rotation Quaternion of a NavMeshAgent. I use NavMeshAgents with updateRotation set to true (default) and set it to false when the enemy is doing an attack that tracks the player. In this case, I calculate the Vector that must be supplied to Quaternion.LookRotation():

    https://answers.unity.com/questions/697830/how-to-calculate-direction-between-2-objects.html

    Mind you, this would cause Agents to rotate on all axis. I'm at work atm so I can't double-check how I fixed that, but from the top of my head I simply set the axis I do not want to zero before passing it to LookRotation().