- Home /
Preventing 2D Vehicle Slip
Hello,
I'm working on 2D vehicle that moves left/right. On flat ground everything works as expected. The issue is when the vehicle needs to go up a hill (a steep one) slowly.
The vehicle pretty much begins to slow down and then slides down, then climbs a little and then slides down again. This repeats and repeats.
My goal is to have the vehicle move at a desired speed like a cruise control.
I will do some more experimenting.
Here is a video of the "issue":
https://www.youtube.com/watch?v=RiiHQnkcztQ&feature=youtu.be
Keep in mind that I have friction for the wheels and ground set to 1.
Answer by Ossi101 · Jul 20, 2019 at 09:24 PM
It took some tinkering and I came up with as simple of a solution as I could for the slipping. I just played with the mass of the wheels depending on what direction the vehicle was going. I wrote two scripts, the first one to manage each individual wheel, in my case, a back and a front. My second script takes the input and gives it to the wheels as needed by the direction of movement. The car game object and the wheels are all dynamic Rigidbody 2Ds as well as their respective Box Collider 2D and Circle Collider 2D with Wheel Joint 2D.
Here is the script for the wheel:
using UnityEngine;
public class Wheel : MonoBehaviour
{
public Rigidbody2D myRigidbody2D = null;
public WheelJoint2D wheelJoint = null;
public float speed = 500.0f;
private JointMotor2D motor;
private float direction = 0.0f;
private void Start()
{
motor = wheelJoint.motor;
}
private void FixedUpdate()
{
if (direction == 0.0f)
{
myRigidbody2D.mass = 1.0f;
wheelJoint.useMotor = false;
return;
}
else
{
wheelJoint.useMotor = true;
motor.motorSpeed = direction * speed;
wheelJoint.motor = motor;
}
direction = 0.0f;
}
public void Move(float directionalInput)
{
direction = directionalInput;
}
public void SetMass(float mass)
{
myRigidbody2D.mass = mass;
}
}
This script has Move() and SetMass() methods to control what the wheels do in relation to the main body of the vehicle. And when the wheel has a direction it will start the motor to move it. If there is no direction the mass is reset and the motor is turned off. Resetting the mass here is key because when the vehicle is not moving the added weight is not needed to produce the right amount of friction to climb slopes. Although you could remove this if your situation needs it. It's up to you!
This is the script for the vehicle body:
using UnityEngine;
public class CarMovement : MonoBehaviour
{
public Wheel backWheel = null;
public Wheel frontWheel = null;
public float overrideWheelSpeed = 0.0f;
public float massOnWheel = 5.0f;
private float directionalInput = 0.0f;
private void Start()
{
if (overrideWheelSpeed > 0.0f)
{
backWheel.speed = overrideWheelSpeed;
frontWheel.speed = overrideWheelSpeed;
}
}
private void Update()
{
directionalInput = 1.0f;
if (directionalInput > 0.0f)
{
backWheel.Move(directionalInput);
frontWheel.Move(directionalInput);
frontWheel.SetMass(massOnWheel);
}
else if (directionalInput < 0.0f)
{
frontWheel.Move(directionalInput);
backWheel.Move(directionalInput);
backWheel.SetMass(massOnWheel);
}
}
}
The input method for moving the vehicle here is just making it automatically go to the right. You can just replace that with player input if you want. No matter what direction we want to move in all the wheels need to spin to generate enough friction to overcome a slope. However, without proper weight distribution on the wheels the vehicle will flip over onto itself. So I applied an increase in mass to the leading wheel. This way when there is an incline that wheel will "stick" to the ground more easily.
Some things to note about this code. You can assign different speeds per wheel manually. Or you can apply one speed globally from the CarMovement script. So long as overrideWheelSpeed is some value above 0.0f it will take that over the wheel's speed. Just a little convenience thing since usually you'll have one speed.
I find that an overrideWheelSpeed of 500-1500 is best in conjunction with a massOnWheel value of 5-10. If you start to go above 2000 speed the physics kinda falls apart ahaha! That's physics for you! I hope this was helpful! Good luck!
Here's the result of my code, first at 500 speed and then 1000 speed per wheel at 5 mass: 
Your answer
Follow this Question
Related Questions
Bumper physics not working, 1 Answer
2D How to make character slowly stop after moving 1 Answer
Loading a scene with a long press! 1 Answer
how to remove all bounce in unity 2d. 0 Answers