Search Unity

NavMeshAgent + Rigidbody to Rigidbody Friction

Discussion in 'Navigation' started by Gooren, Dec 9, 2017.

  1. Gooren

    Gooren

    Joined:
    Nov 20, 2015
    Posts:
    332
    Hi,

    I have a vehicular enemies controlled entirely by a NavMeshAgent component. They also have a kinematic Rigidbody component attached to them for collisions and physics interactions.
    Now imagine some debris falling on a moving vehicle's flat roof. When it falls there and stops moving, it should move with the vehicle thanks to the friction. This is the most "hardcore" physics scenario we have.
    But the enemy just slides from below the debris which then falls on the ground and it looks just bad.
    So I have set NavMeshAgent's updatePosition and updateRotation properties to false and started using
    Code (CSharp):
    1. private void Update()
    2. {
    3.     // Position
    4.     rigidbody.MovePosition(navMeshAgent.nextPosition);
    5.  
    6.     // Rotation
    7.     Vector3 direction = navMeshAgent.steeringTarget - rigidbody.position;
    8.     direction.y = 0f;
    9.     if (direction.sqrMagnitude > 0.1f)
    10.     {
    11.         rigidbody.MoveRotation(Quaternion.RotateTowards(rigidbody.rotation, Quaternion.LookRotation(direction, Vector3.up), navMeshAgent.angularSpeed * Time.deltaTime));
    12.     }
    13. }
    I also checked my Physics Materials. The friction started working, but sometimes (during and after) steering/rotating the agent, the debris somehow obtains a higher velocity than the agent's velocity and falls down over the enemy's front. It seems to behave like if the enemy would be a high speed conveyor belt :D

    Does anyone know if it's even possible to make this work properly when NavMeshAgents update internally in the game loop and not in the physics loop? Making it stable seems impossible AFAIK :(

    Any advice would be greatly appreciated
     
    Last edited: Dec 9, 2017
  2. DwinTeimlon

    DwinTeimlon

    Joined:
    Feb 25, 2016
    Posts:
    300
    My experience is, that I had to switch of the NavMesh agent completely, let the physics do its job and then switch on the NavMesh agent again, when no physical interaction is needed anymore. This probably doesn't help with your current problem I guess.
     
    Gooren likes this.
  3. Gooren

    Gooren

    Joined:
    Nov 20, 2015
    Posts:
    332
    Your solution sounds great for physics based kickbacks and what not.
    In my case it won't help however, just as you suspected. I need continuous physics resolve. I need NavMeshAgents to truly update on every FixedUpdate :(
    Thanks for trying though.
     
  4. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    All but the simplest games should really not be using the navmesh agent. Use the navmesh to handle pathfinding, control movement of entities separately via controllers suited to the task. It just works better all the way around.
     
  5. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Here is a simple method that calculates a path and sticks it into a queue.

    Code (csharp):
    1.  
    2. private void UpdatePath(Vector3 destination)
    3.         {
    4.             NavMeshHit hit;
    5.             Vector3 start = Vector3.zero;
    6.             Vector3 end = Vector3.zero;
    7.  
    8.             Vector3 origin = transform.position;
    9.          
    10.             if (NavMesh.SamplePosition(origin, out hit, 5.0f, NavMesh.AllAreas))
    11.             {
    12.                 start = hit.position;
    13.             } else
    14.             {
    15.                 Debug.LogFormat("SamplePosition start failed {0}", origin);
    16.                 return;
    17.             }
    18.          
    19.             if (NavMesh.SamplePosition(destination, out hit, 5.0f, NavMesh.AllAreas))
    20.             {
    21.                 end = hit.position;
    22.             }
    23.             else
    24.             {
    25.                 Debug.LogFormat("SamplePosition end failed {0}", destination);
    26.                 return;
    27.             }
    28.  
    29.  
    30.             NavMeshPath path = new NavMeshPath();
    31.             if (NavMesh.CalculatePath(start, hit.position, NavMesh.AllAreas, path))
    32.             {
    33.                 CurrentPath = new Queue<Vector3>(path.corners);
    34.             }
    35.             else
    36.             {
    37.                 Debug.Log("CalculatePath failed");
    38.             }
    39.         }
    40.  
     
  6. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    FYI I have a physics heavy game with vehicles,and I highly recommend the Kinematic Character Controller plus navmesh for pathfinding for that scenario. The other approaches outlined above are hacks that will result in all sorts of strangeness. Physics has to be handled correctly and it's impossible to do that using the navmesh agents. They are fundamentally not compatible.
     
  7. Gooren

    Gooren

    Joined:
    Nov 20, 2015
    Posts:
    332
    The Kinematic Character Controller looks nice, but it would be impossible to use it for our TD 3D mobile game with 60 active units at the same time. And the local avoidance etc. would still be missing. I am currently checking if we can use A* Pathfinding Project as a Unity default navigation system replacement.
    Thanks for ensuring me that Unity navigation system is completely unsuitable for me though. I now feel more confident in replacing such a fundamental thing in our game completely.