Unity 2D – Arrow Physics

In this article(Unity 2D – Arrow Physics) I’m going to show you how to create a realistic movement for a 2D arrow in Unity. I’m already assuming that you know how to work with Unity so I will skip the obvious steps.


I will start but telling you how to setup your arrow like a game component. After that I will show you how your C# script should look like.

Step 1Rigidbody 2D

Make sure that you have a Rigidbody 2D component on your unity game object. Your Rigidbody should look like this:

Unity 2D - Arrow Physics -   Rigidbody 2D
Unity 2D – Arrow Physics – Rigidbody 2D

By using a dynamic body type we are able to physically simulate the behavior of the game object . Also, by having a gravity scale equal to 1, we will simulate the object movement in an environment with a gravity acceleration of 9.80665 m/s2.

You can find more about how Rigidbody 2D works in the Unity manual: RB2D

Step 2 – C# Script

In order to obtain the behavior that we wanted we also need to attach a script to our game object.

using UnityEngine;

public class Arrow : MonoBehaviour
{
    [SerializeField]
    private Vector3 m_target;

    private Rigidbody2D m_rb;
    private float m_TimeInTheAir = 1.5f;

    void Start()
    {
        m_rb = GetComponent<Rigidbody2D>();
        m_rb.velocity = CalculateVelocity(m_target, m_TimeInTheAir);
    }

    void Update()
    {
        UpdateAngle();
    }

    Vector2 CalculateVelocity(Vector3 target, float time)
    {
        Vector3 distance = target - this.transform.position;

        float distanceX = distance.x;
        float distanceY = distance.y;

        float Vx = distanceX / time;
        float Vy = distanceY / time + (0.5f * Mathf.Abs(Physics.gravity.y) * time);

        return new Vector2(Vx, Vy);
    }

    void UpdateAngle()
    {
        float angle = Mathf.Atan2(m_rb.velocity.y, m_rb.velocity.x) * Mathf.Rad2Deg;
        transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
    }
}

Actually we are only applying simple physics:
1. Velocity equation:
velocity = distance / time
2. Velocity after a certain time of acceleration:
velocity = initial velocity + acceleration * time

We only need to calculate velocity once, so we are going to do this inside the Start method. The CalculateVelocity method is, as I said, respecting the velocity equations and returning a Vector2 with the X and Y velocity which will be used by the Rigidbody component.

In the Update method we are only going to call the UpdateAngle method in order to make sure that the game object will always rotate to follow the velocity evolution,

atan2(y,x) returns the angle θ between the ray to the point (x,y) and the positive x-axis, confined to (-π, π]. (Source: Wikipedia)

Author: Horațiu Condrea

My name is Horațiu Condrea, and I work as a Software Developer Manager at Siemens PLM Software. I hope that my experiments will prove to be useful for many of you guys/girls out there. Don’t forget to leave a comment whenever you run over a bug or something that is not working as it should be. For any kind of information contact me.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.