Search Unity

NavMeshAgent and player vehicle with collisions - How to do it properly?

Discussion in 'Navigation' started by AutoAssault, Jul 1, 2019.

  1. AutoAssault

    AutoAssault

    Joined:
    Apr 17, 2019
    Posts:
    3
    Hello Unity Community!

    I'am currently experimenting with NavMeshAgents and vehicles with RigidBody (cars). I wanted to share some ideas how to implement NavMeshAgents with physics system in order to be able to hit a NavMeshAgent with a player vehicle with Rigidboy.

    But since things didn't work that good, I am seeking for some advices.

    Attention, wall of text!!

    My goal is to have the following: A driving "NavMeshAgent vehicle" which follows certain paths and can be rammed by the player vehicle i.e. if the player vehicle hits the "NavMeshAgent vehicle" it physically interacts "correctly" in terms of impulse, weight etc.

    What is the problem?: If I setup an NavMeshAgent, it requires to be "isKinematic = true" and it has to have a RigidBody. Since "isKinematic" is set to true, no physics can be applied anymore or in other words the player vehicle can't ram the "NavMeshAgent vehicle".

    To overcome this problem I thought about some approaches. I tested them, but I was not very satisfied with the results. Here are two of my approaches:

    1) I made an "extended" trigger area around the AI vehicle with a capsule collider and an OnEnterTrigger function which detects an incoming nearby player (about 10~15m away from the center point of the AI vehicle) so the "NavMeshAgent vehicle" can set "isKinematic" = false in order to allow the "NavMeshAgent vehicle" for a short time to be hit by the player. An then afterwards if the player leaves the trigger area I set "isKinematic" = true again to continue whatever it has to do.
    However: This does not work very well with large approaching speeds (~130km/h) of the player vehicle. Since the physics systems updates about 30(?) times a second, it only sometimes work due to depending on when the physics updates. ( I am very well aware of this problem). It also makes the AI vehicle stopping for that period of time when the player is inside the trigger area since "isKinematic" is set to false, it can no longer drive/move by the AI system.

    2.) The overcome the physics update problem, I implemented a "collision approaching system". Instead of making an extended collider around the vehicle, I just simply callculate the distance between player and AI vehicle and check the direction vector of the player. If the player direction vector points towards the AI vehicle and the distance between them is short enough (distance was depending on speed of player vehicle, the faster the player, the larger the distance) I again set "isKinematic" = false and then the player can hit the AI vehicle.
    The second implementation turned out to be better in terms of detection, since it does now not rely anymore on physic update system. But I encountered another problem: When do I set "isKinematic" = true (Edit: I wrote "false" here, but it should be "true") One way I tested was "after a certain amount of time" but this turned out be very bad...in some cases the AI vehicle slapped the player vehicle below the terrain :D Other things I tried was by checking if all or at least 2 (or 3) out of 4 wheel colliders are touching the ground...but this caused similar issues.

    My approach in 2) solves the problem partially, but I still don't know how to complete this task. I think it is not very elegant in this way and it makes the AI vehicle weird.

    If you guys have some special tips or could give me some advices of helpfull hints or some links to similar issues I'd be very thankfull!

    regards!
     
    Last edited: Jul 2, 2019
  2. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    313
    I feel you're pretty close with your second solution. Perhaps you need to predict more accurately when the two cars will collide? If you have the direction of both cars and their velocities, you should be able to calculate their moment of impact. Then you know when you need to set IsKinematic as false.
    Alternatively, you can still set IsKinematic to false pre-emptively. The only thing you should add is that your car needs to keep moving like before. Before you change the flag, get your agent's velocity and store it, then give it to your rigidbody as soon as you've turned the flag on.
    This should give a pretty unnoticeable transition. If that doesn't do it, you might have to calculate a force to apply to your rigidbody instead.
     
  3. mistergreen2016

    mistergreen2016

    Joined:
    Dec 4, 2016
    Posts:
    87
    I'm sure you did this, agent.enable = false with isKinematic = false will allow the physics to take over.

    Also another option to using isKinematic is to freeze/unfreeze x,y,z in the rigid body..
     
  4. AutoAssault

    AutoAssault

    Joined:
    Apr 17, 2019
    Posts:
    3
    Hello Yandalf & mistergreen2016,
    thank you both for your replies!

    BIG sorry, in my text (in the second approach) I mixed up false/true. It should be: When do I set "isKinematic" = true? (and not "false" - I will correct this in my original post)...Now my question should make more sense :D

    After I set "isKinematic" = false the AI vehicle can be hit. Here you are right Yandalf: This is not an issue since I already can do calculate the time of impact accurately. Huge sorry here about the confusion here...I wrote this poste late night.

    Maybe the following helps to understand the problem: The player can drive around in the world and will encounter driving AI vehicles at some places. The player vehicle should be able to phyiscally attack the AI vehicle by ramming it. You can think of a little ramming battle between AI and player (if the player wishes do to so), although the AI does not perform complex maneuvers. (Maybe chasing the player within a certain radius and try to ram him - very basic stuff).

    Now, a "ramming battle" like this would end up in a constant switching between setting "isKinematic" = false and "isKinematic" = true on the AI vehicle. The actual problem I am facing here arises everytime the player has hit the AI vehicle or vice versa.

    Think of situations, where the AI vehicle gets thrown in the air (maybe 1~2 meter) and lands (partially) on the player vehicle. These kind of situations causes problems. Because as soon I set "isKinematic" = true, the AI vehicle becomes like a "heavy stone" and smahes everything under it away. There was a situation where the player vehicle slipped through the terrain..and this shouldn't happen at all :D

    @mistergreen2016
    I already experimented with freeze/unfreeze x,y,z but this was not a suitable option for this task. But I think maybe I should play around with agent.enable = false. Thanks for the hint. I remember that there was situtation where could be usefull.

    Again sorry for the confusion in the first post. I hope the second post helps to understand my problem.
     
  5. mistergreen2016

    mistergreen2016

    Joined:
    Dec 4, 2016
    Posts:
    87
    Why does the player vehicle slip through the terrain if isKinematic = false (player)?
     
  6. AutoAssault

    AutoAssault

    Joined:
    Apr 17, 2019
    Posts:
    3
    @mistergreen2016
    The player vehicle slipped through the terrain when the AI vehicle "droped" on the player vehicle and "isKinematic" was set to "true".
    If "isKinematic" = false, everything is ok, there is no problem (since physics can now be applied).

    If "isKinematic" = true, the AI vehicle will clear away everything on it's path. So it does too if it drops on a player vehicle with "isKinematic" = true.

    To further clarify on this: The only vehicle who has a NavMeshAgent is the AI vehicle. The player vehicle of course is controlled by keyboard/mouse. It does not have NavMeshAgent.

    regards
     
  7. mistergreen2016

    mistergreen2016

    Joined:
    Dec 4, 2016
    Posts:
    87
    Try freezing player's Y position in that instance.