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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Why nav mesh agent Movement so weird?

Discussion in 'Scripting' started by leegod, Sep 16, 2019.

  1. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,345
    I just want to natural follow moving to target, but using navmesh agent is very weird...

    I just set navmesh agent like Unity's enemy AI tutorial's one.

    navMeshAgent.speed = moveSpeed;
    private void Chase(StateController controller)
    {
    controller.navMeshAgent.destination = controller.chaseTarget.position;
    controller.navMeshAgent.Resume();
    }

    and result is,

     
  2. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,890
    Make sure there is no Rigidbody or anything on it.
     
  3. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,745
    Navmesh is simple interface built at top of quite complex solution. Undestanding and configuring it's movement may take time. For now it looks like it tries to approach position occupied by other agent. Also it has features like acceleration, slowdonw, target tracking, etc. Probaly the surface is not smooth enough.
     
  4. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,345
    removed rigidbody, but the same vibrating movement.
     
  5. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,345
    hm... then what is good way to make enemy track player and chase movement? just with transform.moveforward and play walking animation? Is this follow surface with just rigidbody with gravity turned on?
     
  6. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,745
    Instead of setting player's position as enemy target, try to find free spot around player far enought from it's body for enemy to stand free (without collisions with player) there and close enough for enemy's attack animation to perform nicely. Set this position as target and update it as player moves away from this position.
     
    tonialatalo likes this.
  7. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,345
    made target as some child transform that is positioned ahead of character, but still monster's vibrating motion does not stop.
     
  8. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,745
    This might be because not smooth navmesh (show it here) or are you using LookAt anywhere?
     
  9. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I suggest you do a simple test without an animated object to understand where you are going wrong with it.

    The documentation illustrates a lot of steps if you are doing root motion, for example. You will need to pay attention for root motion.

    That said, I do not use the agents at all, but instead just ask navmesh to give me a set of corners. The agent uses the same data anyway.

    At leas then when you have a path of Vector3 from navmesh, you can choose how to move how you wish and avoid all these issues.
     
    tonialatalo likes this.
  10. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,386
    Is there a way to calculate a path without even having an agent? I also prefer to handle movement myself, but so far I've always been using a NavMeshAgent to find a path.

    I previously posted some code in response to a previous post a while back:
    https://forum.unity.com/threads/player-jump-not-allowed-on-navmeshagent.718364/#post-4799339
     
  11. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Yeah the NavMesh class allows you to calculate a path how you would like. The path also includes any offmesh links and so on, it all just works. Internally, the agent queries the same stuff.

    https://docs.unity3d.com/ScriptReference/AI.NavMesh.CalculatePath.html

    It is not costly really. It's just written like that in the docs because the agent will do smaller hops there while if you calculate it, there's nothing stopping you from asking it to calculate miles worth.

    In my case I simply restrict path requests to one per frame, and there doesn't seem to be an impact I can measure much so there you go...
     
    tonialatalo likes this.
  12. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Is there any project that does not eventually grow out of the built in navmesh and moves to A* pathfinding project or similar? :D
     
  13. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,345
    Yes vibration reason was LookAt function. So I removed it, but now why this monster walking around back and forth?

    I just did wrote 2 lines code.

    controller.navMeshAgent.destination = controller.chaseTarget.position;
    controller.navMeshAgent.Resume();


     
  14. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,204
    @leegod, never have one transform look directly at a different transform in a top-down game. That'll cause a ton of problems (like vibrating) when their y-position isn't the same. Instead, look at a point that's at the target's x- and z-position, and the looker's y-position:

    We did ship a serious game with built-in navmesh. That was a mistake. I wouldn't say that projects outgrow it as much as it's not suitable for making anything in the first place.

    They're porting it to DOTS now, for some absurd reason. That's turd-polishing at scale for you.
     
    MookeeDev and AndersMalmgren like this.
  15. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I haven't found any problem I can't work around but then I am not using the agent. What were the problems you guys were having? Was it with getting manual paths or agent issues?

    I didn't bother with other assets as they created too many allocations for my taste.
     
  16. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Too little hooks for serious AI development. For example we needed to query the navmesh todo custom processing ontop of it, talk abit about it here

     
    hippocoder likes this.
  17. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,745
    Looks like something stops it from reaching it's destination. Try to disable all physics and remove player and other obstacles, let the beast just reach some destination points to avoid interferences from other objects/physics/ whatever
     
  18. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I solved that by building an open-edge list off the internal mesh that Unity uses. So I know where all the cover points are and it's no problem for me. I didn't need to hook in, but I could've done with a cleaner way to do it.

    Additionally, it's a shame I can't get access to the raw navigation mesh before it is optimised by Unity. They allow debug display of it, so it's there, but they don't allow access to the initial mesh, only the optimised one, which isn't much use when you want to figure out the local topology.

    Because they don't make games with it.

    Wasn't a blocker but I see where you are coming from for sure. Unity needs to do some complex AI such as bots for their shooter. This would give them a clear picture, I'm sure.

    But I would not go as far as to say that you can't make a decent game with Unity's built in (recast) navigation. Most AAA games also use the same source code (as does A* project), but as you point out, the access to the internals does suck.

    It's not even a package yet. I don't think they have any real interest in it. At least it's not crashing and seems stable enough.
     
    tonialatalo and AndersMalmgren like this.
  19. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,204
    It's a stupid black box. If I want it to do something specific, I can't, I instead have to tweak arcane, poorly documented knobs to get something in the vicinity of what I want. There's no hooks to do anything meaningful. Everything is poorly coupled.

    Baking is horrid. You have to give it a bunch of geometries and settings and hope for the best.
    Any baking based on looking at input geometries divorced from any knowledge about the game they're in is going to be bad, but that's the only way you can do things in Unity's setup.

    Baking is a good option for games with very, very simple geometry, and for prototyping, but you really want to be able to just feed in the correct mesh based on what you know about your own game. We spent countless hours fighting against thin slivers, bad corners, weird shapes, and other stuff like that.

    Also, If I want to have to navmeshes next to each other - say a land-based one for land creatures and a water-based one for water-based creatures - then they'll automatically connect to a single mesh, which means that water-based things will be partially on land and land-based things will be partially in water. Woop woop.


    And the agents are worse:
    I can't meaningfully define how the agent takes corners - it will always hug it as tightly as possible, usually in a way that looks bad. I can't define how agents avoid each other, just what their radius is. Their radius when taking corners and avoiding each other is tied together.

    The agent's acceleration and deceleration is the same variable, and I can't do anything about that.

    There's no built-in way to say things like "move by turning". Instead, the agent moves in a straight path towards it's target, always. The way you're supposed to work around that is to use root motion, which is a hack on top of a hack. It also, by default, doesn't take it's facing into account when deciding speed.

    CalculatePath returns true when it can't find a path, as long as it can find a partial path.

    The navmesh defines the points where the agents can have their center position. This means that all solutions for agents with different radiuses will be bad.

    Automatic off mesh links only go down. If you want to automatically be able to jump up, you have to place those out manually.

    Stuffing a bunch of agents into a tight corridor doesn't handle gracefully at all either, last time I checked. Putting a bunch of agents close to each other also performed pretty poorly.

    So the agents are dumb, slow, and look bad.
     
  20. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,345
    This really make me turn off interest on NavMesh permanently.
    Then what do you use for monster, characters movement?
     
    Last edited: Sep 18, 2019
  21. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    In this case you can (like me) tell it to generate the navmesh from physics colliders, and this is pretty precise/predictable thankfully. Bit late now but maybe someone reading will find it useful.
    This is avoidable by creating a different agent type. There can be as many as you like, but basically there will be one separate navmesh baked per agent type, so you can filter it. It's not just for different sizes. But you can also do this via the navmesh surface component. I think you got bit by old navmesh builtin stuff and not the github stuff. And that's 100% Unity's fault for have a crap workflow spread all over.

    For example it can't even do automatic navmesh links, and you have to supply your own. It's fairly different now. But that'a too late and Unity is not doing a good job clarifying matters.
     
    tonialatalo likes this.
  22. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,204
    Yeah, I have looked at the new navmesh stuff, and it looks somewhat improved - but why isn't it a package? And the initial announcement turned me off - I asked them if they were going to let us supply our own meshes, and they were like "we believe you get the best results from baking".

    Aron Granberg's A* project does the same thing as builtin, but with (paid) source access and more options. For our current game we rolled our own thing, as we had very different needs and needed a different kind of navigation.
     
    DwinTeimlon and hippocoder like this.
  23. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,345
    I mean, not the pathfinding, but just character's movement solution. Using CharacterController of Unity builtin?
     
    Last edited: Sep 18, 2019
  24. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,345
    Code (CSharp):
    1. public class ChaseAction : Action
    2. {
    3.     public override void Act(StateController controller)
    4.     {
    5.         Chase(controller);
    6.     }
    7.  
    8.     Vector3 moveDirection = Vector3.zero;
    9.     private void Chase(StateController controller)
    10.     {
    11.         float gravity = 9.8f;
    12.         if ((controller.chaseTarget.position-controller.transform.position).magnitude >= controller.chaseStopDis)
    13.         {
    14.             if (controller.chaController.isGrounded)
    15.             {
    16.                 moveDirection = controller.chaseTarget.position - controller.transform.position;
    17.                 moveDirection = moveDirection.normalized * controller.moveSpeed;
    18.                 gravity = 0;
    19.             }
    20.             Debug.Log("Chase call");
    21.             moveDirection.y -= gravity * Time.deltaTime;
    22.             controller.chaController.Move(moveDirection * Time.deltaTime);
    23.         }
    24. }
    So I set like above with Character Controller attached to monster, and set Movespeed as 2 or 3 and chaseStopDis as 10, but even if monster's distance become shorter than 10, it still move slightly periodically and irregularly toward to character, finally touch and push it.

    Why this happen?
     
  25. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,886
    I think you should probably open a new thread in relevant support section as what your asking has nothing to do with navmesh or navmesh agents which is what this thread is originally about
     
  26. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,345
    But in this thread I posted relevant video links, and its very strange that why those codes inside
    1. if ((controller.chaseTarget.position-controller.transform.position).magnitude >= controller.chaseStopDis
    this line is called..even when 2 thing's distance is very close... Same result with Vector3.Distance too.
     
  27. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I have complained about it not being in a package and it's not just me. I suppose DOTS rewrites have taken priority but it would have been nice to communicate that to users. I'm still guessing. Because that's all I have.

    Still, it is usable and I am using it. But it feels woefully understaffed.
     
  28. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,345
    So I set

    Debug.Log(Vector3.Distance(controller.chaseTarget.position, controller.transform.position));

    and have monitored this values, but very strangely, it should maintain similar value, but sometimes it became very weird value. It should maintain within 15 because I set min distance both characters have as 15, but like below image, it became over 15, (suddenly it become 31) then .Move code called and become closer, and finally it break the line and keep moving.

    Very frustrating. So vector3.distance not calculated accurately always?

    Any other way to stop moving when both character controller's position is close enough as I can set distance between?

    distance.PNG
     
  29. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Vector3.Distance is always accurate. But do you know what you are passing in? GIGO.
     
    MadeFromPolygons likes this.
  30. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,345
    Code (CSharp):
    1. private void Chase(StateController controller)
    2.     {
    3.         Debug.Log(Vector3.Distance(controller.chaseTarget.position, controller.transform.position));
    4.         moveDirection = Vector3.zero;
    5.         if (Vector3.Distance(controller.chaseTarget.position, controller.transform.position) >= controller.chaseStopDis)
    6.         {
    7.            
    8.             if (controller.chaController.isGrounded)
    9.             {
    10.                 moveDirection = controller.chaseTarget.position - controller.transform.position;
    11.                 //moveDirection = controller.transform.TransformDirection(-moveDirection.normalized);
    12.                 moveDirection = moveDirection.normalized * controller.moveSpeed;
    13.             }
    14.         }
    15.  
    16.         moveDirection.y -= gravity * Time.deltaTime;
    17.         controller.chaController.Move(moveDirection * Time.deltaTime);
    18. }
    I don't know. Just this code and character controller.

    character-control.PNG
     
  31. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
  32. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,345
    I don't use NavMesh, and at above my code, there is no NavMesh related.
     
  33. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,886
    What? This thread is literally called "why navmeshagent movement so weird"

    So what exactly are you doing if your using a navmeshagent but no navmesh?

    If not using a navmesh, but you were when you made this thread: make a new thread with relevant info or at very least update initial post so users know what is actually going on and what you are asking for?
     
  34. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,345
    Originally used, but it seems too much time to take to settle all down, so I changed to search more faster way.
     
  35. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,345
    So maybe I should use NavMesh again because CharacterController shows more weird phenomenon I can't understand why and can't find my code's wrong.
    And so how to set movement speed of NavMesh agent?
     
  36. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    In the navmesh agent component there is a speed.
     
    MadeFromPolygons likes this.
  37. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,345
    navMesh movement too shows this maddening. It does not stop at outside of borderline I set.

    Here is video and code.

    I set controller.chaseStopDis value as 15.



    Code (CSharp):
    1. Debug.Log(Vector3.Distance(controller.chaseTarget.position, controller.transform.position));
    2.      
    3.         if (Vector3.Distance(controller.chaseTarget.position, controller.transform.position) >= controller.chaseStopDis)
    4.         {
    5.             controller.navMeshAgent.destination = controller.chaseTarget.position;
    6.             controller.navMeshAgent.isStopped = false;
    7.         }
    8.         else
    9.         {
    10.             controller.navMeshAgent.isStopped = true;
    11.         }
     
  38. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,345
    So I found the reason that "Target" empty transform inside player character's Y position fluctuate a little bit by Idle animation of character.

    So this causes Vector3.distance's weired value changes, result in enemy break the border line and make it keep moving towards character.

    By human sense, this is ridiculous because even if that Target transform is fluctuate, it is very slight amount of Y position, and it should not affect the Vector3.Distance meaningfully.

    But the reality is not, so this is Unity's bug maybe.

    So after I put out that Target transform from character, so its transform position is static, and monster does not come too closer to Target no matter how long time passes as intended.
     
  39. New_Game_Ideas

    New_Game_Ideas

    Joined:
    Jul 17, 2021
    Posts:
    4
    This may be because of auto breaking. (If you decide to toggle it off make accelaration 9999 -or very high amount like tihs one- otherwise, it will move back and forth around the targetPosition). Also I advice you to use SetDestinaiton instead.
     
  40. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Not really, no.

    Use dot product using two vectors:
    a = direction from corner before destination, to destination
    b = agent velocity or movement direction

    Then check the dot product result is positive or negative (depending on your specific needs) to see if you've arrived or even slightly gone past it. It's fool-proof and doesn't require special conditions, maths or guesswork.