Search Unity

How to trigger a Jump on an offmesh link

Discussion in 'Navigation' started by kev_pearman, Mar 25, 2015.

  1. kev_pearman

    kev_pearman

    Joined:
    Jul 2, 2014
    Posts:
    5
    As per the screenshot below i have a navmesh with an offmesh link that goes up onto a box and i want the charcter with the agent attached to jump when he hits the start of the off mesh link. I can't find any information on how to achieve this and was hoping you guys could help?

    upload_2015-3-25_13-57-30.png

    The character hits the offmesh link and carries on running forward into the wall, if i call
    agent.isOnOffMeshLink at this point it returns true so i know the off mesh link has been triggered, just not sure how to transition the character into a jump upon triggering the offmesh link.

    Any advice?
     
  2. Jakob_Unity

    Jakob_Unity

    Joined:
    Dec 25, 2011
    Posts:
    269
    I assume you have disable "Auto Traverse OffMeshLink" on the agent component, and this is what you need for custom movement when moving on offmeshlinks. Below is an example of custom movement(s) .

    The gist is: move agent by its transform - when done call "CompleteOffMeshLink"

    Code (csharp):
    1. // AgentLinkMover.cs
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public enum OffMeshLinkMoveMethod {
    6.    Teleport,
    7.    NormalSpeed,
    8.    Parabola,
    9.    Curve
    10. }
    11.  
    12. [RequireComponent (typeof (NavMeshAgent))]
    13. public class AgentLinkMover : MonoBehaviour {
    14.    public OffMeshLinkMoveMethod method = OffMeshLinkMoveMethod.Parabola;
    15.    public AnimationCurve curve = new AnimationCurve ();
    16.    IEnumerator Start () {
    17.      NavMeshAgent agent = GetComponent<NavMeshAgent> ();
    18.      agent.autoTraverseOffMeshLink = false;
    19.      while (true) {
    20.        if (agent.isOnOffMeshLink) {
    21.          if (method == OffMeshLinkMoveMethod.NormalSpeed)
    22.            yield return StartCoroutine (NormalSpeed (agent));
    23.          else if (method == OffMeshLinkMoveMethod.Parabola)
    24.            yield return StartCoroutine (Parabola (agent, 2.0f, 0.5f));
    25.          else if (method == OffMeshLinkMoveMethod.Curve)
    26.            yield return StartCoroutine (Curve (agent, 0.5f));
    27.          agent.CompleteOffMeshLink ();
    28.        }
    29.        yield return null;
    30.      }
    31.    }
    32.    IEnumerator NormalSpeed (NavMeshAgent agent) {
    33.      OffMeshLinkData data = agent.currentOffMeshLinkData;
    34.      Vector3 endPos = data.endPos + Vector3.up*agent.baseOffset;
    35.      while (agent.transform.position != endPos) {
    36.        agent.transform.position = Vector3.MoveTowards (agent.transform.position, endPos, agent.speed*Time.deltaTime);
    37.        yield return null;
    38.      }
    39.    }
    40.    IEnumerator Parabola (NavMeshAgent agent, float height, float duration) {
    41.      OffMeshLinkData data = agent.currentOffMeshLinkData;
    42.      Vector3 startPos = agent.transform.position;
    43.      Vector3 endPos = data.endPos + Vector3.up*agent.baseOffset;
    44.      float normalizedTime = 0.0f;
    45.      while (normalizedTime < 1.0f) {
    46.        float yOffset = height * 4.0f*(normalizedTime - normalizedTime*normalizedTime);
    47.        agent.transform.position = Vector3.Lerp (startPos, endPos, normalizedTime) + yOffset * Vector3.up;
    48.        normalizedTime += Time.deltaTime / duration;
    49.        yield return null;
    50.      }
    51.    }
    52.    IEnumerator Curve (NavMeshAgent agent, float duration) {
    53.      OffMeshLinkData data = agent.currentOffMeshLinkData;
    54.      Vector3 startPos = agent.transform.position;
    55.      Vector3 endPos = data.endPos + Vector3.up*agent.baseOffset;
    56.      float normalizedTime = 0.0f;
    57.      while (normalizedTime < 1.0f) {
    58.        float yOffset = curve.Evaluate (normalizedTime);
    59.        agent.transform.position = Vector3.Lerp (startPos, endPos, normalizedTime) + yOffset * Vector3.up;
    60.        normalizedTime += Time.deltaTime / duration;
    61.        yield return null;
    62.      }
    63.    }
    64. }
    65.  
     
  3. Lyton

    Lyton

    Joined:
    Apr 19, 2015
    Posts:
    1
    Hey Jakob, could you explain your code? I'm new to AI programming so I'm just creating text examples for now. I want to just create an Agent that will jump over an object via OffMeshLink.
     
  4. Kalbytron

    Kalbytron

    Joined:
    Aug 16, 2013
    Posts:
    1
    You know what, I've tried this code out, and apparently the while(true) is causing unity to crash. Maybe some explanation and tweaks might help.
     
    donatello41 likes this.
  5. Jakob_Unity

    Jakob_Unity

    Joined:
    Dec 25, 2011
    Posts:
    269
  6. Jakob_Unity

    Jakob_Unity

    Joined:
    Dec 25, 2011
    Posts:
    269
    If you're new to programming co-routines might not be the easiest start.
    I'll give an outline instead: The script gives the NavMeshAgent the option to traverse OffMeshLinks in one of four ways
    • Teleport - simply skips the link instantaneous.
    • Normal Speed - makes the agent move across with its normal move-speed.
    • Parabola - make agent follow a parabolic curve across link.
    • Curve - make the agent follow a curve of your choice (click curve in inspector to edit).
     
  7. Psyco92

    Psyco92

    Joined:
    Nov 15, 2013
    Posts:
    22
    Last edited: Oct 2, 2016
  8. timberap

    timberap

    Joined:
    Jun 11, 2016
    Posts:
    1
    when I use they script I get error
    The name `Curve' does not exist in the current context
    The name `Parabola' does not exist in the current context
    The name `NormalSpeed' does not exist in the current context
    can someone please help
     
  9. surajsirohi1008

    surajsirohi1008

    Joined:
    Jun 21, 2016
    Posts:
    267
    works perfectly, thanks
     
    Taloose likes this.
  10. andersonamerico07

    andersonamerico07

    Joined:
    May 12, 2018
    Posts:
    1
  11. RamonLion

    RamonLion

    Joined:
    Jul 19, 2012
    Posts:
    11
    Hey Jakob,

    I was hoping you could help clarify how you go about STARTING this process and then furthermore, how do you catch the complete?

    I have a Player Agent which uses agent.velocity and I am trying to get it to navigate the link when I press a button. So far nothing.
     
  12. Ex6tra

    Ex6tra

    Joined:
    Oct 31, 2019
    Posts:
    14
    Thank you this saved me a lot of time.
     
  13. IndieFist

    IndieFist

    Joined:
    Jul 18, 2013
    Posts:
    520
    This look fine and i got this example working, but because i have an enemycontroller that uses agent speed, should i do something like "agent.istopped = true" while doing the curve or the parabola? because right now do something like a jump.