- Home /
C# How do I get my turret to fire at player every few seconds while they are in range?
Basically I have a turret and a set range. Whenever the player enters that range I want my turret to fire at them once every few seconds an continue this as long as the player is in range. I have seen several examples how to do this, even in C#, but I have had little success so far. I tried using a Coroutine and IEnumerator, which worked as long as the player started out in range, but once they left range and came back it would do nothing. I tried InvokeRepeating, but it didn't seem to delay the shots no matter what I set the time between calls to. The strip of code below seems to be the cleanest and it will shoot at the player while they are in range, but I need to add some sort of time delay to it.
using UnityEngine;
using System.Collections;
public class S_skullTower : MonoBehaviour {
public Transform target;
public float turretSpeed;
public float fireRate;
public float fireBallHeight;
public GameObject fireBall;
public float range;
float distance;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
//Rotate turret to look at player.
Vector3 relativePos = target.position - transform.position;
Quaternion rotation = Quaternion.LookRotation(relativePos);
rotation.x=0;
rotation.z=0;
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * turretSpeed);
//Fire at player when in range.
distance = Vector3.Distance(transform.position,target.position);
if(distance < range)
{
launchFireBall();
}
}
void launchFireBall()
{
Vector3 position = new Vector3(transform.position.x, transform.position.y + fireBallHeight, transform.position.z);
Instantiate(fireBall, position, transform.rotation);
}
}
Any direction or suggestions would be much appreciated.
Answer by ArkaneX · Aug 23, 2013 at 08:28 PM
You can add a new variable:
private float _lastShotTime = float.MinValue;
and then use:
if (distance < range && Time.time > _lastShotTime + (3.0f / fireRate))
{
_lastShotTime = Time.time;
//print(Time.time);
launchFireBall();
}
This way, your tower shot speed will depend on fireRate. You can of course change 3.0f to any value.
Answer by wiiarethesound · Aug 23, 2013 at 08:19 PM
Personally, I like to use some kind of timer with a float and Time.deltaTime. Something like:
if (distance < range)
{
fireTimer += Time.deltaTime;
if (fireTimer >= fireRate)
{
fireTimer -= fireRate;
launchFireBall();
}
}
Also, just a couple notes for you: instead of using Vector3.Distance (which uses a sqrt function internally) you could do something like:
sqrDistance = (transform.position - target.position).sqrMagnitude;
And then instead of checking against range, check against range², i.e.
if (sqrDistance < range * range)
{
// Do something
}
Hope this helps!
EDIT: just a side note: as it stands, this code will shoot a fireball every X seconds that the player is within range. Once they are out of range that timer value will still be non-zero. You will want to set it back to zero when the player is out of range if you want the timer to be reset.
Not sure why, but this one still produced a constant stream of bullets regardless of fireRate. The other notes you had were very helpful in streamlining my code, though. :)
Your answer
Follow this Question
Related Questions
Distribute terrain in zones 3 Answers
Multiple Cars not working 1 Answer
Door opening sound, according to opening speed/direction? 1 Answer
How to work a real life timer? 2 Answers
String format to show float as time 3 Answers