[SOLVED] What is the best way to move my rigidbody car in unity?

I am currently making a car controller in unity and looking for a way to move my car while being able to correctly collide with obstacles. I also want the car to be able to drive on uneven roads. The road is kinematic while the obstacles have gravity and are not kinematic.
1 – I tried using transform.Translate but as expected, it just ended up ignoring colliders.

        verticalInput = Input.GetAxis("Vertical");
        transform.Translate(transform.forward * speed * verticalInput * Time.fixedDeltaTime);

2 – I then tried using Rigidbody.MovePosition() while the car has gravity and is not kinematic. The car was able to correctly drive on uneven roads but wasn’t successful in pushing away the obstacles. The obstacles were pushed below the car (between the wheels).

        verticalInput = Input.GetAxis("Vertical");
        rb.MovePosition(rb.position + transform.forward * speed * verticalInput * Time.fixedDeltaTime);

3 – I tried using Rigidbody.MovePosition() while the car is kinematic with self-coded gravity. The car fell down and ignored the road collider. But I noticed that this approach made the car interact well with the obstacles.

        verticalInput = Input.GetAxis("Vertical");
        rb.MovePosition(rb.position + transform.forward * speed * verticalInput * Time.fixedDeltaTime);

4 – I tried altering the Rigidbody’s velocity while the car is not kinematic. The car tumbled instead of moving like an actual car. The car also can’t be steered.

    verticalInput = Input.GetAxis("Vertical");
    // Move the vehicle
    rb.velocity = new Vector3(rb.velocity.x, rb.velocity.y, speed * verticalInput * Time.fixedDeltaTime);

5 – I used Rigidbody.AddForce() while the car is not kinematic. I had to set the speed to like 100000 then the car started very very slow then accelerated to a very very fast speed. (I want the car to move like a transform.Translate)

        verticalInput = Input.GetAxis("Vertical");
        rb.AddForce(transform.forward * speed * verticalInput * Time.fixedDeltaTime);

Btw, I’m using Unity 2020.1

1 and 2 are “teleporting” the rigidbody. The physics engine tries to resolve collisions after the teleport, but then you teleport the rigidbody again. This makes collisions highly inconsistent. Sometimes some collisions work, other times some collisions don’t work.

3 - In kinematic rigidbodies the position is controlled by the user, not by the physics. The rigidbody will go wherever you move it to, ignoring any collision geometry.

4 - Similar to 1, but with velocity. The physics engine computes some velocity, then you override it, and the engine computes the next step using the new value. The result is inconsistent. Additionally, velocity is a time-independent magnitude here. Time.fixedDeltaTime doesn’t make sense here.

5 - AddForce is the way to go, but this implementation is incorrect. Also, again, Time.fixedDeltaTime doesn’t make sense here.

One correct way is calculating the velocity you want, then applying the difference with the current velocity via AddForce with ForceMode.VelocityChange. This will cause the rigidbody to move at the expected velocity, and collisions will be resolved properly because all the work is done by the Physics engine:

rb.AddForce(expectedVelocity - rb.velocity, ForceMode.VelocityChange);

You may also want to learn about the different combinations of rigidbodies and colliders, and proper example usages of each case:

https://forum.unity.com/threads/help-understanding-all-8-collider-rigidbody-combinations.525258/