I wrote the code below in order to try to get a bullet to fire at a specific angle for my top-down shooter. However when I press space the bullet just spawns in front of the game object despite it having a bullet speed. I made sure that my bullet prefab has a rigidbody and I am calling to it in my script.

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

public class FireAway : MonoBehaviour
{
private Vector3 mouse_pos;
private Vector3 object_pos;
private float angle;
private float bulletSpeed = 1;
public GameObject ammo;
private Rigidbody2D rb2D;

void Start()
{
    rb2D = ammo.GetComponent<Rigidbody2D>();
}

// Update is called once per frame
void FixedUpdate()
{
    // Point the cannon at the mouse.
    mouse_pos = Input.mousePosition;
    mouse_pos.z = 0.0f;
    object_pos = Camera.main.WorldToScreenPoint(transform.position);
    mouse_pos.x = mouse_pos.x - object_pos.x;
    mouse_pos.y = mouse_pos.y - object_pos.y;
    angle = Mathf.Atan2(mouse_pos.y, mouse_pos.x) * Mathf.Rad2Deg - 90;
    Vector3 rotationVector = new Vector3(0, 0, angle);
    transform.rotation = Quaternion.Euler(rotationVector);

    if (Input.GetKeyDown("space"))
    {

        GameObject BulletPlayer = (GameObject)Instantiate(ammo, 
transform.position, transform.rotation);
        //bullet.transform.LookAt(mouse_pos);
       rb2D.AddForce(BulletPlayer.transform.forward * bulletSpeed);
    }
}
}
up vote 1 down vote accepted

Your problem is that you're spawning an instance of the ammo prefab, and then applying force to the prefab instead of to the instance you just spawned.

To avoid this, just have one variable for the prefab instead of two:

 public Rigidbody2D bulletPrefab;

Then instantiate it, and capture a reference to the instance's rigidbody:

 Rigidbody2D bulletInstance = Instantiate(bulletPrefab, position, orientation);

 bulletInstance.velocity = bulletInstance.transform.forward * bulletSpeed;

I don't recommend using force for this if you just want to set a specific launch velocity. Force can be affected by mass and timestep, so it's simpler for a case like this to just set the velocity directly.

I don't use unity myself, so I can only give you general information here:

rb2D.AddForce(BulletPlayer.transform.forward * bulletSpeed);

In order to accelerate any object to from velocity (v0), to velocity (v1), you must apply a force of newtons(N), in a direction , over a time interval (t).

At the moment, all you are doing is applying a direction (unit vector, has length of 1), then multiplying by 1, which has no effect on the vector.

The magnitude of that impulse will then be reduced by the bullet's mass, further reducing the visible effect of the impulse.

In short, the bullet has velocity, but it's so slow you can't see it move.

a = (F * t)/M where M is mass of the bullet, a is the change in velocity (v1-v0)

Basically, F must increase for your bullet to fly.

  • This answer would be correct if rb2D referred to the instance of the bullet we just spawned, but it doesn't — it's still pointing at the prefab, and we never apply a force to the newly-spawned instance at all. – DMGregory Dec 3 at 13:45
  • @DMGregory Fair enough. I'll leave the answer up as it's informative in it's own way. – Ian Young Dec 3 at 16:07

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.