- Home /
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!
Answer by robertbu · Oct 08, 2014 at 01:36 AM
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.
shouldn't be the condition somehow the other way round? Time.time is increasing and if it's greater than your timeout you will fire again.
Answer by BadAssGames · Oct 08, 2014 at 12:33 AM
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.
Actually the value is 0.25f because a integer divided by a float yields a float, not an integer. Only when two integers are involved the result will be an integer as well. So:
float i = 1 / 4; // will be 0 as both are integers
float f = 1 / 4f; // will be 0.25f
Answer by PlayKiseki · Oct 09, 2014 at 07:33 AM
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!
Your answer
Follow this Question
Related Questions
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
[HELP] Rotate Bullet Script 0 Answers
Enable/Disable shader on script 2 Answers
Enter Trigger and Rigidbody Enable 1 Answer
Add Weapon 0 Answers