Game programming

My first game in Unity part4 – Slowing down the car smoothly

Alrightyyyyy!

Each time I post, I learn something new (I mean, prior to posting, or else I’ll be keeping posting just to get [random?] knowledge, that’d be awesome!), and my script is getting a little more complex. Actually, this time, we’re going to create a new script, and it’s going to be linked to the script attached to the car. How cool is that?

You’ll have probably noticed I’ve made a new vehicle (not finished yet). That’s the one I plan to use for that game: a (small) truck. I won’t give more details for now. To the script! If you’ve followed most tutorials, your vehicle must be going quite much, even after releasing the accelerator, as if there was nothing to slow it down. However, motorized vehicles (all?) have what’s often called “engine braking” (NOT “jake brake”, that’s different). If the driver isn’t accelerating, the vehicle’s engine will slow the whole down.
Engine braking is braking that uses the resistance of engine rotation.
Although it’s not very true on automatic transmission cars (I didn’t know that before I moved to Japan, as cars in Europe are generally MT, AT being way more expensive – the opposite here), but that’s very noticeable on MT cars and motorcycles (even scooters). You’ve perhaps seen road signs asking to use engine brakes, especially in mountains.

In my case, because I don’t have enough knowledge about how to affect the motor’s rotation (if that’s even possible), I found what’s called Drag.
https://docs.unity3d.com/ScriptReference/Rigidbody2D-drag.html
Drag is the tendency of an object to slow down due to friction with the air or water that surrounds it.”
It’s not the same as engine braking, but that will do for now.

Activated only when NOT pressing a key
If just set without any conditions, drag will constantly apply a force that will go against our vehicle’s velocity. So I wanted it to be OFF when I was pressing the up/down arrow keys.
Here is what I did (I blurred/cut the unneeded code on purpose):

I added only 3 things:
public float dragForce = 0.5f; That will appear among the script component to make it easily editable. Note that 0.5 is quite high, I then changed it to 0.2 (and the truck’s mass to 1200)
– In void FixedUpdate(), rb.drag = dragForce; The drag value of our RigidBody2D (rb) is set to 0.5 every frame by default.
– Then, to bypass the default drag value, I added rb.drag = 0f; when both up and down arrow keys are pressed, regardless of the speed.

Testing aaaaand… it works! Nice! But wait a minute, I just noticed something peculiar while jumping. Yes! The car slows down the same way in the air that it does on the ground! (when I don’t press any keys)
Argh!

Why are you slowing down that much in the air?!!
Yes, there comes quite a troublesome issue, especially when an object has a big mass and a relatively low speed (way lower than its terminal velocity), it is not supposed to be slowed down that much!
Hm…let’s think about it for a few seconds. I want my vehicle to slow down thanks to its engine brake, so the conditions are… it should be happening when the front wheels are touching the ground AND when I’m not pressing the up/down arrow keys.
So my idea was to create a new wheel collider that will detect if it is touching another specific collider: the ground. Easier said than done… Although I figured out almost everything by myself, calling stuff from a script to use it in another was hard. Let’s do it in the right order, shall we?

Step 1:
First, I created an empty object inside the FrontWheel object, so that I get the precise coordinates. I called it GroundDetector, and I created 2 components: a script that I named GoundCollisionDetector (you name your stuff the way you want, I like when it’s clear so I write in full) and a Circle Collider 2D that has the exact same radius as my wheels colliders, because it is supposed to act like an invisible wheel. I checked Is Trigger, because it will be used as a… trigger, yes.

Step 2:
Because I find assigning colliders to every object supposed to act as the ground tedious, I created an empty object for the ground collider. That way, even if I have to delete a piece of my level, it won’t delete my actual “track” that I can easily edit. So you do as you wish, but it’s how I did, it looks more logical to me (for now). And to this object that I called Ground_Collision, I created and assigned a new tag I named Ground.

Step 3:
Time to get to the script! It’s a straightforward script, I created a boolean (a condition that is either true or false), and if the whatever that collides with the wheel has the Ground tag, the boolean GroundCollision is true.
What is in green is another way to interact: instead of using a tag, one can use the name of an object. The thing is if I do so, I’ll have to edit the script every time (I think?) I add something acting as the ground. With a tag, I simply need to assign the tag to any object.
The Debug.Log  is here to check that it is properly working or not (it shows the text in the inspector). So in the end, the clean code should be:

public class GroundCollisionDetector : MonoBehaviour{
public bool GroundCollision;
public void OnTriggerStay2D (Collider2D col){
if (col.gameObject.tag == “Ground”){
GroundCollision = true;}
else if (col.gameObject.tag != “Ground”){
GroundCollision = false;}}}

That’s it for the wheel’s script!

Step 4:
Now to call that script from the car’s script. It’s actually very simple.
I added:
public GroundCollisionDetector GroundColScript;
And I moved the rb.drag = dragForce; from the FixedUpdate to my new condition: it can only happen if up/down arrow keys aren’t pressed, which means if movement == 0f
So it became:
if (movement == 0f){
rearWheel.useMotor = false;
frontWheel.useMotor = false;
if (GroundColScript.GroundCollision){
rb.drag = dragForce;}}

if (GroundColScript.GroundCollision) is what calls the boolean (GroundCollision) from the other script!

Step 5:
Finally, and it’s a very important step or else it won’t work, select your vehicle, scroll down to your script component, find Ground Col Script (or whatever name you chose) and drag the wheel object in its space.

Play, et voilà!

Leave a Reply