1. Help us improve the editor usability and artist workflows. Join our discussion to provide your feedback.
    Dismiss Notice
  2. Unity 5.6 is now released.
    Dismiss Notice
  3. Check out all the fixes for 5.5 in patch releases 1 & 2.
    Dismiss Notice
  4. Get further faster with the Unity Plus Accelerator Pack, free for new Unity Plus subscribers for a limited time. Click here for more details.
    Dismiss Notice
  5. Learn how you'll soon be able to publish your games to China in four simple steps with Xiaomi. Sign up now for early access.
    Dismiss Notice

Transform points at run time are not the same as design time.

Discussion in 'Navigation' started by rickblacker, Apr 18, 2017.

  1. rickblacker

    rickblacker

    Joined:
    May 1, 2014
    Posts:
    160
    Hi all..
    I'm trying to experiment with the Nav system. I have a VERY basic level.
    - A ship
    - A terrain
    - Water

    I'm tying to use the Nav system to make a ship sail through the water. To create my navigation points, I created an empty game object with one gizmo for visual reference. I then created a prefab out of that naming it NavPoint.

    I then placed 7 NavPoint prefabs around my screen making sure that all Y axis were at 0. I named each prefab NavPoint1 through NavPoint7. See
    NavPointsMap.PNG


    On my Ship, I have a NavMeshAgent and a script called ShipNavigation.
    My ShipNavigation script is based on the Unity reference
    https://docs.unity3d.com/Manual/nav-AgentPatrol.html


    NavScripts.PNG

    As you can see, I have added each NavPoint to the scripts collection.

    Here is the ShipNavigation script. It's not bullet proof yet, just proof of concept code.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.AI;
    5.  
    6. public class ShipNavigation : MonoBehaviour
    7. {
    8.  
    9.     public GameObject[] _navPoints;
    10.     private NavMeshAgent _navAgent;
    11.     private int _nextPoint = 0;
    12.  
    13.  
    14.     void Start( )
    15.     {
    16.         _navAgent = GetComponent<NavMeshAgent>();
    17.         _navAgent.autoBraking = false;
    18.  
    19.         DisplayPointPosition( );
    20.         GoToNextPoint();
    21.     }
    22.  
    23.  
    24.     void GoToNextPoint( )
    25.     {
    26.         if( _navPoints.Length == 0 )
    27.             return;
    28.  
    29.         Debug.Log( "Nav To " + _navPoints[ _nextPoint ].name );
    30.         transform.LookAt( _navPoints[ _nextPoint ].transform.position );
    31.  
    32.         _navAgent.destination = _navPoints[ _nextPoint ].transform.position;
    33.         _nextPoint            = NextNavPoint( _nextPoint );
    34.     }
    35.  
    36.  
    37.     void Update( )
    38.     {
    39.         if( _navAgent.remainingDistance < 0.5f )
    40.             GoToNextPoint( );
    41.     }
    42.  
    43.  
    44.     // Get the next spot in the array. Circle back to the beginning if needed
    45.     private int NextNavPoint( int curNavPoint )
    46.     {
    47.         if( curNavPoint == _navPoints.Length - 1)
    48.             curNavPoint = 0;
    49.         else
    50.             curNavPoint++;
    51.         return curNavPoint;
    52.     }
    53.  
    54.  
    55.     // Utility function to just display the NavPoint transform positions.
    56.     private void DisplayPointPosition( )
    57.     {
    58.         Transform t;
    59.         foreach( GameObject o in _navPoints )
    60.         {
    61.             t = o.transform;
    62.             Debug.Log( o.name + " --- X = " + t.position.x  + ", Y = "  + t.position.y + ", Z = " + t.position.z);
    63.         }
    64.     }
    65. }
    66.  
    When the code runs, I'm spitting out this debug info. I wanted to see what each NavPoint prefab has as it's transform location. When I look at this, I can see that at run time, my prefabs do NOT have the same values as they have in Scene view/Inspector.

    Here is what debug shows.
    NavDebugLog.PNG

    Yet, here is what each value is in the inspector.
    NavPoint1 X=73, Y=0, Z=-155
    NavPoint2 X=-32, Y=0, Z=-37
    NavPoint3 X=-14, Y=0, Z=121
    NavPoint4 X=79, Y=0, Z=145
    NavPoint5 X=130, Y=0, Z=32
    NavPoint6 X=248, Y=0, Z=-120
    NavPoint7 X=173, Y=0, Z=-238

    After logging these values out to the console and I log where the ship is heading to, which would be NavPoint1. This can be seen in the debug log in the console. GoToNextPoint() gets called, I log where the ship is heading which can be seen in Nav To NavPoint1 in the console. I then set the nav agents destination and the ship begins to move. Despite the transform x,y,z values being different between design time and run time, the ship starts to move towards NavPoint1. I then get the next index in the array for the next time we need to tell the ship where to go.

    Update().
    The function is working as I want. Initially...
    While the ship is still heading towards NavPoint1, everything works fine. But, once this if condition passes
    Code (CSharp):
    1. if( _navAgent.remainingDistance < 0.5f )
    GoToNextPoint() gets called repeatedly.

    It's as if
    Code (CSharp):
    1. if( _navAgent.remainingDistance < 0.5f )
    does not pick up on the fact that there is a new NavPoint to head to and it thinks it's still close to it's destination.

    Then, the ship will just navigate between NavPoint1 NavPoint6, NavPoint7 and circle around.


    Like I said, I know the code (mine) is not bullet prooft, and it's also based on the Unity example
    https://docs.unity3d.com/Manual/nav-AgentPatrol.html


    Thoughts on why I'm getting odd behavior like this?
     
  2. rickblacker

    rickblacker

    Joined:
    May 1, 2014
    Posts:
    160
    Guess I should also add that Transform.LookAt is not rotating the ship in the direction of the navigation point. Am I wrong in assuming that this would rotate my ship in the direction of next destination / navpoint?
     
  3. Jakob_Unity

    Jakob_Unity

    Unity Technologies

    Joined:
    Dec 25, 2011
    Posts:
    220
    The path calculation can take several frames, especially if the path passes through a lot of navmesh polygons (see also https://docs.unity3d.com/ScriptReference/AI.NavMesh-pathfindingIterationsPerFrame.html)

    Additionally - the remainingDistance is the remaining distance of the current, already calculated, path.

    So I'm guessing it's likely because you still have the same destination for a number of frames (for some of the legs on the route), plz - try this:

    Code (csharp):
    1.  
    2. if(! _navAgent.pathPending && _navAgent.remainingDistance < 0.5f)
    3.   GoToNextPoint( );
    4.  
    while I'll go fix the example in the docs :oops:
     
    rickblacker likes this.
  4. rickblacker

    rickblacker

    Joined:
    May 1, 2014
    Posts:
    160
    Hey Jakob!

    Adding !_navAgent.pathPending to the if statement fixed my issue! I had a feeling it was something to do with what you explained. I just wasn't sure how to fix it.

    Thank you so very much! :)