Search code examples
c#unity-game-enginegame-physics

UNITY - Shoot Projectile on the direction of where the gun is facing


I Have a gun that spawn a projectile that bounces of colliders (a Ricochet). It is supposed to be shooting to the direction of where the gun is facing but what I am getting is the projectile always shoots 45 degrees upwards to the right I know this is because of my constant declared vector 2.

I tried using Vector2.up but it prevents the projectile to do the ricochet effect because it always wants to go upwards.

How should I implement those things? I just want the projectile to shoot to the direction where my gun is facing and bounces of on colliders. This is a 2D game btw. I have my codes attached below so you can see. Thanks!

Projectile Script:

private Rigidbody2D rb;
public static bool canMove = true;

void Start()
{
 rb = GetComponent<Rigidbody2D>();
 rb.velocity = new Vector2(10f, 10f);
}
void Update()
{
 //transform.Translate(Vector2.up * speed * Time.deltaTime);
 if (canMove)
 {
     rb.isKinematic = false;

 }
 else if (!canMove)
 {
     rb.isKinematic = true;
 }
} 

Gun Script:

float offset = -90f;

public GameObject projectile;
public Transform shotPoint;
public GameObject child;

void Start()
{

}

void Update()
{
    Vector3 diff = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
    float rotZ = Mathf.Atan2(diff.y, diff.x) * Mathf.Rad2Deg;
    transform.rotation = Quaternion.Euler(0f, 0f, rotZ + offset);

    if (Input.GetMouseButtonDown(0))
    {
        Instantiate(projectile, shotPoint.position, transform.rotation);
        Projectile.canMove = true;
    }
}

Solution

  • The Rigodbody.velocity is in World-Space coordinates.

    When you pass in

    rb.velocity = new Vector2(10f, 10f);
    

    it will go in world space 10 in X and 10 in Y direction.


    In order to pass it in as local coordinates in general you can not always rely on Tramsform.InverseTransformDirection as suggested here since the Transform component. In this specific case it might work but in general you set velocities in FixedUpdate and in that moment the Transform component might not be updated yet!


    But the Rigidbody2D component is so in general you can use Rigidbody2D.GetRelativeVector in order to convert a local vector relative to the Rigidbody into world coordinates:

    // Might also be Vector.up depending on your setup
    rb.velocity = rb.GetRelativeVector(Vector2.right * speed);
    

    Note: it would be better you make

    [SerializeField] private Rigidbody2D rb;
    

    and already reference it via the Inspector. Then you can get rid of the expensive GetComponent call.