- Home /
make projectiles always hit target
Hey guys, Making a 3d TD game where I have one of my towers shooting a projectile to hit an enemy unit. Since the enemy units are moving the projectile doesnt hit its target every time. I heard this can be remedied by using the speed and direction of the enemy. I dont know how I would include this though. I dont think it would hit if the enemy changed direction either. Does anyone know of a way I could solve this problem? Code is posted below. Thanks in advance,
AstarAIEnemy enemyObjectDetection = EnemySpawn.enemyList[closestIndex].GetComponent<AstarAIEnemy> (); //gets astarai code for that unit
targetPosition = enemyObjectDetection.transform.position; //sets the enemy position to the pos of the player unit
float distanceToTargetPos = Vector3.Distance (targetPosition, transform.position); //finds distance between the two units
//projectile motion code
// while (true) {
Projectile.position = this.transform.position; //puts projectile at archers pos
//calc velocity
float projectile_Velocity = distanceToTargetPos / (Mathf.Sin (2 * firingAngle * Mathf.Deg2Rad) / gravity);
// Extract the X Y componenent of the velocity
float Vx = Mathf.Sqrt (projectile_Velocity) * Mathf.Cos (firingAngle * Mathf.Deg2Rad);
float Vy = Mathf.Sqrt (projectile_Velocity) * Mathf.Sin (firingAngle * Mathf.Deg2Rad);
// Calculate flight time.
float flightDuration = distanceToTargetPos / Vx;
Projectile.rotation = Quaternion.LookRotation(targetPosition - Projectile.position); //rotates player/projectile towards object
while (elapse_time <= flightDuration) {
Projectile.Translate (0, (Vy - (gravity * elapse_time)) * Time.deltaTime, Vx * Time.deltaTime);
elapse_time += Time.deltaTime;
yield return null;
}
//yield return new WaitForSeconds(5f);
Projectile.position = this.transform.position; //resets so that unit can fire again
elapse_time = 0;
Answer by ABerlemont · Jun 24, 2014 at 09:04 AM
If you want your missile to "follow" your target wherever it goes you can do this :
using UnityEngine;
using System.Collections;
public class Missile : MonoBehaviour {
public Transform target;
float speed = 2f;
void Update(){
if(target == null) return;
transform.position = Vector3.MoveTowards(transform.position, target.position, Time.deltaTime * speed);
}
}
EDIT
Another way to do it.
This one is timed based instead of speed based so that's it's easier to control height.
using UnityEngine;
using System.Collections;
public class Missile : MonoBehaviour {
public Transform target;
float timeTravel = 10f;
float time = 0f;
Vector3 origin;
Vector3 destination;
float distance = 0f;
void Start(){
shootAt(target);
}
void shootAt(Transform newTarget){
target = newTarget;
time = timeTravel; // in seconds
origin = transform.position;
destination = target.position;
}
void Update(){
if(target == null) return;
time -= Time.deltaTime;
destination = target.position;
float progress = Mathf.InverseLerp(timeTravel, 0f, time);
//set projectile position
Vector3 newPosition = Vector3.Lerp(origin, destination, progress);
//set projectile height
newPosition.y = Mathf.Cos(Mathf.Lerp(-Mathf.PI * 0.5f, Mathf.PI * 0.5f, progress));
transform.position = newPosition;
if(transform.position == destination){
target = null;
}
}
}
@ABerlemont This would work but I also need it to arc like it was a projectile. Not just a missle.
I edited my answer to have the arc thing. To change height just multiply the newPosition.y before applying it to the object's position.
@ABerlemont I used your movetowards code with my existing physics code for the y component of velocity to get an answer. I had to put the target position inside the while loop so that it updates the enemy position while its traveling. Thanks for your help, ill give you the answer.