Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

NavMesh Agent internal position

Discussion in 'Unity 5 Pre-order Beta' started by Carpe-Denius, Dec 3, 2014.

  1. Carpe-Denius

    Carpe-Denius

    Joined:
    May 17, 2013
    Posts:
    842
    How should I use navmeshagents now?

    Release notes say "AI: When NavMeshAgent updatePosition is false - moving the transform position doesn't affect the internal agent Position."

    but that means... even if I use updatePosition=false, because I want to use animation based movement, the navmeshagent walks ahead. If I set it to true, I can't move the gameobject by myself...

    I can't even set the internal position of the navmeshagent to the current gameobject.

    The only way around that at the moment seems to be to set

    agent.enabled=false;
    agent.enabled=true;

    on every update?
     
  2. p87

    p87

    Joined:
    Jun 6, 2013
    Posts:
    318
    it seems like the updatePosition flag causes the agent to stop updating it's "current position" to match the transform position. I don't think it stops the agent from moving.

    I don't think you need to change updatePosition - you still want it to update. If you set it to false it will just cause your pathfinding to misbehave, probably.

    Animation root motion + NavMeshAgent can be done, there is an example in the Mecanim Examples asset that is on the asset store. In a nutshell you place a script on the same GameObject as the Animator, and that script should implement OnAnimatorMove

    Inside OnAnimatorMove, you can get the root movement from the animator and apply it to the NavMeshAgent's velocity like this:
    1. voidOnAnimatorMove()
    2. {
    3. _agent.velocity = _anim.deltaPosition /Time.deltaTime;
    4. }
    Look inside the "NavMeshExample" scene of these assets for an example: https://www.assetstore.unity3d.com/en/#!/content/5328
     
    thanglq and McGravity like this.
  3. Carpe-Denius

    Carpe-Denius

    Joined:
    May 17, 2013
    Posts:
    842
    It worked until the change in B12, with "updatePosition" set to false, the agent still had a desired velocity, but didn't move.

    But I will try your suggestion, thank you.
     
  4. DanSuperGP

    DanSuperGP

    Joined:
    Apr 7, 2013
    Posts:
    408
    I also find this change very confusing. My understanding of the updatePosition flag was that it turned off the Agent's ability to control it's position, which was the correct thing to do if you wanted to use the Agent to do the pathfinding but control the locomotion yourself with an animation driven or steering based approach. With this change it's not clear how either of those options would even be possible.

    Hopefully we can get a dev on the AI team to comment on this.
     
  5. Carpe-Denius

    Carpe-Denius

    Joined:
    May 17, 2013
    Posts:
    842
    I tried Phils suggestion, it works. updatePosition and updateRotation should be true, OnAnimatorMove should set agents velocity and after that, it works like before. Animation is in control of locomotion, the agent is in control of pathfinding.

    But if somebody of the AI-team reads this...
    A few callbacks would be nice, like "ReachedPathPoint" or "FinishedCalculation"
     
    twda and DanSuperGP like this.
  6. DanSuperGP

    DanSuperGP

    Joined:
    Apr 7, 2013
    Posts:
    408
    Oh I see
     
  7. p87

    p87

    Joined:
    Jun 6, 2013
    Posts:
    318
    I am doing the same thing, using NavMeshAgent for path finding, and using a combination of Animation Root Motion and Scripts for movement and rotation. It does feel kind of hacked together.

    I wish there was some way to configure the NavMeshAgent so it would only rotate, and not move. But it seems like when you disable the agent's movement (I set the speed to 0) it stops rotating as well.

    So if that was the intended usage of the updatePosition flag in the past, I'm kind of curious why it was changed. I never used the updatePosition flag in the past, so I'm not familiar with how it worked before.

    It seems like the NavMeshAgent could benefit from a little separation of concerns - one component for pathfinding, and one component for movement.
     
    twda likes this.
  8. Carpe-Denius

    Carpe-Denius

    Joined:
    May 17, 2013
    Posts:
    842
    You could use rotatetowards in your OnAnimatorMove.
    There is navmeshagent.warp for translating, with that and your hint everything should be possible.
     
  9. RElam

    RElam

    Joined:
    Nov 16, 2009
    Posts:
    375
    I think a unity dev needs to weigh in on this, because this just looks like a bug to me. I was using NavMeshAgent with a RigidBody, and moved it using desiredVelocity, which did work before, now I simply cannot do this (well, not without a really hacked/inefficient approach). Physically driven objects using pathfinding is a pretty common use case, so I seriously doubt they intentionally broke that.

    The 'fix' described here for animation locomotion, if I understand correctly, seems to work because essentially the animation is changing velocity and the agent is in charge of position. In the case of physics, I can't run simulation that doesn't move my objects, therefore the agent can't be in charge of position.

    What's in there right now doesn't make any sense, my guess is the internal position is some kind of threading byproduct or something, and the intent is some code is supposed to say 'if updatePosition is false, then some other position owner will set it', like rigidBody, and perhaps physics update or something else broke that path. Regardless, it'd be nice to have a unity dev confirm that this is a bug cause I don't wanna have to refactor to a less desirable approach.
     
    twda and p87 like this.
  10. VileDog

    VileDog

    Joined:
    Sep 6, 2012
    Posts:
    6
    For character walk animation i using next code:

    // Update is called once per frame
    void FixedUpdate () // Update() or FixedUpdate - does not matter!
    {
    navAgent.SetDestination (target.position);
    speed = navAgent.velocity.magnitude;

    anim.SetFloat ("speed", speed);
    }

    In beta01 everithing work fine. But now i'am using beta14 & now value of speed varable is jumping like crazy, even when character (navAgent) not moving!
    NavMesh was recalculated of course!
     
  11. Jakob_Unity

    Jakob_Unity

    Joined:
    Dec 25, 2011
    Posts:
    269
    You'd want to assign 'nextPosition' of the navmesh agent to control the internal agent (simulation) position in case 'updatePosition' is false - the position is subject to navmesh constraints (boundary and connectivity). Alternatively you can use NavMeshAgent.Move() to move the agent with a relative movement.

    When (re)enabling 'updatePosition' the transform position goes to the internal agent position - the reason is that we can't guarantee that the simulation position (constrained) can move to the transform position (unconstrained).

    I recently realized the documentation for 'nextPosition' is completely wrong - it's fixed in upcoming beta

    @
    RElam
    Could you elaborate on this (PM if necessary) - i'm not sure i understand your setup - are you switching between agent and physics controlling your GO ?

    @VileDog
    You may want to mask out the y-component of the velocity before the obtaining the magnitude.
     
  12. DanSuperGP

    DanSuperGP

    Joined:
    Apr 7, 2013
    Posts:
    408
    Ok, I find that confusing.

    If you are using the NavmeshAgent for pathfinding but not locomotion, for instance because you are using steering behaviors or animation driven locomotion techniques, I thought you set a destination, and then navigate toward the "nextPosition" on the path that's generated, and expect that once you reach that position the navmeshagent will update the nextposition to the next point on the path.

    But if you are setting nextPosition, aren't you changing the path itself?
     
  13. RElam

    RElam

    Joined:
    Nov 16, 2009
    Posts:
    375
    Not switching, I'm using the agent to determine where he wants to go, and physics to determine where he actually goes. IOW, for my purposes I don't want the pathfinding solution in charge of movement, just pathfinding. With this setup, I can 'drive' objects however I want, in some cases they're vehicles, in some cases characters, but all can be heavily influenced by physics simulation. Previously I could do this by monitoring desiredVelocity, and driving object through whatever means I wish to that velocity, and because there was a concept of desiredVelocity, I assumed that the usage case of using NavMeshAgent just for pathfinding was considered, but perhaps it was not and I've just been taking advantage of a byproduct.
     
    DanSuperGP likes this.
  14. DanSuperGP

    DanSuperGP

    Joined:
    Apr 7, 2013
    Posts:
    408

    You're not the only one.
     
  15. Roni92

    Roni92

    Joined:
    Nov 29, 2013
    Posts:
    225
    And that's why I don't use navmeshes in Unity and done own pathfinding instead... Because PF is PF, not moving system. It just should return array of positions where you should move, not actually move my object.
     
    twda and jeffreyf like this.
  16. Jakob_Unity

    Jakob_Unity

    Joined:
    Dec 25, 2011
    Posts:
    269
    So if you want the agent to do pathfinding and physics to do the path following - it should still work.
    However you might end up in a deadlock - whenever physics prevents the agent from moving through
    (i.e. there's a passage in navmesh - but not in physics world).

    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4. public class MoveRigidbody : MonoBehaviour {
    5.    Rigidbody rb;
    6.    NavMeshAgent ag;
    7.  
    8.    void Start () {
    9.      rb = GetComponent<Rigidbody>();  
    10.      ag = GetComponent<NavMeshAgent>();
    11.  
    12.      // Disable agent control of the transform
    13.      ag.updatePosition = false;
    14.      ag.updateRotation = false;
    15.    }
    16.    
    17.    void Update () {
    18.      // Move rigibody by agent velocity and update agent position
    19.      rb.velocity = ag.velocity;
    20.      ag.nextPosition = rb.position;
    21.    }
    22. }
    23.  
    Is this the gist of what you're doing ?
     
  17. RElam

    RElam

    Joined:
    Nov 16, 2009
    Posts:
    375
    Yea, something like that, terminology is certainly a bit funky, but I'll try this out this weekend and relay my results. Sounds promising.