Pugito Pitapayle
Pugito Pitapayle

Reputation: 13

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;
    }
}

Upvotes: 1

Views: 8716

Answers (2)

CosmicGiant
CosmicGiant

Reputation: 6439

Because you are telling it to do so.

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

10 to the right, and 10 upwards.


Unless your projectile has a constant force applied to it, like a missile, get rid of everything related to forces or velocity in the projectile script. It will do you no good.

Then, on the gun script:

//...
if (Input.GetMouseButtonDown(0)) {
    var projectileInstance = Instantiate(projectile, shotPoint.position, transform.rotation);
    var rigidbody = projectileInstance.GetComponent<Rigidbody2D>();
    rigidbody.velocity = transform.TransformDirection(yourDirectionVector);
    Projectile.canMove = true;
}

Where Transform.TransformDirection is what makes yourDirectionVector, which is a direction relative to the gun, be transformed into one relative to world-space.

Upvotes: 1

derHugo
derHugo

Reputation: 90813

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.

Upvotes: 2

Related Questions