Firing only a single projectile at a time, then adding a second.

I know there are a lot of projectile scripts and questions out there but I could not find one to answer what I am after.

I have a point in the centre of the screen that projectiles get fired out of.
This faces away from the camera.

At the moment, when I click and hold the mouse button, it puts the projectile prefab into the centre point.
When I release the mouse button, the projectile fires.
When the player presses and holds the mouse button again, the previous projectile is destroyed and a new one is put into the center of the screen.
This is partly the functionality I am after as I don’t want the player to keep firing as many projectiles as they want.
I would like to add the bonus that after x amount of head shots, the player is awarded another projectile to their pool, so they can have a maximum of 2 projectiles in the scene at once. This continues up to a maximum of 5.

Here is where I handle the firing:
I was thinking that the projectiles need to get pushed into an array and then it fires only those in the array but could not see how it would know which projectile to destroy or how many are in the scene.

    public static int numberOfProjectiles;
	public int shootForce = 90;
	public Transform target;
	public Vector3 firePosition;
	public GameObject projectilePrefab;
	public GameObject projectile;
	public float shootForce;
	public static bool canShoot = false;

	void Start () {
		numberOfProjectiles = 1;
		firePosition = target.transform.position;
	}

	void Update () 
	{
	    if (Input.GetMouseButton(0)) // aim while the mouse button is down
	    {
		Destroy(projectile);
		projectile = (GameObject)Instantiate (projectilePrefab, firePosition, firePosition.transform.rotation);
		projectile.rigidbody.AddForce(-projectile.transform.forward * shootForce);
			
		}
	}

Then, when the projectile hits a collider on an enemy (Separate Script on the enemy):

 void Update()
 {
      if(headShotCount==3)   //not sure how to keep a record of how many times this can be incremented
      {
           ProjectileScript.numberOfProjectiles +=1;
      }
 }

 void OnCollisionEnter(Collisions collision) 
{
	headShotCount +=1;
}

All help and advice appreciated!

Hi there

There’s a fairly classic solution to this ‘recycling’ problem. Typically it starts with:

  1. the ‘emitter’ (i.e. your gun) having a list of currently active projectiles its fired
  2. the ‘projectile’ knowing when it was fired, and who fired it

Projectiles typically ‘die’ for 1 of 3 reasons:

  • they hit something, and ‘choose’ to destroy themselves, and maybe trigger some game action like applicaton of damage
  • they reach a maximum life time (current time - fire time > x) and thus destroy themselves
  • the emitter wants to fire, and its list of currently active projectiles is longer than the maximum number of projectiles it supports, so it chooses to recycle one

So the basic procedure in your gun script should be:

       //check if fire button pressed
        if(pressed_fire)
        {
            //if we've hit the limit, destroy the oldest one (when a projectile dies it automatically removes itself from the list)
            if (list_of_active_projectiles.count > maximum_active_projectiles)
                kill_the_oldest_projectile();

            //create a new projectile
            new_projectile = Instantiate(my_projectile_prefab);
            //... do whatever setup you do here ...
            //tell the projectile who fired it, and add it to the active projectile list
            new_projectile.emitter = this;
            list_of_active_projectiles.Add(new_Projectile);
        }

When a projectile is destroyed, it’s script should automatically notify its emitter that it has been destroyed so that it is removed from the active projectile list.

So you’re basically maintaining a list of projectiles your gun is responsible for. By doing this the gun is able to recycle existing projectiles by scanning that list and killing the oldest one.

Hope that helps :slight_smile:

I can see how that works in principle but still a bit unsure as to where everything sits.
The above would sit on the existing ‘gun’ object and manage the projectiles.

I don’t get how the list (is it an IList in Unity?) takes care of the destroying of the objects (the kill_the_oldest_projectile(); method you have).
At the moment, the projectile is just a gameobject with a collider and rigidbody. On the enemy is the hit collision points which destroy the projectile (I did it this way because all the animations sit on the enemy and it is easier to call different animation on collisions this way).

Also, where is the emitter property to sit? I coulnd’t find any inbuilt unity ones.

Thanks again