- Home /
Laser fire time limit
I have a gun that fires a laser but i want to make it so that the laser only remains active for a few seconds and then has to cooldown before it can be used again i have the following code for the laser and the cooldown seems to be working but the problem is that the player can keep the mouse button held down and just perpetually keep on fireing.
public class LaserScript : MonoBehaviour {
LineRenderer line;
Light light;
ParticleSystem particle;
float cooldown;
public GameObject explosion;
void Start () {
line = gameObject.GetComponent<LineRenderer> ();
light = gameObject.GetComponent<Light>();
light.enabled = false;
line.enabled = false;
cooldown = Time.time;
}
void Update () {
if (Input.GetButtonDown ("Fire1")) {
StopCoroutine("fireLaser");
StartCoroutine("fireLaser");
}
}
IEnumerator fireLaser(){
light.enabled = true;
line.enabled = true;
while (Input.GetButton("Fire1") && Time.time >= cooldown) {
Ray ray = new Ray(transform.position, transform.forward);
RaycastHit hit;
line.SetPosition(0, ray.origin);
if(Physics.Raycast(ray, out hit, 100)){
line.SetPosition(1, hit.point);
if(hit.rigidbody){
hit.rigidbody.AddForceAtPosition(transform.forward * 5, hit.point);
Instantiate (explosion, hit.transform.position, transform.rotation);
hit.transform.gameObject.SetActive(false);
}
}
else{
line.SetPosition(1, ray.GetPoint(100));
}
yield return null;
}
line.enabled = false;
light.enabled = false;
cooldown = Time.time + 1;
}
}
any help you guys can provide id be really gratefull for. thanks in advance.
Stopping and starting the laser fire every frame when the mouse button is down is really not efficient, and actually it doesn't work for your requirement. You need to only start the coroutine under the following 2 conditions:
1) The mouse button was not pressed previously
2) The laser is not cooling down
You can stop the coroutine on mouse up or when the cooldingDown flag is turned on. All the coroutine does is show the laser each frame, so you start the coroutine when it is time to show the laser and stop it when it's time to stop showing the laser. The coroutine will increment a heatBuildup value every frame indicating the laser is building up heat.
In Update(), you check heatBuildup for being > some threshold and set the coolingDown flag once reached. Also, you decrement heatbuildup (you may only decrement it when the laser is off if you choose). Lastly, you test heatBuildup for being < some threshold that will shut the coolingDown flag off.
But doesn't get button down only become true for the one frame that it is pressed, regardless of whether it is held down or not?
Yes, sorry, I read GetButton from your coroutine, brain melted. You are correct. The rest of the answer still should apply, but I'm going to delete it if I can since I think Bored$$anonymous$$ormon has the better solution.
@supernat Your solution was still valid. Ultimately there are two approaches to this problem.
@supernat's solution. Only call the laser script if the conditions are true. Check these conditions in update. This is actually the approach I would use. I would also change laser so it is not a coroutine. Then again my personal preference is not to use coroutines at all.
$$anonymous$$y solution. Add extra conditions to the coroutine. This will require the $$anonymous$$imum amount of effort to get to from the OP.
Reading this again you could make this faster by caching the result of the raycast. Only worth the effort if you have a lot of these lasers going off everywhere.
Answer by Kiwasi · Jun 15, 2014 at 10:53 PM
In essence there is nothing in your while loop that will trigger the laser to stop firing.
You need a second timer. Try the following at line 27-28. You will also need to throw in a declaration for float FireTimer
. Adjust the actual time to suit your needs:
FireTimer = Time.time + 0.5f;
while (Input.GetButton("Fire1") && Time.time >= cooldown && Time.time <= FireTimer)
On a separate note StopCoroutine is not buying you anything, the coroutine will stop itself if the key is released.
thanks i just added the stopCoroutine in case anything went wrong and it didn't stop properly. ill try your solution and hopefully it works.
Edit: works perfectly thank you so much for your help.
Your answer
Follow this Question
Related Questions
How to add a cooldown sort of thing. 1 Answer
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
For loop resetting itself, but needs to stop 2 Answers
Timescale not affect timer? (C#) 2 Answers