2D Shooting

There are three main ways to shoot things in Unity.

  • For laser-types of things where you insta-hit, you can use ray-casting.

  • You can move sprites and check by distance.

  • You can move sprites, and use colliders. This is how we are going to demo things here.

Make a sprites in Aseprite

We need a target and a projectile.

  • Make a bullet, laser, heart, whatever projectile you want to shoot.

  • Make a target to hit.

  • Export, and import into Unity changing the normal three things. (pixels per unit, compression, filter)

../../_images/target_projectile.png

Detect mouse down events

Now, we will use the mouse button to shoot. First, we need to detect mouse-down events.

In our Update method on cour controller (not FixedUpdate, doesn’t seem to work well), we can detect a mouse-down event with Input.GetMouseButtonDown(0). The 0 is for our left mouse button. An implementation might look like:

// Has the mouse been pressed?
if (Input.GetMouseButtonDown(0))
{
    Debug.Log("Mouse down");
}

Code and confirm it works.

Create a bullet

Now we need something to shoot.

  • Create a bullet prefab.

  • Add a box collider so we can detect collisions. Set the collider to be a trigger, as we don’t want it bumping into things.

  • Add a rigidbody so we can move it via physics.

../../_images/bullet_prefab.png

Go to your character controller cand add a public variable for the prefab. Code would look like:

public GameObject bulletPrefab;

Then drag the prefab into the new blank spot in your character.

../../_images/game_object.png

Update code to fire the bullet:

// Mouse pressed?
if (Input.GetMouseButtonDown(0))
{
    // Make a bullet
    var bullet = Instantiate(bulletPrefab, body.position, Quaternion.identity);
    // Get the body of the bullet
    var bulletbody = bullet.GetComponent<Rigidbody2D>();
    // Move the bullet to the right
    bulletbody.velocity = new Vector2(4, 0);
}

It would be better code if you make the speed a public variable rather than hard-code it. And we’ll get to aiming in a bit.

Create targets

Now we need something to shoot. Create targets. Add a collider. Add a tag for “Destroyable”.

../../_images/destroyable.png

Add a bullet script to destroy

This bullet script will destroy itself after moving 8 units, or it will destroy an object tagged ‘destroyable’.

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

public class BulletScript : MonoBehaviour
{
    Vector3 _origin;
    public float maxDistance = 8.0f;

    // Start is called before the first frame update
    void Start()
    {
        // Get position we started at, so we can see how far the bullet traveled.
        _origin = transform.position;
    }


    public void OnTriggerEnter2D(Collider2D collision)
    {
        Debug.Log("Trigger");
        if (collision.tag == "Destroyable")
        {

            Debug.Log("Destroyable");
            // Destroy item we hit
            Destroy(collision.gameObject);
            // Cause bullet to destroy itself
            // Put this outside the if to get deleted when hitting non-destroyable objects
            Destroy(gameObject);
        }
    }

    // Update is called once per frame
    void Update()
    {
        // How far has the bullet gone?
        float distance = Vector2.Distance(_origin, transform.position);
        // If too far, then remove ourselves from the game.
        if (distance > maxDistance)
        {
            // Cause bullet to destroy itself
            Destroy(gameObject);
        }
    }
}

Calculate angles

Next, if we want to fire in a particular direction, we need to do some math. Here’s the code with comments.

 1 // Get the angle of a vector
 2 public float GetYRotFromVec(Vector2 v1)
 3 {
 4     float _r = Mathf.Atan2(v1.y, v1.x);
 5     float _d = (_r / Mathf.PI) * 180;
 6
 7     return _d;
 8 }
 9
10 void Update()
11 {
12     // Get our axis values
13     horizontal = Input.GetAxisRaw("Horizontal");
14     vertical = Input.GetAxisRaw("Vertical");
15
16     // Has the mouse been pressed?
17     if (Input.GetMouseButtonDown(0))
18     {
19         // -- Fire a bullet
20
21         // Create the bullet
22         var bullet = Instantiate(bulletPrefab, body.position, Quaternion.identity);
23         // Get a reference to the bullet's rigid body
24         var bulletbody = bullet.GetComponent<Rigidbody2D>();
25         // Where is the mouse on the screen?
26         var mousePosition = Input.mousePosition;
27         // Where is the mouse in the world?
28         Vector3 target3 = Camera.main.ScreenToWorldPoint(mousePosition);
29         // Set the z value of this vector 3
30         target3.z = 0;
31         // What is the normalized vector from the player to the mouse?
32         Vector2 direction = (target3 - transform.position).normalized;
33         // What is the angle in degrees?
34         float angle = GetYRotFromVec(direction);
35         // Rotate the bullet
36         bulletbody.rotation = angle;
37         // Give the bullet speed
38         bulletbody.velocity = direction * bulletSpeed;
39     }
40 }