Targetting enemy, repeating code
Hi all,
So my issue is i have produced messy code. I have a gun and a bullet. In a fixedupdate in the gun, it searches through all the spawned enemies and stored the closest in a variable called myTarget. Then when the player presses a ui element, a bullet is instantiated. Ideally in the start() of the instantiated bullet object i have something like enemy = player.GetComponent().GetTarget(); Which should return the myTarget. However no matter what i tried various things would happen, a bullet would spawn with no target even though one is passed. So now ive created that same loop through all the enemies to search for the target again, it might not even be the same as the myTarget in the gun now!
public GameObject NearestEnemy() {
enemies = GameObject.FindGameObjectsWithTag("Enemy");
myTarget = null;
float distance = Mathf.Infinity;
Vector3 position = transform.position;
foreach (GameObject enemy in enemies){
Vector3 diff = enemy.transform.position - position;
float curDistance = diff.sqrMagnitude;
if (curDistance < distance){
myTarget = enemy;
distance = curDistance;
}
if (myTarget == enemy){
//Debug.Log("My closest selected enemy so far is: " + myTarget.transform.name);
}
}
return myTarget;
}
public void LazerAttack(){
if (myTarget == null){
} else if (Vector3.Distance(myTarget.transform.position, transform.position) < range && ammo > 0 && !bulletSpawned && myTarget != null){// if myTarget is in range then fire AND bullet spawned false
//Debug.Log(" target is " + myTarget);
bulletSpawned = true;
//Debug.Log("set bullet spawned to " + bulletSpawned);
Instantiate(bulletPrefab, transform.position, transform.rotation); // spawn bullet at the players current pos
ammo--;
}
//Debug.Log ("ATTACK BUTTON PRESSED");
}
So i have it working with essentially the same script which loops through all the enemies and returns the closest. Which is messy and not good. Anyone know how i can pass the myTarget to the instantiated bullet. In the fixedupdate of the buller i have a slerp which follows the nearest enemy.
Ive tried creating a setter in the bullet but no luck, it just fires into space. Ive also tried a getter in the bullet to the gun to get the target with no luck either! Thanks for the help
One thing you could try is setting up a clone of your spawned GameObject in script with a line of code like
GameObject clone = (GameObject)Instantiate (GameObjectYouWantToSpawn, positionOfSpawn, Quaternion.identity);
Then you can access a public function in your "cloned" object and set stuff there.
clone.GetComponent<ScriptYouAreAccessingHere>().setTargetFunction(target);
Not sure if this will work but it's worth a shot :D
Answer by JoshuaMcKenzie · Feb 02, 2016 at 02:08 AM
after spawning the bullet get the bullet's script and simply pass in the value.
public float range;
public int ammo;
public GameObject bulletPrefab;
private GameObject myTarget;
private float targetRange;
public void LazerAttack()
{
GetNearestEnemy();
if(myTarget && ammo>0 && targetRange < range)
{
GameObject bullet = GameObject.Instantiate<GameObject>(bulletPrefab);
bullet.transform.position = transform.position;
bullet.transform.rotation = Quaternion.identity;
//you need to get the bullet's monobehaviour to set its target after instantiating
BulletScript script = bullet.GetComponent<BulletScript>();
script.target = myTarget;
--ammo;
}
}
void GetNearestEnemy()
{
myTarget = null;
targetRange = 0;
//We don't need to use FindGameObjectWithTag!
//enemies = GameObject.FindGameObjectsWithTag("Enemy");
//This is much faster!
foreach ( GameObject enemy in EnemyScript.Enemies)
{
float currDistance = (enemy.transform.position - transform.position).magnitude;
if(!myTarget || currDistance<targetRange )
{
myTarget = enemy;
targetRange = currDistance;
}
}
}
With BulletScript being the actual monobehavior you have on your bullet (do note that the bullet script won't have access to the myTarget variable in the Awake(), since that runs immeadiately when you instantiate the bullet prefab).
Also FindGameObjectsWithTags is a pretty slow function (and performance might be a factor depending on how many times you call LazorAttack() each second). instead if you just slightly prep your enemy's monobehavior script you can possibly get a noticeable increase in framerate.
using System.Collections.Generic;
public class EnemyScript : MonoBehaviour
{
private static List<GameObject> enemies = new List<GameObject>();
public static List<GameObject> Enemies
{
get
{
return new List<GameObject>(enemies);
}
}
void OnEnable()
{
enemies.Add(gameObject);
}
void OnDisable()
{
enemies.Remove(gameObject);
}
}
Hi! Thanks for the answer, ive been reading it and implementing what you suggested. However im struggling to use the enemy script, which is in turn failing to instantiate a bullet. As the user is rarely pressing lazer attack and the array of enemies is 8 tops id like to try first getting the findwithtag working, then perhaps explore more options if i need more speed. So in the Bullet script i have a variable called target. This should then work correct? So in the start of the bullet, im calling the nearest enemy script, which value it returns is my target. by
target = player.GetComponent<Gun>().NearestEnemy();
But the game targets the first enemy it appears regardless if the target changes?
public GameObject NearestEnemy(){
enemies = GameObject.FindGameObjectsWithTag("Enemy");
GameObject myTarget = null;
float distance = $$anonymous$$athf.Infinity;
Vector3 position = transform.position;
foreach (GameObject enemy in enemies){
Vector3 diff = enemy.transform.position - position;
float curDistance = diff.sqr$$anonymous$$agnitude;
if (curDistance < distance){
myTarget = enemy;
distance = curDistance;
}
}
return myTarget;
}
If the code is still not working then I assume its due to how the code is running in the other scripts. Possibilities can be what ever is calling LazorAttack (possible but unlikely the culprit). what ever code you have in your bullet script, or what you have in your enemy script. since none of these have been provided and can only go on the code presented. if you can post the bullet script and possibly the enemy script then the issue might be pinpointed (since your using Find with tag you should make sure the enemy has that exact tag (letter casing matters) and that the scripts are enabled. make sure the bullet's script is active when spawned.