Why is there a delay before the script functions?

Hi there,

In my project, the player can hold down the “Fire1” key to shoot bullets in autofire mode. For some reason, however, there is about a second delay from pressing the key to the bullet appearing. Could somebody please take a look at my code and help me understand why this is happening?

Script 1 - Gets the bullet from a pool:

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

public class playergunscript : MonoBehaviour
{
		public float fireRate = 4.0f;
		private float counter = 0.0f;

		void Start ()
		{
				this.enabled = false;
		}

		void Update ()
		{
				counter += Time.deltaTime;

				if (counter > 1 / fireRate) {
						GameObject obj = playerbulletpool.current.GetPooledObject ();
						obj.transform.position = transform.position;
						obj.transform.rotation = transform.rotation;
						obj.SetActive (true);
						counter = 0.0f;
				}
		}
}

Script 2 - Autofire when “Fire1” is held:

sing UnityEngine;
using System.Collections;

public class playercontrolscript : MonoBehaviour {

	private playergunscript playergunscript;

	void Start(){
				playergunscript = GetComponentInChildren<playergunscript> ();
		}

	void Update () {
				if (Input.GetButton ("Fire1")) {
						playergunscript.enabled = true;

				} else {
						playergunscript.enabled = false;
				}
		}
}
}

Thank you very much for your time!

void Update ()
{
counter += Time.deltaTime;

                if (counter > 1 / fireRate) {
                        GameObject obj = playerbulletpool.current.GetPooledObject ();
                        obj.transform.position = transform.position;
                        obj.transform.rotation = transform.rotation;
                        obj.SetActive (true);
                        counter = 0.0f;
                }
        }

The line if(counter > 1 / fireRate) { it looks like you want to wait .25 seconds (because your fireRate is 4.0). If this is so, you need to cast the 1 as a float, because right now it is an integer. So change the 1 in that line to 1.0f. Should fix the issue.

On a further note, if the purpose of counter is just to make a short delay, a coroutine with a yield statement would be a little more efficient.

Your problem is this line:

  counter += Time.deltaTime;

You re enabling and disabling the playergunscript. When the gun script is disabled, you don’t get Update() calls, so counter is not being incremented. Only when the “Fire” button is pressed will it increment. You have a number of choices. If it were me, I’d put a Fire() method in playergunscript and then have the script decide if it can fire or not. As an alternate, you could use a timestamp. Each time the gun fires you record the time. Then your check would be:

if (recordedTime + (1.0f / fireRate) <= Time.time) {

This does not require Update to increment a counter.

Hi all,

Thanks for your answers! I understand that the delay was caused by the Update() method not being called until the button was clicked. I took @robertbu’s advice and instead created an isFiring() bool which is called when the button is clicked instead and there is no longer a delay. I haven’t updated the counter to a coroutine yet since right now there’s no performance issues. I’ll consider it when I do some code cleanup, however.

Here are the updated, working scripts (including the ability to fire left and right). I hope this question can help somebody else:

playergunscript:

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

public class playergunscript : MonoBehaviour
{
		public float fireRate = 4.0f;
		private float counter = 0.0f;
		public bool isFiring = false;

		void Update ()
		{
				counter += Time.deltaTime;

				if (isFiring == true) {
						if (counter > 1.0f / fireRate) {
								GameObject obj = playerbulletpool.current.GetPooledObject ();
								obj.transform.position = transform.position;
								obj.transform.rotation = transform.rotation;
								obj.SetActive (true);
								counter = 0.0f;
						}
				}
		}
}

playercontrolscript:

using UnityEngine;
using System.Collections;

public class playercontrolscript : MonoBehaviour
{

		public Vector3 speed = new Vector2 (10, 10);
		private Vector2 movement;
		private playergunscript playergunscript;
		private playergunleft playergunleft;

		void Start ()
		{
				playergunscript = GetComponentInChildren<playergunscript> ();
				playergunleft = GetComponentInChildren<playergunleft> ();
		}

		void Update ()
		{
				// get axis information
				float inputX = Input.GetAxis ("Horizontal");
				float inputY = Input.GetAxis ("Vertical");
		
				// movement per direction
				movement = new Vector2 (
			speed.x * inputX,
			speed.x * inputY);

				if (Input.GetButton ("Fire1")) {
						playergunscript.isFiring = true;
						playergunleft.isFiring = false;
				} else {
						playergunscript.isFiring = false;
				}
				if (Input.GetButton ("Fire2")) {
						playergunleft.isFiring = true;
						playergunscript.isFiring = false;
				} else {
						playergunleft.isFiring = false;
				}
		}

		void FixedUpdate ()
		{
				rigidbody2D.velocity = movement;
		}

}

Thanks again for your suggestions!