- Home /
How do I queue up targets in a TD?
Hi all,
Here's a problem that's been bugging me for a few days now; I couldn't figure it out on my own, so I thought I'd ask here. I've just started making a Tower Defense game, and have quickly set up a couple temporary scripts, one attached to a cube that automatically moves in a straight line past my tower, and one on my tower. A child of the tower is a cylinder collider made into a trigger.
At first I tried making the trigger itself note when the cube entered its range, but since I couldn't figure that out, I made the cube send a message to the tower when the cube hit the trigger, and from there made the tower look at the cube until it left the trigger area. That worked fine, until I added in multiple cubes. The way I had set it up meant it screwed up when there were multiple cubes in the trigger area, but I can't for the life of me figure out how to make it so that:
- The first cube is targeted by the tower,
- When that cube leaves the trigger area or is destroyed, the tower targets the next one, and
- Continues to cycle through all of the possible targets when the current one is destroyed or goes out of range
Here's the scripts I already have, if it helps in any way. This one's on the turret:
var targetedEnemy : GameObject; var inRange : boolean = false;
function Update() { if (targetedEnemy && inRange == true) { transform.LookAt(targetedEnemy.transform); } }
function EnteringRange(recievedGameObject : GameObject) { targetedEnemy = recievedGameObject; inRange = true; }
function LeavingRange() { inRange = false; }
And this one's on the cube:
var thisObject : GameObject; var otherObject : GameObject;
function Start() { thisObject = gameObject; }
function Update () { transform.Translate(0.025, 0, 0); }
function OnTriggerEnter (hit : Collider) { otherObject = hit.gameObject; otherObject.SendMessageUpwards("EnteringRange", thisObject); }
function OnTriggerExit (hit : Collider) { otherObject.SendMessageUpwards("LeavingRange"); }
Thanks for your help!
Update:
I tried changing the inRange variable to an int, and every time an enemy came in range it'd add 1 to the variable, and every time one left it'd subtract 1, which made it not screw up, however the turret would then target the newest enemy to enter the range, whereas I wanted it to select the first one to enter, i.e the one closest to leaving.
Answer by Bunny83 · Mar 23, 2011 at 02:06 AM
You talk about the common targetting modes in TD games. There are a lot TDs where you can choose the mode. I'll choose the Onslaught TD game as reference.
It have modes like:
- Newest
- Oldest
- Nearest
- Furthest
- Strongest
- Weakest
Beside those criteria that choose what you want to target it's important whether the tower should Lock on target or not. I guess lock on target is what you want.
Every of those modes I've listed above needs to check all enemies that are in range to decide what's the desired target. If you use "lock on target", you don't need to look for another one until the current leaves the range or dies.
Unity's triggersystem is really great, but only for triggering events. For selecting I would recommend to use a function inside Physics. For such range detecting tasks Physics.OverlapSphere comes in handy. It returns all colliders (also those marked "asTrigger") that are inside a certain radius.
Your tower only have some states that you should seperate:
- No target: keep on searching for targets
- Have a target
- Lock on target: keep that target and check if we loose it
- Without lock: Just like no target
Here's a small example of the idea i was talking about:
edit: This will pick the strongest target.
var currentTarget : Transform; var range : float = 5.0;
function SearchTarget() { var newTarget : Enemy = null; var collidersInRange = Physics.OverlapSphere(transform.position,range); for (var currentCollider : Collider in collidersInRange) { var currentEnemy : Enemy = currentCollider.GetComponent.<Enemy>(); if (newTarget == null) { newTarget = currentEnemy; } else if (newTarget.health < currentEnemy.health) { newTarget = currentEnemy; } } if (newTarget != null) currentTarget = newTarget.transform; }
function Update () { if (currentTarget == null) { SearchTarget(); } else { var targetDistance = (currentTarget.position - transform.position).magnitude; if (targetDistance > range) { currentTarget = null; } else { ShootAtTarget(); // or maybe AimAtTarget(); } } }
As long as the tower have a target there's nothing else in "the towers mind". Only if the current target gets destroyed (that would cause the variable to go null) or when it leaves the range it would look for a new target.
Wow thanks, that's exactly what I needed! The code you've written is really helpful. Only thing for me now is to figure out how to each of the furthest/nearest/strongest/weakest etc things, but I THIN$$anonymous$$ I can do that.
Well, that was just an existing example ;) You don't need all that things. If you really plan to implement all these modes your enemies have to track some information: creation time for oldest and newest, health for strongest and weakest,if you have slow towers the current speed for fastest and slowest and maybe the way it has traveled to deter$$anonymous$$e which one is furthest.
The only thing I'm really missing now (which is probably blatantly obvious, but I can't for the life of me see it) is how to access the variables needed (speed, maxHealth, etc). The only way I know to get a variable in another object is with a static variable, but that obviously won't work, or Send$$anonymous$$essage, but I have a feeling getting every enemy to send a message to every turret they're in range for isn't the best way to do things either :P
Every enemy should have a script that holds this information (i call it "Enemy.js"). You can simply get the script reference with var enemy : Enemy = currentCollider.GetComponent.<Enemy>();
. I will add it to my example.
Thank you so much! This works like a charm, and when I've done fiddling with it to get to know the unfamiliar things I'll definitely be able to use it to make a really good game! Thanks again for taking the time to explain it all to me; I wish I could upvote more than once!
Your answer
Follow this Question
Related Questions
Multiple targeting help 1 Answer
Targeting child object components based on a trigger. 0 Answers
Disable a target after trigger exit? 1 Answer
multiple targets and one trigger, is it possible? 1 Answer
Target touching enemy collision 1 Answer