Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

Rigidbody + NavMeshAgent

Discussion in 'Physics' started by Multithreaded_Games, Jan 18, 2017.

  1. Multithreaded_Games

    Multithreaded_Games

    Joined:
    Jul 6, 2015
    Posts:
    121
    Hi all,

    So, I have a somewhat unique situation as far as I've determined and I'm throwing this out there to see if anyone has solved it or has any additional recommendations. Warning: this is a slightly long post.

    I would like to use a NavMeshAgent in conjunction with a Rigidbody. However, I do not want to use pathfinding--namely, I want to use the NavMeshAgent for its ability to keep my character grounded at all times. Our game does not feature any jumping, nor is the player character able to fall off of edges (this is a somewhat old-school RPG) and the NavMesh did a beautiful job of preventing those two things from happening.

    As far as I've been able to figure out, navigation updates are done based on the Update function and NOT FixedUpdate. This is important because I would also like for the player character to be able to respond correctly to collisions with static and occasionally moving objects with Rigidbodies. This means, and again, as far as I can tell, I should directly alter the movement of this character within FixedUpdate.

    Let me back up slightly: currently, our game handles player input AND movement within the Update function. OK, cool. Camera control is handled in LateUpdate. Still good, everything's great--until you collide with an object. At this point, an unacceptable amount of jitter enters the fray and it makes sense. I reckon that if you want accurate physics responses, you need to do those updates at the same interval as physics (FixedUpdate)

    So like any good programmer, we cheated. We found out early on that changing the Physics timestep to something smaller (IE, smaller period, larger frequency) actually fixed our jittery collision issue. Why? Well, it's simple in retrospect: when running the game at 60 FPS, the fixed timestep we chose (0.016) matched up closely with the forced update rate of the game (also 60FPS.) This resulted in very smooth collisions. However, this is a terrible thing to do and I would not recommend it as games that do not run at that rate will still suffer from jittery collisions.

    So this is a no-go overall, but it solved the problem for certain cases. Eventually, we decided to migrate to a new controller, but problems arise when trying to use a completely physics-based model for determining movement, issues that I don't necessarily feel like trying to debug, especially when the NavAgent 'forced groundedness' already solved these issues. Not to mention our project is quite mature already and redoing our terrain is pretty much a non-option at this point.

    So let's cut to the chase: has anyone successfully used a NavMeshAgent (again, not using it for actual pathfinding) with a Rigidbody? I've determined that it does seem possible, at least, in theory to figure out the Navmesh Agent's 'sampled position', which could then theoretically be used in conjunction with FixedUpdate, whether it's via velocity/MovePosition updates, but I'm wondering how well this works in practice.
     
  2. henaxing

    henaxing

    Joined:
    Jan 17, 2015
    Posts:
    41
    My next project use that. Do set rigidbody with kinematic. That's what you want.
     
  3. Multithreaded_Games

    Multithreaded_Games

    Joined:
    Jul 6, 2015
    Posts:
    121
    I'm sorry, but this isn't actually what I want. Moving kinematic rigidbodies do not respond to collisions which pretty much immediately disqualifies it.
     
  4. henaxing

    henaxing

    Joined:
    Jan 17, 2015
    Posts:
    41
    That's not what I meant. I understood you wanted to move object with rigidbody and navemeshagent, and also you want it to be changed time to time, right? Then, move navmeshagent with kinematic body. If you want rigidbody again, then disable navmeshagent and also kinematic property of rigidbody, so it works with physics again. If it's not what you want, probably I understood problem wrong.

    Besides, you have to check navmeshagent with obstacles: navmeshobstacle, not colliders.
     
  5. Multithreaded_Games

    Multithreaded_Games

    Joined:
    Jul 6, 2015
    Posts:
    121
    Thanks again for your answer. I'm sure I wasn't clear enough: what I want is to be able to move the character using both the NavMeshAgent and Rigidbody simultaneously. I know that I can switch on and off, but I want to use the NavMeshAgent part to keep the character constantly grounded and collide with static obstacles more 'cleanly' and use the Rigidbody to collide properly with other actual Rigidbodies. The problem though is that NavMesh updates are not in sync with physics updates, which produces jitter in certain cases while moving. Ignoring for a moment why I'm trying to do this, I was merely wondering if it can be done and if anyone has successfully done it. To reiterate further, I'm not using the NavMeshAgent at all for its pathfinding.
     
  6. henaxing

    henaxing

    Joined:
    Jan 17, 2015
    Posts:
    41
    Rigidbody will collide with other static/dynamic collider even if they don't have obstacles. Obstacle only makes the clean path for path finder of NavMeshAgent.

    As I told you above, I'm using "the character using both the NavMeshAgent and Rigidbody simultaneously" on my new project, and mine works perfectly as I expected.

    So, the problem is.. the jittering? If it is, you should modify settings of NavMeshAgent or colliders, I think..

    By the way, if you don't use a NavMeshAgent for path finding, then why do you keep it? If grounding is the problem, then you may use the constraints of rigidbody.
     
  7. Multithreaded_Games

    Multithreaded_Games

    Joined:
    Jul 6, 2015
    Posts:
    121
    Sorry, let me back up a bit. I know the distinction between colliders and obstacles. I know quite a bit about both NavAgents and Rigidbodies as well. Sorry if I wasn't clear, but it isn't just to keep the character grounded. Another benefit to using a NavAgent is that you are inherently 'blocked' off from certain areas of the map. Our scenes contain many jagged rocks/slopes and most importantly, sheer dropoffs from higher elevations. With a NavAgent keeping the character 'grounded' (and I don't just mean, on the ground only, I mean NEVER in the air) we were able to avoid many undesirable effects without explicitly resorting to a full physics simulation. For instance, without a NavAgent and only driven by a Rigidbody-based third person controller, we now have to check every single rock in our scene and all sloped areas to ensure that the character cannot move on them. With a NavAgent on the character (again, even WITHOUT pathfinding), this is handled automatically. You cannot go places where there is no NavMesh period. This is a pretty significant deal for us because again, it keeps you from going into certain places automatically based on how the navmesh is built! It is incredibly time-detrimental to back and ensure that all rocks/slopes are handled correctly when you can just 'look' at the navigation mesh and tell instantly where you can and cannot go. Even better, you don't need explicit physics calculations to handle all collisions, only the ones that can occur with non-static objects that are not bound to the navmesh. But worst of all, with just physics and gravity, you can walk over the edges of certain things. Now, sure, I could write some code to raycast and see if you're going to fall and stop movement. I could easily do that. I could also raycast with physics to avoid every single 'rock' just by virtue of being a rock. But our project is quite mature and this requires a heavy rewrite of several different subsystems.Hopefully this makes sense so far.

    The basic problem is that I would have to resort to an entire physics-based simulation to get correct collisions (non-jitter in all situations) As I mentioned in my first post, this comes from an inherent difference in the times at which Update and FixedUpdate are ran. Physics simulations should be ran in FixedUpdate, but NavMesh calculations occur during Update. Having a NavAgent enabled at the same time as a Rigidbody that is being updated with velocity/AddForce updates results in them 'fighting' over the position of the character and results in jitter, not only in collisions, but even during certain camera movements. Again, I apologize for the lengthy response but this is a somewhat complicated problem and I'm not sure that I can break it down any further. I don't want pathfinding and I don't want to disable/enable a NavAgent/Rigidbody at different times--they should be enabled at ALL times and I furthermore cannot switch to a kinematic Rigidbody because they explicitly do NOT react with collisions against actual physics rigidbodies/colliders.
     
  8. henaxing

    henaxing

    Joined:
    Jan 17, 2015
    Posts:
    41
    Ok, now I got it clearly. Your point is that you want to set character movable only in certain places.
    Then, How about it? http://answers.unity3d.com/questions/889836/using-unity-navigation-in-a-fixed-timestep.html
    I hope it would be helpful but I'm afraid that you mentioned you don't need path finding what so ever..

    Besides, I think you can check movable places manually in every fixedupdate frame by raycasting or something with your movable places. I tested it by my self a moment ago, and it works perfectly. To remove jittering, the point is that you have to modify your position at last of fixedupdate. I did it with calling Coroutine and WaitForFixedUpdate in FixedUpdate.
     
  9. henaxing

    henaxing

    Joined:
    Jan 17, 2015
    Posts:
    41
    Here's my sample code to make it manually.

    void FixedUpdate() {

    this.StartCoroutine("checking");
    }

    IEnumerator checking() {

    yield return new WaitForFixedUpdate();
    // checking position with something..
    // set new position or prev position
    // you have to save prev pos to return
    }
     
  10. Multithreaded_Games

    Multithreaded_Games

    Joined:
    Jul 6, 2015
    Posts:
    121
    Interesting, wasn't familiar with the WaitForFixedUpdate coroutine being used in that way. I assumed that FixedUpdate would automatically be called at that point anyhow, but I will certainly try that. I've actually found out with further testing that it's possible to do NavMesh specific raycasts. It seems that it's possible to still use the NavMesh in conjunction with the Rigidbody to both work simultaneously.

    Thanks again for bearing with me and your responses!
     
  11. henaxing

    henaxing

    Joined:
    Jan 17, 2015
    Posts:
    41
    Yeah, we can always find our own solutions. WaitForFixedUpdate can be usable in varius situations at last of FixedUpdate. I'm glad that it was helpful. Good luck! I love Unity. ;)
     
    Hafazeh likes this.
  12. Xepherys

    Xepherys

    Joined:
    Sep 9, 2012
    Posts:
    178
    You can also set agent.updatePosition=false (and agent.updateRotation=false) in script to prevent Nav AI from moving the character.
     
    Unshackled likes this.