Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

NavMesh.CalculatePath and OffMesh-Links

Discussion in 'Navigation' started by adamgryu, Nov 21, 2015.

  1. adamgryu

    adamgryu

    Joined:
    Mar 1, 2014
    Posts:
    167
    I might be missing something, but it doesn't seem like NavMesh.CalculatePath uses Off-Mesh links. I haven't been able to find anything on this in the documentation / forums. Is there any way that I can use NavMesh.CalculatePath in a way that returns off-mesh links? (Bonus points if the there's any way of distinguishing them from other points in the path!)

    I am using a Rigidbody-based nav mesh agent, and I use CalculatePath to find the path for it to follow. I could always create my own solution for dealing with off-mesh links, but I don't want to miss something that's already there.
     
  2. TaurusSilver

    TaurusSilver

    Joined:
    Sep 1, 2015
    Posts:
    10
    I also have this problem. If anyone knows a solution, that would be great.
     
  3. 3skull

    3skull

    Joined:
    Dec 26, 2014
    Posts:
    1
    I also would need a solution for this....
     
  4. Jakob_Unity

    Jakob_Unity

    Unity Technologies

    Joined:
    Dec 25, 2011
    Posts:
    269
    CalcuatePath should find paths across offmeshlinks - if that's not the case please a bug-report reproducing the problem.
    A quick test here confirms that it works.
     
  5. BlueScreenISU

    BlueScreenISU

    Joined:
    Aug 27, 2015
    Posts:
    20
    Does not work for me either. I have manually created Off Mesh Links.
    They are only found when using agent.SetDestination(), but not with NavMesh.CalucatePath() nor agent.CalucatePath().
     
  6. Jakob_Unity

    Jakob_Unity

    Unity Technologies

    Joined:
    Dec 25, 2011
    Posts:
    269
    Please help me help you!

    Report a bug containing project/scene reproducing the problem.
    Post the case # here or PM it to me.
     
  7. BlueScreenISU

    BlueScreenISU

    Joined:
    Aug 27, 2015
    Posts:
    20
    Hello,
    I took a work around by adding a NavMeshAgent to the gameobject, without updating the position. Now I calculate the path from there.
    That works at least.
    Blue
     
  8. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,105
    Sorry to resurrect this, but I'm dealing with the exact same issue here, and I've seen no more recent post answering the question.

    When using NavMesh.CalculatePath() without an Agent, how can I tell that a given corner represents the start of an OffMeshLink?

    Jakob_Unity said above that CalculatePath uses OffMeshLinks in calculating its path. I'm using the path to move a Rigidbody around, without an Agent. I need to know when the rigidbody has reached the start of the OffMeshLink that CalculatePath intended to use.

    Does anyone have experience using CalculatePath without an agent, and still being able to traverse links?
     
    CasualT_Bossfight likes this.
  9. BlueScreenISU

    BlueScreenISU

    Joined:
    Aug 27, 2015
    Posts:
    20
    Hello there,

    i am not totally sure how I fixed it but this is the line of code that works with OffMeshLinks today. Since it was 3 years ago I think it was fixed in some version of unity. Make sure to use the latest any try again:

    UnityEngine.AI.NavMesh.CalculatePath(transform.position, <destination>, NavMesh.AllAreas, path);

    It could also be that I changed something with the position (maybe invalid height/misplaced) of the OffMeshLinks themselves, cant remember :(

    Hope it helps.
    Blue
     
  10. BlueScreenISU

    BlueScreenISU

    Joined:
    Aug 27, 2015
    Posts:
    20
    Hello again,

    after digging in my commits I think I might have the solution. Try this:

    Code (CSharp):
    1.  
    2. NavMeshPath path = new NavMeshPath();
    3.  
    4.  yield return new WaitForEndOfFrame();
    5.  
    6. UnityEngine.AI.NavMesh.CalculatePath(transform.position, destination, NavMesh.AllAreas, path);
    7.  

    I think the yield is the key to success!
    Blue
     
  11. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,105
    Well, the path is correct when using NavMesh.CalculatePath, in that the path contains a certain number of corners going from start to end. However, I still don't see how I can tell that any given set of corners in the path represents an offMeshLink, versus being a standard connection between areas in the mesh.

    Consider this simple diagram:

    upload_2018-4-29_15-41-10.png

    Here the blue lines are walls, and the black region is a pit over which I have an OffMeshLink. I've performed CalculatePath starting from the purple circle, heading to green start. This will result in a path whose corners represent the orange and pink lines I've drawn. The difficulty is that the pink line represents a jump over an OffMeshLink. But there's nothing in the `path` object to indicate that.

    So, given a path with these points, how is it possible to identify that the corners associated with the pink line are part of an OffMeshLink?
     
    CasualT_Bossfight likes this.
  12. BlueScreenISU

    BlueScreenISU

    Joined:
    Aug 27, 2015
    Posts:
    20
    Hello,

    Okay. Then your challenge is a bit different :)
    maybe you could test whether any positions are of your OffMeshLinks' positions.
    When they match, there is an OffMeshLink used.

    Blue
     
  13. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,105
    Well that's the thing: I don't see any way to get the list of OffMeshLinks associated with the NavMesh. That doesn't appear to be public information on the NavMesh.
     
    CasualT_Bossfight likes this.
  14. joshenes

    joshenes

    Joined:
    Apr 18, 2014
    Posts:
    48
    Unfortunately you only have access to know if a link is being used when using a NavMeshAgent. Calculating a path only gives the positions. I have this issue also and we will be moving away from using Unity Navmesh due to this and other limitations.
     
  15. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,283
    Well, this sucks. Why is the data about the offmesh links not included in the NavMeshPath?
     
    CasualT_Bossfight likes this.
  16. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,283
    If anyone encounter a case when it's needed to determine if entity is moving on the off mesh link - use NavMesh.SamplePosition to determine position where object is heading (shift along the direction).

    Then, test the NavMeshHit.mask to check if it's the different area. This is much more reliable than using NavMesh.Raycast.
     
  17. dizzy2003

    dizzy2003

    Joined:
    Nov 25, 2013
    Posts:
    97
    5 years later we still need this.

    please make a navpath return positions and offmeshlinks

    That way we dont have to do weird spatial searches to determine if a vector 3 is near an offmesh link and the next vector 3 is near the end of the offmesh link.
     
  18. jorg3n3gr3iros

    jorg3n3gr3iros

    Joined:
    Aug 19, 2016
    Posts:
    7
    Try to use a trigger in the off mesh link objets...you can use Ray cast along path or onTrigger enter to cast the off mesh link component inside trigger
     
  19. jorg3n3gr3iros

    jorg3n3gr3iros

    Joined:
    Aug 19, 2016
    Posts:
    7
    Code (CSharp):
    1. Vector3 Position=StartPosition;
    2. for(Int i=1;i<path.corners.Lenght;i++)
    3. {
    4. Vector3 nextPosition=path.corners[i];
    5. RayCastHit hit;
    6. if(Physics.LineCast(Position,neextPosition,out hit)
    7. {
    8. var link = hit.collider.GetComponent<OffMeshLink>();
    9. if(link!=Null)
    10. {
    11. ///Do something;
    12. }
    13.  
    14. }
    15. Position = nextPosition;
    16. }
     
  20. JanJulin

    JanJulin

    Joined:
    Mar 17, 2020
    Posts:
    2
    Since this is the first post that comes in search engine for this issue, I'll share this in here in case somebody encounters this issue in the future.

    Basically it just takes all OffMeshLinks and checks their position against the NavMeshPath corners with slight maximum deviation from the positon (since the corners position data did not exactly match the off mesh link position).

    I'm using it just to calculate shortest path along the nav mesh.

    Note: It's unoptimised so it might be heavy on the CPU with bunch of offmeshlinks.


    Code (CSharp):
    1.  private OffMeshLink[] allOffMeshLinks;
    2.     private List<Transform> allOffMeshLinkTransforms;
    3.     private float maxDeviation = 0.05f;
    4.     private void Start()
    5.     {
    6.         allOffMeshLinks = FindObjectsOfType<OffMeshLink>();
    7.         allOffMeshLinkTransforms = new List<Transform>();
    8.  
    9.         for (int i = 0; i < allOffMeshLinks.Length; i++)
    10.         {
    11.             if (!allOffMeshLinkTransforms.Contains(allOffMeshLinks[i].startTransform))
    12.                 allOffMeshLinkTransforms.Add(allOffMeshLinks[i].startTransform);
    13.             if (!allOffMeshLinkTransforms.Contains(allOffMeshLinks[i].endTransform))
    14.                 allOffMeshLinkTransforms.Add(allOffMeshLinks[i].endTransform);
    15.         }
    16.     }
    17.     //Get calculated path length
    18.     private float GetPathLength(NavMeshPath path)
    19.     {
    20.         float lng = 0.0f;
    21.  
    22.         if ((path.status != NavMeshPathStatus.PathInvalid))
    23.         {
    24.             for (int i = 1; i < path.corners.Length; ++i)
    25.             {
    26.                 if (!IsOnOffMeshLinkPosition(path.corners[i - 1], true, maxDeviation) || !IsOnOffMeshLinkPosition(path.corners[i], true, maxDeviation))
    27.                 {
    28.                     lng += Vector3.Distance(path.corners[i - 1], path.corners[i]);
    29.                 }
    30.             }
    31.         }
    32.  
    33.         return lng;
    34.     }
    35.     //Check if position is close enough of off mesh link
    36.     private bool IsOnOffMeshLinkPosition(Vector3 position, bool ignoreY, float maxDeviation)
    37.     {
    38.         Vector3 meshLinkPosition = Vector3.zero;
    39.         Vector3 comparePosition = position;
    40.         if (ignoreY)
    41.             comparePosition.y = 0;
    42.         for (int i = 0; i < allOffMeshLinkTransforms.Count; i++)
    43.         {
    44.             meshLinkPosition = allOffMeshLinkTransforms[i].transform.position;
    45.             if (ignoreY)
    46.             {
    47.                 meshLinkPosition.y = 0;
    48.             }
    49.             if (Mathf.Abs((meshLinkPosition - position).sqrMagnitude) < maxDeviation)
    50.                 return true;
    51.         }
    52.         return false;
    53.     }
     
    CasualT_Bossfight likes this.