Search Unity

Resolved Navmesh Agent - The Y Next Position & Y Velocity does not update if there is no X velocity.

Discussion in 'Navigation' started by ecoude, Aug 17, 2020.

  1. ecoude

    ecoude

    Joined:
    Aug 15, 2019
    Posts:
    9
    Tried to post this to Unity Answers but my post seems to be stuck into moderation queue, trying here.

    I'm using the Navmesh agent to make player pathfinding movement in a 2D game (XY). I'm trying to implement 2 movement options, a) Mouse Click (which works fine), b) WASD (where the problem lies).

    Currently, the player will not move up or down when attempting to go straight up or straight down (pressing only W or S).

    After trying to Debug this I found out that the Y axis of the navAgent.nextPosition was not updating unless there was some X axis input. The same thing goes for the navAgent.velocity (despite the navAgent.desiredVelocity to be correct).

    It's my first time using Navmesh so I'm not too sure what could cause this, here is the debug result and some script snippet. I'm trying to use with my WASD movement so I don't have to add a bunch of colliders on my environment (currently using navmesh obstacles which I carve).

    Here's a image of the debug, a snippet of the script and an image of my navAgent:
    Debug.jpg Inspector.jpg


    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.AI;
    3.  
    4. public class Script_Player_Controls : MonoBehaviour
    5. {
    6.     [Header("Mouse Player Movement")]
    7.     [SerializeField] private Camera myCamera = default;
    8.     [SerializeField] private ScriptObj_VectorValue startingPosition = default;
    9.     [SerializeField] private ScriptObj_UIBools UIBoolManager = default;
    10.     [SerializeField] private float playerSpeed = 3.4f;
    11.     private Vector2 animationTargetPos;
    12.    
    13.  
    14.     [Header("WASD Player Movement")]
    15.     private Vector3 direction;
    16.  
    17.     [Header("Pathfinding")]
    18.     [SerializeField] private NavMeshAgent navAgent = default;
    19.     [SerializeField] private int rayDistance = 100;
    20.     [SerializeField] private float timeBeforeAnimSwitch = 0.5f;
    21.  
    22.     private void Awake()
    23.     {
    24.         navAgent.updateRotation = false;
    25.         navAgent.updateUpAxis = false;
    26.         navAgent.updatePosition = false;
    27.         playerSpeed = navAgent.speed;
    28.     }
    29.  
    30.     void Start()
    31.     {
    32.         transform.position = startingPosition.entryPos;
    33.     }
    34.  
    35.     void FixedUpdate()
    36.     {
    37.         MouseMove();
    38.         WASDMove();
    39.         Vector2 nextPos = navAgent.nextPosition;
    40.         transform.position = Vector2.MoveTowards(transform.position, nextPos, playerSpeed * Time.deltaTime);
    41.     }
    42.  
    43.     private void WASDMove()
    44.     {
    45.         direction.x = Input.GetAxisRaw("Horizontal");
    46.         direction.y = Input.GetAxisRaw("Vertical");
    47.         if (direction != Vector3.zero)
    48.         {
    49.             direction.x = transform.position.x + direction.normalized.x;
    50.             direction.y = transform.position.y + direction.normalized.y;
    51.             navAgent.destination = direction;
    52.         }
    53.         Debug.Log("NextPos: " + navAgent.nextPosition + ". Destination: " + navAgent.destination + ". Velocity: " + navAgent.velocity + ". Desired Velocity: " + navAgent.desiredVelocity); //Don't worry this atrocity will get removed.
    54.     }
    55.  
    56.     private void MouseMove()
    57.     {
    58.         MoveAnimation(); //Handles Animations, will be reworked
    59.         MoveRestrictions(); //Handles movement restrictions, will be reworked
    60.  
    61.         if (Input.GetMouseButton(0) && currentState == PlayerState.walk)
    62.         {
    63.             Ray ray = myCamera.ScreenPointToRay(Input.mousePosition);
    64.             RaycastHit hit;
    65.             if (Physics.Raycast(ray, out hit, rayDistance))
    66.             {
    67.                 navAgent.destination = new Vector2(hit.point.x, hit.point.y);
    68.             }
    69.  
    70.             animationTargetPos = myCamera.ScreenToViewportPoint(Input.mousePosition);
    71.         }
    72.     }
     
  2. ecoude

    ecoude

    Joined:
    Aug 15, 2019
    Posts:
    9
    I temporarily fixed it with a "dirty" fix. adding the following right before setting the navAgent.desitination in the WASDMove() method.
    Code (CSharp):
    1.             if (direction.y > 0) //Dirty fix for Y axis no movement bug
    2.             {
    3.                 direction.x = direction.x + 0.01f;
    4.             }
    5.             else if (direction.y < 0)
    6.             {
    7.                 direction.x = direction.x - 0.01f;
    8.             }
    basically I noticed that it was impossible when using the mouse controls to have a perfect Y-axis input and that there was always a bit of X-axis to the input (generally within 0.1 to 0.005) so adding this same "imperfection" somehow allows for Y-velocity (since there is X-velocity I reckon).

    Seems to work fine right now but if someone knows why this is occurring and has a cleaner fix, please tell me!

    EDIT: Nevermind, sometimes the player will go super slow for some reason (seems to be related to how far you are from starting position).
    EDIT2: The closest the player is from the the 0,0 worldpoint, the fastest it is on the Y axis.
     
    Last edited: Aug 17, 2020
    PharmacyBrain and Ashechol like this.
  3. ecoude

    ecoude

    Joined:
    Aug 15, 2019
    Posts:
    9
    Ok so the solution was to actually make a custom navAgent following the tutorial here.
     
  4. giordanonin

    giordanonin

    Joined:
    Feb 12, 2021
    Posts:
    1
    I fixed it without having to recreate the entire thing. Still a "Dirty" fix though.

    Code (CSharp):
    1. if(shouldMove && moveTowards) {
    2.                 lookDirection = agent.velocity.normalized;
    3.                 Vector3 targetPosition = moveTowards.transform.position;
    4.                 if(Mathf.Abs(transform.localPosition.x) - Mathf.Abs(moveTowards.transform.localPosition.x) < 0.01f){
    5.                     targetPosition.x += 0.02f;
    6.                 }
    7.                 agent.SetDestination(targetPosition);
    8.             }
    9.             else agent.SetDestination(transform.position);
     
  5. athacus

    athacus

    Joined:
    Apr 11, 2022
    Posts:
    2
    I'm still having this problem in the latest version of unity. Is it really just one of those "fallen through the cracks" bugs that won't get a fix?
     
  6. Igotlazy

    Igotlazy

    Joined:
    Jan 15, 2018
    Posts:
    65
    Setting the destination seems to work fine for me (maybe they fixed it), but I'm getting this issue for NavMeshAgent.Move.

    Even something as silly as this...
    Code (CSharp):
    1.     public void Move(Vector2 moveDirection)
    2.     {
    3.         if (moveDirection.x == 0)
    4.             moveDirection.x = 0.000001f;
    5.         navMeshAgent.Move(moveDirection);
    6.     }
    fixes it. Super strange. Can someone at Unity comment on this?
     
    Last edited: Sep 6, 2023
  7. Igotlazy

    Igotlazy

    Joined:
    Jan 15, 2018
    Posts:
    65
    I have discovered that supplying a non-zero Z component to the vector also results in movement. The agent remains bound to the graph so it doesn't move at in all the Z. No x drift required.

    I'm assuming that there's some internal check in Move that rejects movement in only the Y direction since the Agent was originally made for 3D, and would typically move in the XZ plane as opposed to the XY. Current fix looks like this.

    Code (CSharp):
    1.     public void Move(Vector2 moveDirection)
    2.     {
    3.         var newMove = (Vector3)moveDirection;
    4.  
    5.         if (newMove.x == 0) //Fixes oddity with navMeshAgent not accepting movement vectors if x == 0. Z value is irrelevant since we're confined to a 2D XY navmesh.
    6.             newMove.z = 0.000001f;
    7.  
    8.         navMeshAgent.Move(newMove);
    9.     }
    Value doesn't even need to be that low by the way. Just making sure nothing... freaky happens >_>
     
  8. Hao_Cgh

    Hao_Cgh

    Joined:
    Sep 27, 2021
    Posts:
    5
    There was also a strange thing happen in lgotlazy's method , the agent will stop a while then keep move when input Vertical Axis. So I have to modify the horizontal Axis