Unity3D OffNavMesh jump issue

11,037

Solution 1

Its recommended to solve your problems via animation. Just create a Jump animation for your object, and play it at the correct time. The position is relative, so if you increase the Y-position in your animation it will look like the object is jumping.

This is also how the Unity sample is working, with the soldiers running around.

Solution 2

I came by this question, and had to dig through the Unity sample. I just hope to make it easier for people by extracting the important bits.

To apply your own animation/transition across a navmesh link, you need to tell Unity that you will handle all offmesh link traversal, then add code that regularly checks to see if the agent is on an offmesh link. Finally, when the transition is complete, you need to tell Unity you've moved the agent, and resume normal navmesh behaviour.

The way you handle link logic is up to you. You can just go in a straight line, have a spinning wormhole, whatever. For jump, unity traverses the link using animation progress as the lerp argument, this works pretty nicely. (if you're doing looping or more complex animations, this doesn't work so well)

The important unity bits are:

_navAgent.autoTraverseOffMeshLink = false; //in Start()
_navAgent.currentOffMeshLinkData; //the link data - this contains start and end points, etc
_navAgent.CompleteOffMeshLink(); //Tell unity we have traversed the link (do this when you've moved the transform to the end point)
_navAgent.Resume(); //Resume normal navmesh behaviour

Now a simple jump sample...

using UnityEngine;

[RequireComponent(typeof(NavMeshAgent))]
public class NavMeshAnimator : MonoBehaviour
{
    private NavMeshAgent _navAgent;
    private bool _traversingLink;
    private OffMeshLinkData _currLink;

    void Start()
    {
        // Cache the nav agent and tell unity we will handle link traversal
        _navAgent = GetComponent<NavMeshAgent>();
        _navAgent.autoTraverseOffMeshLink = false;
    }

    void Update()
    {
        //don't do anything if the navagent is disabled
        if (!_navAgent.enabled) return;

        if (_navAgent.isOnOffMeshLink)
        {
            if (!_traversingLink)
            {
                //This is done only once. The animation's progress will determine link traversal.
                animation.CrossFade("Jump", 0.1f, PlayMode.StopAll);
                //cache current link
                _currLink = _navAgent.currentOffMeshLinkData;
                //start traversing
                _traversingLink = true;
            }

            //lerp from link start to link end in time to animation
            var tlerp = animation["Jump"].normalizedTime;
            //straight line from startlink to endlink
            var newPos = Vector3.Lerp(_currLink.startPos, _currLink.endPos, tlerp);
            //add the 'hop'
            newPos.y += 2f * Mathf.Sin(Mathf.PI * tlerp);
            //Update transform position
            transform.position = newPos;

            // when the animation is stopped, we've reached the other side. Don't use looping animations with this control setup
            if (!animation.isPlaying)
            {
                //make sure the player is right on the end link
                transform.position = _currLink.endPos;
                //internal logic reset
                _traversingLink = false;
                //Tell unity we have traversed the link
                _navAgent.CompleteOffMeshLink();
                //Resume normal navmesh behaviour
                _navAgent.Resume();
            }
        }
        else
        {
            //...update walk/idle animations appropriately ...etc
Share:
11,037

Related videos on Youtube

avuthless
Author by

avuthless

Mobile games and apps programmer, technology enthusiast and RC fan.

Updated on June 04, 2022

Comments

  • avuthless
    avuthless almost 2 years

    I have set up Unity navigation meshes (four planes), navigation agent (sphere) and set up automatic and manual off mesh links. It should now jump between meshes. It does jump between meshes, but it does that in straight lines.

    In other words, when agent comes to an edge, instead of actually jumping up (like off mesh link is drawn) it just moves straight in line but a bit faster. I tried moving one plane higher than others, but sphere still was jumping in straight line.

    Is it supposed to be like this? Is it possible to set up navigation to jump by some curve? Or should I try to implement that myself?

  • avuthless
    avuthless over 11 years
    Can i detect when agent is performing "jump"?
  • TJHeuvel
    TJHeuvel over 11 years
    Did you check out the navigation samples provided by Unity? They should contain logic like that.
  • avuthless
    avuthless over 11 years
    No i did not and i will do that now. Thank you for fast and accurate reply.
  • TJHeuvel
    TJHeuvel over 11 years
    beta.unity3d.com/3.5-preview/NavMeshTest-3.5.0f1.zip I believe these are the tests. Check em out, all those soldiers animate properly.
  • avuthless
    avuthless almost 11 years
    NavMeshAgent.isOnOffMeshLink will tell you if you are in the air without all this code. The question itself asks "can a jump be made in custom curve" not polar. Your answer does not answer anything i ask so i guess you will have to do some other good deed for this week :)
  • user2502703
    user2502703 almost 11 years
    NavMeshAgent.isOnOffMeshLink is a bool. LinkTypeJumpAcross is a string. Depends on what the developer is trying to do but yeah its not an answer to your question.
  • brain56
    brain56 about 8 years
    Bless you, Matt Bond.