How do I delay a shot?

I have a game where I press the Spacebar to fire a bullet through the camera. I have set it up so that the player has the press the Spacebar each time they want to fire the gun, instead of just holding the Spacebar down.

However I want to put a delay on each shot fired, so the player doesn't just spam press the Spacebar.

I just don't know what I would need to do to get this working, any ideas?

4 Answers

4

Use a coroutine:

var shotDelay = .5;

function Start () {
    while (true) {
        while (!Input.GetButtonDown("Fire")) yield;
        // Fire bullet here
        yield WaitForSeconds(shotDelay);
    }
}

Create a cooldown timer and initialize it to zero. Each time they shoot, add some time to the cooldown timer. Each Update(), remove some time from it. Only allow the player to fire when their cooldown timer equals zero. This is a typical solution.

Wow, you already got three snippets! Matt's code is similar to what I described except: (a) he counts up instead of down which is okay, (b) you need to add code to reset the timer after firing, and (c) I would put an if around +Time.deltaTime to only increment it when it's not time to fire for strict correctness.

He likely took such measures in his real code. :)

One example of a reload timer could be like so:


var reloadTime : float = 4; 
var timer : float = 0;

function Update(){ 
    timer += Time.deltaTime(); 
    if (fire && timer > reloadTime){ 
        // do your firing 
    } 
}

Unity scripting will often suggest using the following

JS:

// Prints 0
print (Time.time);
// Waits 5 seconds
yield WaitForSeconds (5);
// Prints 5.0
print (Time.time);

C#

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour 
{
   public IEnumerator Awake() 
   {
      print(Time.time);
      yield return new WaitForSeconds(5);
      print(Time.time);
   }
}

U need to use a coroutine to be able to yield like that though.

Making your own timing mechanism is just as valid in any build. I did just that for my gun.

This is the one I found somewhere made by someone that helped in making a recoil sample which uses and demonstrates that the unity method works.

var bullet : GameObject;
var fireDelay : float = 0.1;
var exitPoint : Vector3;
var recoil : float = 100.0;
var sound : AudioClip;

private var canFire : boolean = true;

function Update () {
    if(Input.GetMouseButton(0))
    FireOneShot();
}

function FireOneShot() {
    if(!canFire)
    return;

    canFire = false;

    audio.PlayOneShot(sound);
    transform.parent.rigidbody.AddTorque(Random.insideUnitSphere * recoil);
    //allows time for the recoil to move the barrel,
    //otherwise the first shot would 
    //always be completely accurate
    yield WaitForSeconds(0.1);
    Destroy(Instantiate(bullet, transform.position + 
    transform.TransformDirection(exitPoint), transform.rotation), 10.0);

    yield WaitForSeconds(fireDelay);
    canFire = true;
}

And here is one of my own timing mechanisms. I have tested it and it works.

In the Update Method build something that resembles this, just make sure the second block comes after the register of the mouse button block.

    if (Input.GetMouseButton(0))
    {
        if (readyToFire)
        {
            Fire();
            readyToFire = false;
            useFireClock = true;
        }
    }

    //Starts the clock on reload/cooldown
    if (useFireClock)
    {
        useClock();
    }

My Clock method, the base values allow for resetting to the value it had on startup, just assign those on the start methods.

private void useClock()
{
    gunCoolDown -= Time.deltaTime;
    if (gunCoolDown <= 0)
    {
        //The gunCoolDown variable allows you to easily change the time 
        //of the call You can easily use a general clock and rename
        //it to some const INTERVAL
        gunCoolDown = GunCoolDownBaseValue;  //<-- Not type, forum color error
        readyToFire = true;
        useFireClock = false;
    }
}

The fire methods needs no clock mechanisms so it's still interchangeable, u can easily call other methods like this aswell.

I'm sure one of the solutions will work for you :)

To ADD the special effect you want to require a new keystroke. Simply use the GetKeyDown, it will not register is key is HELD down , that requires additional logic. Which I can help you with aswell if you want

Or anyone else for that matter!