GAME DEVELOPMENT WITH UNITY

Unity: Using RigidBody AddForce() method to move Game Object

There are mainly two ways of moving a gameObject in Unity:

  • Changing Position Coordintes: By directly changing the position of a gameObject without much consideration to its physics or other such components. This is what we've been doing so far, by simply adding a value to the object's X position every frame.
  • Rigidbody Physics: When dealing with objects that follows physics rules, it makes more sense to apply forces on objects or change their velocity instead of a direct position update. Looks more real.

In this tutorial we will cover an interesting example of using Rigidbody Physics for movement instead of Position change trick. We've worked with shooting bullets so far, right? But our bullets have only travelled using the position change regardless of what they are and how they move in real world.

Which also leads to issues like the one in which our bullet kept going even after it hit the target(Checkout our previous tutorials for the example).

It simply didn't know that it was supposed to stop, after hitting the target, since we programmed it to keep going to the right.

Instead of doing that, what if we applied a very strong impulsive force to the bullet, much like the one in real life? Doing so will make the bullet move because of its momentum, and not because of a programmed position update.

Let's explore this option, and, we'll understand the AddForce() method provided by the class Rigidbody. Open up the script that defines our bullet/fireball's behaviour:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FireballBehaviour : MonoBehaviour
{
    private float fireballXValue;
    public float fireballSpeed;
    
    void Start()
    {
        // getting the initial position where prefab is created
        fireballXValue = gameObject.transform.position.x;
    }
    
    // Update is called once per frame
    void Update() 
    {
        // adding speed value to the X axis position
        // value
        fireballXValue += fireballSpeed;
        // setting new X value to position
        gameObject.transform.position = new Vector2(fireballXValue, gameObject.transform.position.y);
        }
    }

}

Since pretty much everything we've written in this script deals with movement by position change, let's clear everything up so we have a clean Start() and Update() methods again.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FireballBehaviour : MonoBehaviour
{
    private float fireballXValue;
    public float fireballSpeed;
    
    void Start()
    {
        
    }
    
    // Update is called once per frame
    void Update() 
    {
        
    }

}

Controlling GameObjects using components

Now we know that we can access a gameObject in the script attached to it by using the reference gameObject.

Also, we can access and Component(like RigidBody, Collider etc) attached to the gameObject using the GetComponent function.

While earlier, we used to update any component's property using the Inspector view. Here, we will try to do that from within the script.

First off, we still have to declare the Rigidbody2D variable, but instead of making it public, let's make it private instead.

private RigidBody2D fireballBody;

Now, in the Start() method, we'll add the following line:

void Start()
{
    fireballBody = GetComponent();
}

So what does this line do? This line of code is, in a way, an automatic way of detecting and setting the variable. By calling the GetComponent method, we are simply telling Unity to go ahead and detect the type of component, specified in the angle brackets <> for our gameObject. In our case, we want the script to detect a Rigidbody2D component, so we'll put that within the angle brackets. This method doesn't have any overloads(variant).


Adding Velocity and Force to a RigidBody component

So now that we have control on our fireball's Rigidbody, what do we do with it? Well, we can either add a velocity to it, or add a force to it. Note that, both of these components are a part of the physics behind the gameObject, and not a direct change to the transform (and hence, its position) itself.

What's the difference? If you add a velocity to your body, you're ignoring any mass that the body has. It simply sets it going without considering how heavy the body is. If you add a force however, you're taking the mass of the body into account.

That means adding even a small velocity to something heavy like a big car will make it move, but adding a small force on the same car will only budge it slightly. As far as we're concerned, we'll add a velocity to the fireball, since we can consider it to have pretty low weight in itself.


Adding velocity property

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FireballBehaviour : MonoBehaviour
{
    private RigidBody2D fireballBody;
    public float speed;
    
    void Start()
    {
        fireballBody = GetComponent();
        
        // velocity is a property of RigidBody2D
        fireballBody.velocity = new Vector2(speed, 0);
    }
    
    // Update is called once per frame
    void Update() 
    {
        
    }

}

Wait a second! You added the fireballBody.velocity code into the Start() method, not the Update() method. To understand this, let's take an example. Imagine your mom asks you to change the lightbulb in the kitchen. You say, "sure, I'll do it", and you do it later on (Or don't, as is the case with most of us). Now imagine your mom asking you to change the lightbulb, 60 times per second for the rest of your life whether you change the lightbulb or not. A bit terrifying, isn't it? We are doing quite the same thing here, in Unity. If we set the velocity in the Start() method, we are simply telling the game to change the velocity once and then move on.

But If we write that same code in the Update() method, we'd simply be asking Unity to set the Rigidbody's speed to our defined values again and again. Since our values don't change for the time being, we're un-necessarily telling the script to assign the value to something it's already done.


Adding force using AddForce()

Now, let's explore the way of adding a force to the gameObject.

The Right Way to Move


The first parameter for the method AddForce() asks for simply a Vector2 to know in which direction you want to apply the force in. For example, a force using new Vector2(4, 5) will apply a force of 4 units horizontally right and 5 units vertically upwards.

The second parameter is a bit more interesting. You'll see that the additonal second parameter is an enum named ForceMode2D. ForceMode2D is a pair of modes for applying a force onto a gameObject. These modes are named Force and Impulse. Based on what kind of force you want to apply, you either input ForceMode2D.Force (for applying a constant, consistent force) or ForceMode2D.Impulse(for applying an instantaneous, striking force.)

For our scenario, we want to apply a sudden, massive force on our fireball so it shoots forward. Applying a constant force would make it accelerate up from a slow speed, which would seem kind of odd.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FireballBehaviour : MonoBehaviour
{
    private RigidBody2D fireballBody;
    public float speed;
    
    void Start()
    {
        fireballBody = GetComponent();
        
        // AddForce is a function of RigidBody2D
        fireballBody.AddForce(new Vector2(speed, 0), ForceMode2D.Impulse);
    }
    
    // Update is called once per frame
    void Update() 
    {
        
    }

}

If you try out both these methods in Unity, your fireballs should move the same way still, but this time, without ever modifying its position directly and using physics instead. We let Unity handle that for us.