0
\$\begingroup\$

I am working on a 2D top-down view game. I am trying to get my player to fire a bullet, when spacebar is pressed. I added a component to my player (a bullet sprite) and placed it under his gun (so you can't see it). I added a debug message "Shoot" to make sure that whenever I hit spacebar it gets registered - however, the bullet never shoots. I get the message

UnassignedReferenceException: The variable bulletPrefab of ShootBullet has not been assigned

Here is my script:

public class ShootBullet : MonoBehaviour {
    public Rigidbody bulletPrefab;
    float attackSpeed = 2f;
    float cooldown;

    void Update () {
        if(Time.time >= cooldown) {
            if(Input.GetKeyDown (KeyCode.Space)) {
                Fire();
                Debug.Log ("Shoot");
            }
        }
    }

    // Fire a bullet
    void Fire() {
        Rigidbody bPrefab = Instantiate(bulletPrefab, transform.position, Quaternion.identity) as Rigidbody;
        bPrefab.AddForce (Vector3.up * 100f);
        cooldown = Time.time + attackSpeed;
    }
}

Any ideas?

\$\endgroup\$
5
  • 3
    \$\begingroup\$ You must assign an existing prefab (your bullet) in the editor so your script (attached to the player) can find it. Your bullet should not be a sprite component attached to the player but a game object of its own. Also note that the bullet does not have to be in the scene, only the prefab is needed. \$\endgroup\$
    – Whiskas
    May 17, 2015 at 15:57
  • \$\begingroup\$ Thanks. I have done this, I also moved the contents of the script into the main Player script. In the if-statement that checks for whether or not the spacebar gets pressed I initialise a gameObject go and then use go.transform.TransformDirection(new Vector3(0, 0, 10f));. I get no errors but the bullet still doesn't fire. \$\endgroup\$ May 17, 2015 at 17:39
  • \$\begingroup\$ maybe you instantiate bullet "inside" the player (shooter). Instantiate it at some Vector3 delta : Rigidbody bPrefab = Instantiate(bulletPrefab, transform.position +DELTA,... \$\endgroup\$ Jun 17, 2015 at 9:08
  • \$\begingroup\$ Haven't unity right here right now but I would not use Rigidbody to declare an object to instantiate. Try declaring it as a GameObject and obviously, if you didn't, assign your prefab to it in the inspector \$\endgroup\$
    – Leggy7
    Jul 17, 2015 at 9:46
  • \$\begingroup\$ Try replacing all the 'Rigidbody' words to 'GameObject' in all three places and add GetComponent<Rigidbody>() before AddForce and after the prefab name. \$\endgroup\$
    – John Smith
    Aug 24, 2015 at 8:15

2 Answers 2

1
\$\begingroup\$

Assuming you've correctly assigned a valid prefab GameObject to your 'bulletPrefab' variable, it looks like it should work.

You say the "bullet still doesn't fire". Have you ensured that the AddForce method is being called i.e. add some debugging to that Fire() method to ensure it's being hit.

The only other thing I can think of is that you need to be using and referencing a RigidBody2D component instead of RigidBody. It all depends on what target settings you chose for your project i.e. 2D or 3D.

\$\endgroup\$
-1
\$\begingroup\$
public class ShootBullet : MonoBehaviour {
    public GameObject bulletPrefab;
    float attackSpeed = 2f;
    float cooldown;

    void Update () {
        if(Time.time >= cooldown) {
            if(Input.GetKeyDown (KeyCode.Space)) {
                Fire();
                Debug.Log ("Shoot");
            }
        }
    }

    // Fire a bullet
    void Fire() {
        GameObject bPrefab = Instantiate(bulletPrefab, transform.position, Quaternion.identity) as GameObject;
        bPrefab.AddForce (Vector3.up * 100f);
        cooldown = Time.time + attackSpeed;
    }
}

The problem you're having here is that you're declaring bulletPrefab as a Rigidbody, Rigidbody is a Component, not an object, you do not instantiate Rigidbodies alone. You instantiate a whole gameObject, with Components such as, transform, SpriteRenderers, Rigidbody, Collider, etc..

Go to your Assets, create a new Prefab. Now create a new gameObject in your scene, and modify the bullet you want to instantiate. After you're all set, drag the gameObject you just created onto the empty prefab, so it knows what it is. And afterwards, drag the Prefab you just created, onto the Public GameObject of your script, so the script will now instantiate a new bullet Object everytime you press space.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Actually, it's perfectly valid to create a public variable of some component type X, and use X myXInstance = Instantiate(prefab) as X; - this limits the inspector to only accept gameobject references that have the component type you need, making it harder to accidentally assign an incompatible object. And the Instantiate function will still create the whole GameObject instance with the component attached, not just a free-floating component. The asker's problem appears to simply be an unassigned variable in the inspector. \$\endgroup\$
    – DMGregory
    May 17, 2015 at 16:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .