Search code examples
c#unity-game-enginegame-physicsrigid-bodies

Using RigidBody2D in Unity


My buddy and I recently teamed up to create a top-view space shooting game, like asteroids. We’ve watched a lot of tutorials, and we’ve managed to work with translate.Transform() and get our object to move.

Now we want to apply force to our ship using RigidBody2D:

Here is a screenshot of our Unity window:

Screenshot of Unity window

As seen in the screenshot above, we made a Player Ship prefab with a spaceship sprite, a circle collider, a rigidbody 2D and a PlayerThrust script.

In Thrust.cs:

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

public class Thrust : MonoBehaviour
{
    // Thrust script components
    public  Rigidbody2D rigidBody;     // GameObject's Rigidbody2D component
    public  float       thrustAmount;  // amount of thrust applied to be defined in unity
    private float       thrustInput;   // float variable to keep track of user input of the 'up' arrow key/'up' axis tilt on joystick

    // Start is called before the first frame update
    void Start() {}

    // Update is called once per frame
    void Update() 
    {
        // handle input
        thrustInput = Input.GetAxis("Vertical");  // float ranging from -1.0 to +1.0

        // Debug
        Debug.Log(Vector2.up * thrustInput * thrustAmount);
    }

    // Fixed Update is called every fixed framerate frame
    // use for physics
    void FixedUpdate() {
        // only accelerate forward
        if (thrustInput > 0) 
        {
            // Apply thrust in direction ship is facing
            rigidBody.AddRelativeForce(transform.up * thrustInput * thrustAmount);
        }
    }
}

Why doesn’t the ship move?

Debug.Log(Vector2.up * thrustInput * thrustAmount); outputs a number which makes sense, it goes up to the thrust amount when the button is pressed, and goes back to 0.0 when the button is released.


Solution

  • Here's a test to see what is going on. 2 scripts. One will spawn a ship (A cube), and the other will use thrusters. Hold down the up key a bit to engage the thrusters, as the cube falls quickly.

    This should work on at least Unity 5.6 up to 2020.

    #1 -

    Create a new blank scene. Make sure you're in 2D view. Don't change anything. Add this script to the camera (All it does is spawn an object):

    using System.Collections;
    using UnityEngine;
    
    public class SpawnShipTest : MonoBehaviour
    {
        private void Start()
        {
            //Create a new scene, put this script on your camera.
            StartCoroutine(SpawnTestObject());
        }
    
        IEnumerator SpawnTestObject()
        {
            //Spawn object
            var go = GameObject.CreatePrimitive(PrimitiveType.Cube);
            var col = go.GetComponent<BoxCollider>();
            Component.Destroy(col);
    
            yield return new WaitForSeconds(.2f);
    
            go.transform.position = new Vector3(0f, 0f, -2f);
            go.AddComponent<ShipThrustTest>();
    
            go.AddComponent<Rigidbody2D>();
    
        }
    }
    

    #2 -

    Add this script in your projects folder somewhere (then press play, and view the Game Window):

    using UnityEngine;
    
    public class ShipThrustTest: MonoBehaviour
    {
        // Thrust script components
        public Rigidbody2D rigidBody;      
        public float thrustAmount;   // amount of thrust applied to be defined in unity
        private float thrustInput;    // float variable to keep track of user input of the 'up' arrow key/'up' axis tilt on joystick
    
        void Start()
        {
            rigidBody = GetComponent<Rigidbody2D>();
            thrustAmount = 10f;
        }
    
        void Update()
        {
            thrustInput = Input.GetAxis("Vertical"); 
        }
    
        void FixedUpdate()
        {
            if (thrustInput > 0)
            {
                rigidBody.AddRelativeForce(transform.up * thrustInput * thrustAmount * 2f,  ForceMode2D.Force);
            }
        }
    }