- Home /
My tower defense script fires too often
Hello, I made a tower script for my tower defense game. Its working for the most part but the problem is that Im using OnTriggerStay to activate it, which creates the problem that it increases its fire rate by how many enemies are in the trigger, instead of fireing at the constant speed its suppose to.
I cant figure a way around that because I need to use OnTriggerStay so that it actually stops once the enemy dies/leaves and I cant figure out any other method for it to stop.
using UnityEngine; using System.Collections;
public class TowerScript : MonoBehaviour {
public float FireRate = 1.0f; //How fast the tower fires
private float FireRateStore; //Stores the FireRate so that it can reset itself later
public GameObject TowerAmmo; //The prefab bullet that the tower uses
public Transform TowerOpening; //Where the Tower's Ammo comes out(its barrel)
public bool Fire = false; //Checks to see if the tower can fire
bool FireTemp = false; //This is so that the Tower fires once in the begining
void Start()
{
FireRateStore = FireRate;
}
void FixedUpdate()
{
}
//****************
//This is the timer for the tower. Checks to see if the enemy is within range.
//Then checks to see if the timer is greater than 0, if it is, it wont fire. Once it hits 0, it can fire
//Will fire once, then restarts the timmer so that it can no longer fire.
//****************
void OnTriggerStay(Collider other)
{
if (other.tag == "Enemy")
{
if(FireRate> 0.0f)
{
Fire = false;
FireRate -= Time.deltaTime;
}
else
{
Fire = true;
}
if(Fire == true)
{
Instantiate (TowerAmmo, TowerOpening.position, TowerOpening.rotation);
FireRate = FireRateStore;
Fire=false;
}
}
}
//****************
//Since the main fire timer wont fire until after it reaches 0, it wont fire right away
//This trigger is so that it fires at lest once right away.
//****************
void OnTriggerEnter(Collider other2)
{
if (other2.tag == "Enemy")
{
FireTemp = true;
if(FireTemp == true)
{
Instantiate (TowerAmmo, TowerOpening.position, TowerOpening.rotation);
FireTemp = false;
}
}
}
}
Stay is one of these functions best left alone. It is intensive and does nothing that cant be handled by Enter/Exit.
Answer by Saint0120 · Jan 27, 2015 at 04:24 AM
Ok, I fixed the problem every one. Since I couldn't use OnTriggerExit I had to stick with OnTriggerStay and used a bool and went back to using LeoKingKong suggestion of keeping the timer part of the script within the update, with the bool as the means of checking if it should fire.
Some quick pseudo code of this fix is. I hate how simple the answer really was =/
void OnTriggerStay(Collider other) { if (other.tag == "Enemy") { Fire = true; } }
void FixedUpdate() { if(Fire==True) { Instantiate bullet Fire=False //If there are no enemies within the trigger, that means there is no way to activate the true statement } }
Glad you've got it sorted! I've edited my above code for the sake of it working for others co$$anonymous$$g on this thread as at a quick look other.gameObject = target was the wrong way round! Also you don't need OnTriggerEnter, its just an example of how it could be used. Good luck on your game!
I would say your solution is kind of heavy. If you'd found away to subtract one from the enemycount when a enemy died the code would be much more efficent in turns of CPU prossessing power needed. Also if you are finished with the question you should choose an answer as the right one so the question is marked as solved.
Answer by Glurth · Jan 25, 2015 at 02:40 PM
Without getting into the actual logic, why not use OnTriggerExit() to detect when the enemy leaves or dies?
OnTiggerEnter() {...enemycounter++;...}
OnTiggerExit() { .. enemycounter--;..}
EDIT: oops, I didn't men to convert this comment to an answer!
oh, didn't even know that was possible! I'm never sure when to leave a comment or an answer. The downvote I got, on an poor answer I gave, has me paranoid.
You get privileges with higher $$anonymous$$arma ;)
We all get downvotes :) Don't let them put you off. If its snowballing you can always hit $$anonymous$$ETE :D
Answer by spacedazza · Jan 25, 2015 at 07:45 PM
try makeing a new var and give it a time it should fire and ammo the time it takes for each cannon to fire
Answer by LeonardNS · Jan 25, 2015 at 09:41 PM
You need to move what you have in the OnTriggerStay to FixedUpdate and only use The OnTrigger functions to check if there is enemies there.
That fixes this problem, but now my tower always fires and never stops, even when I create a bool for the Update that turns true when the enemy enter the OnTriggerStay
Do you also turn OFF that bool on OnTriggerExit? Also, I would turn the bool on during OnTriggerEnter, rather than on TriggerStay.
I would say using an int var is the best, no bool.
void OnTriggerEnter (Collider : other)
{ if (other.tag = "Enemy") {
NumberOfEnemies += 1;
}
} and then the same on OnTriggerExit but with "NumberOfEnemies -= 1;" ins$$anonymous$$d.
or something like that. If NumberOfEnemies is greater than 0 then fire.
Thank you, I did not understand what Glurth had meant until you typed it like that, and thank you to Glurth. Unfortunately that did not fix it. When an enemy dies within the trigger, the OnTriggerExit does not register it, there for it does not activate NumberOfEnemies -=1, which means Im still face with the problem that my Tower never stops firing.
So it seems that if I put the main part of my code within OnTriggerStay or Update, theres no way that I immediately see of it checking to see if theres nothing inside. I tried variations of your advice but it all leads to the problem that theres no way of checking if theres nothing in the trigger without using OnTriggerStay because OnTriggerExit doesnt want constitutes anything that was Destroyed within the trigger as exiting
Answer by stevecus · Jan 26, 2015 at 07:31 PM
Something you could also do is define a target so it only registers 1 enemy at a time.
void OnTriggerEnter(collider other)
{
//if an object enters collider
if(other.gameObject.tag == "enemy")
{
//define the target
target = other.gameObject;
}
}
void OnTriggerStay(collider other)
{
//if it has a target
if(target != null)
{
//Input attack code etc
}
//if i dont have a target
if(target == null)
{
//set a new target
other.gameObject = target;
}
}
void OnColliderExit(Collider other)
{
//if target out of range
if(other.gameObject.tag == "enemy")
{
//remove him as the target
target = null;
}
}
Your answer
Follow this Question
Related Questions
Have "OnTriggerStay" detection but only call it once? 1 Answer
Tower Defense tpwers follow player untill i klick 1 Answer
Simple one-way teleport? 2 Answers
Change cursor on OnTrigger 0 Answers