How Do You Fire a Projectile / Bullet in Unity?
If you think about it, I’m sure almost every game you have played has had projectiles in it. They are an integral part of many games. Unity makes it fairly easy to fire a projectile. These are the basic steps to fire a projectile in Unity:
- Create a game object for the projectile and make it a prefab.
- Create a game object from where the projectile spawns and create a script for it.
- In that script, create a speed variable and call the Instantiate() function in the Update() function using the projectile prefab in the “original” parameter, and default values for the other two parameters.
- Create a projectile script and add a speed variable. Use “transform.Translate()” in the Update() function to move the projectile after it is instantiated.
Create Your Game Objects
This will be a simple example of how to fire a projectile in Unity. First, you need to create a game object. Right click in the Hierarchy tab, probably on the left, and select 3D Object > Cube. With the Cube selected, go to the inspector and select Add Component at the bottom, then search for Script and select New Script. Name it, if it asks for one.
The cube will be where the projectile is instantiated. Note that you don’t need this cube to make a projectile, but in this example it will be used as for where the projectile will come from. Think of it as the player.
Now create another game object. I will create a sphere. Right click in the Hierarchy tab again, select 3D Object > Sphere. Let’s shrink it. Make sure the sphere is selected and go to ‘Scale’ in the Transform component of the Inspector. Make each value, x, y, and z, .25. Scaling the game object isn’t necessary for a projectile, but it makes things easier to see in the scene.
Making Your Projectile a Prefab
To be able to instantiate the Projectile game object into the scene, you have to make it a prefab. Prefabs are basically game objects that are reusable. Their components and data are stored as an asset. You can call them into the scene as needed.
To create a prefab, add a game object to the Hierarchy Tab. Then drag it into the Assets folder of the Project Tab. You should also create a Prefab folder to hold your prefabs.
So drag your sphere projectile from the Hierarchy Tab into the Project Tab. Again, you can make a Prefabs folder in the Assets folder to store all the prefabs you have in your game. After creating the prefab, delete the sphere from the Hierarchy Tab so that it is no longer in the scene.
Prepare the Projectile Start Point
In this example, when the Spacebar is pressed by the user, the sphere projectile will spawn at the player and shoot upwards in the scene.
Open the script that is attached to the cube. First we will make a reference to the projectile prefab.
public class ProjectilePlayer: MonoBehavior
{
[SerializeField]
private GameObject projectilePrefab;
}
[SerializeField] – This is not necessarily needed for this example, however, most variables should be private to restrict unwanted access from other classes that may be programmed by mistake to access certain variables. [SerializeField] allows for a private variable to be accessed in the Inspector. You can then edit that variable in the Inspector instead of having to re-code a value into the script every time you have to change it.
In this case, drag the sphere projectile prefab from the Assets folder into the Projectile Prefab selector in the Script Component for the Cube. Make sure to save script files and the Unity editor as you make changes to them.
Back in the the cube’s script add the following in the Update() function:
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
Instantiate(projectilePrefab, transform.position, Quaternion.identity);
}
}
if(Input.GetKeyDown(KeyCode.Space)) – Input.GetKeyDown is a function used to check if a player presses a specific key on a keyboard or joystick. (KeyCode.Space) is the parameter of the GetKeyDown function. Space is the name of the Spacebar key on a keyboard. So GetKeyDown is checking if the Space or Spacebar key is pressed.
Instantiate(projectilePrefab, transform.position, Quaternion.identity); – This is the code that will make the projectile game object appear in the scene. Instantiate() makes a copies an object into a scene. ProjectilePrefab is the reference to the projectile game object we wrote in the beginning. Remember, in the editor we associated the Sphere to this reference, so the sphere will be instantiated into the scene.
The next parameter, transform.position references the current position of the game object is attached to. In this case, this is the cube. This parameter tells Unity where the projectile will be spawned in the scene. So it will be spawned at the cube’s position. Finally, Quaternion.identity is put in the parameter where the rotation of the instantiated object is entered. By typing in identity, there is no rotation applied to the game object.
Prepare the Projectile
Open the script that is attached to the sphere projectile and create the speed variable for the projectile.
public class ProjectileProjectile : MonoBehaviour
{
[SerializeField]
private float speed = 5.0f;
We already know about [SerializeField], so let’s discuss the variable. The word float is the variable’s data type and can be a whole number and fractions of a number. The word speed is the name of the variable. Finally, = 5.0f initializes the variable to the value of 5. Note you need the letter f after the number when initializing a float.
Finally, let’s make the projectile move in the Update() function.
void Update()
{
transform.Translate(Vector3.up * speed * Time.deltaTime);
}
transform.Translate is a function that translates, or moves, an object across space in the scene. The first parameter of the function, Vector3.up, moves the object positively along the Y axis. This vector is multiplied by the speed variable we created which is then multiplied by Time.deltaTime. Time.deltaTime is the “interval in seconds from the last frame to the current one” according to Unity’s documentation. It is needed for accurate movement over time.
At this point, you can now fire spheres up on the Y axis. This type of firing is ok for something like a retro 2D space shooter. But what if you need to fire a projectile in different directions in Unity?
Fire a Projectile in the Direction You’re Facing
If you want to control where the projectile moves, you can do that easily too!
To fire a projectile in a certain direction, use transform.rotation as the value in the rotation parameter of the Instantiate() function that creates the projectile in the scene.
So what this is saying is whatever direction that, for example, your player or gun is facing, that is where the projectile will move. You do have to make sure you get your directions right. It can be a little tricky in Unity. In the example we made, the projectile is moving up on the Y axis of the cube. It will still shoot from the face of the cube that is facing upwards on the Y axis. But we can rotate the the cube to shoot in different directions.
Go back into your cube script and change it to the following below. Everything new is bolded.
public class ProjectilePlayer : MonoBehaviour
{
[SerializeField]
private GameObject projectilePrefab;
// Start is called before the first frame update
[SerializeField]
private float speed = 10.0f;
void Start()
{
}
// Update is called once per frame
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
Instantiate(projectilePrefab, transform.position, transform.rotation);
}
if(Input.GetKey(KeyCode.LeftArrow))
{
transform.Rotate(Vector3.forward * speed * Time.deltaTime);
}
if(Input.GetKey(KeyCode.RightArrow))
{
transform.Rotate(-Vector3.forward * speed * Time.deltaTime);
}
}
}
private float speed = 10.0f; – This is the variable that will be used for how fast the cube rotates.
Instantiate(projectilePrefab, transform.position, transform.rotation); – Before, the third parameter in the Instantiate function was Quaternion.identity, which meant there was no rotation applied to the projectile when it was instantiated. However, this time we changed the rotation of the sphere projectile to equal the rotation of the cube.
To do that we got the transform component of the cube, and then accessed it’s exact rotation: transform.rotation. Calling transform in a script that is attached to a game object will access that specific game object’s transform. So to access the cube’s rotation, all we had to do is use transform.rotation.
if(Input.GetKey(KeyCode.LeftArrow))– Like the if statement from before, this is saying if the left arrow key on the keyboard is pressed down, whatever code that is in between the following braces is executed.
transform.Rotate(Vector3.forward * speed * Time.deltaTime); – This line of code is the Rotate function that rotates the object it is attached to. In this case, it is the cube. Vector3.forward means that the object will move counter-clockwise around the Z axis if the camera is facing toward positive Z. That movement is multiplied by our speed variable and then Time.deltaTime so that the speed is accurate. This allows us to rotate the cube and test if the projectile shoots in the proper direction.
if(Input.GetKey(KeyCode.RightArrow))– This is saying if the right arrow key on the keyboard is pressed down, whatever code that is in between the following braces is executed.
transform.Rotate(Vector3.forward * speed * Time.deltaTime); – This line of code is the Rotate function that rotates the object it is attached to. In this case, it is the cube. -Vector3.forward means that the object will move clockwise around the Z axis if the camera is facing toward positive Z. That movement is multiplied by our speed variable and then Time.deltaTime so that the speed is accurate.
There are other ways to move a projectile. You may also destroy a projectile if it collides with another object. These topics are covered in different articles. For now, experiment with these scripts. It is a vital part of the learning process that you play around and create your own scripts.