- Home /
Some help with aiming script, please.
Hi,
I am working on an aiming script which uses a trigger collider that extends forward in front of the Player to detect if enemies have entered it and therefore in front of him. When they do, it goes on to calculate the distance of each enemy from the Player and then finds which is closest to the player. It will then place the cursor into this enemy for the user to begin shooting.
The enemies that enter the trigger are added to an array (enemyArray) inside OnTriggerEnter(), which is used in the FindClosestEnemy() function. Enemies are removed from the array when they leave the trigger, in OnTriggerExit().
Now, all this is working fine, but I am now trying to implement what will happen when an enemy is destroyed (shot at by the user). It appears as though this would be a very similar process to that of when an enemy leaves the trigger, (remove enemy, resize array, etc), but I seem to be getting errors in one place or another.
I was wondering if anyone can lend a hand here as I have a feeling this should be something relatively simple to do.
I have pasted the script below (not as bad as it looks).
Any questions, please ask :) Thanks
//-----
public GameObject[] enemyArray;
// The current number of enemies inside the trigger
private int enemyCounter = 0;
// Global variable used to hold the current enemy position. This is required so that the
// Shooter_R script can access it and assign it to the direction of the bullets to shoot at the enemy.
public Vector3 EnemyPosition = Vector3.zero;
// Variable to hold the current closest enemy GameObject
public GameObject closest;
// GameObject used to access the Player object in another script
private GameObject playerObj;
// GameObject used to access the BulletSpawner_R object in another script
private GameObject bulletDirObj;
private Vector3 fwd = Vector3.zero;
public bool EnemyTargetted;
// Used for other scripts to tell this script that the currently targetted enemy has been destroyed
public bool EnemyDestroyed;
//-----------------------------------------------------
// Use this for initialization
void Start()
{
playerObj = GameObject.Find("Player");
// Find the BulletSPawner object
bulletDirObj = GameObject.Find("BulletSpawner_R");
// fwd = bulletDirObj.transform.TransformDirection(Vector3.forward);
EnemyTargetted = false;
EnemyDestroyed = false;
}
//-----------------------------------------------------
// Update is called once per frame
void Update()
{
// if array has not been created
if (enemyArray == null )
{
// Debug.Log("CLOSESTENEMY - UPDATE - ARRAY = NULL");
// Debug.Log("Array is null");
EnemyTargetted = false;
GetComponent<CrosshairToggle>().EnemyPos = Vector3.zero;
// Access the CrosshairToggle script and Disable it as no enemies in Tube
GetComponent<CrosshairToggle>().enabled = false;
}
// if array is empty (0 enemies)
else if (enemyArray.Length == 0)
{
EnemyTargetted = false;
closest = null;
GetComponent<CrosshairToggle>().EnemyPos = Vector3.zero;
// Access the CrosshairToggle script and Disable it as no enemies in Tube
GetComponent<CrosshairToggle>().enabled = false;
}
// Otherwise, the array must have something inside it (i.e enemies)
else
{
for (int i = 0; i < enemyCounter; i++)
{
// Call the FindClosestEnemy() function to find which of the enemies in the enemyArray (the tube)
// is the closest to the player.
FindClosestEnemy();
// Debug.Log("UPDATE - ENEMY_TARGETTED = TRUE");
EnemyTargetted = true;
// Access the CrosshairToggle script and Enable it
GetComponent<CrosshairToggle>().enabled = true;
// Access the script's EnemyPos variable and pass it the position of the enemy
GetComponent<CrosshairToggle>().EnemyPos = EnemyPosition;
}
}
}
//-----------------------------------------------------
/* This function detects and keeps track of the enemies entering the trigger and adds them to an array.
* The array holding the current enemies is enemyArray.
*
*/
void OnTriggerEnter(Collider theCollider)
{
// if the collider of the object that entered the trigger has tag "Enemy"..
if (theCollider.gameObject.tag == "Enemy")
{
// Debug.Log("CLOSESTENEMY - TRIGGER_ENTER");
// Increment the array counter by 1
enemyCounter++;
// if no other enemies in the trigger..
if (enemyCounter == 1)
{
// Re-size the array to the counter size
enemyArray = new GameObject[enemyCounter];
}
// Otherwise, there is more than 1 enemy in the trigger..
else
{
// Debug.Log("CLOSESTENEMY - ON_TRIGGER_ENTER - ELSE");
// So copy the previous enemyArray in an array called oldEnemies
GameObject[] oldEnemies = enemyArray;
// Re-size the enemyArray array to the size of the enemyCounter
enemyArray = new GameObject[enemyCounter];
// Initialize the index
int i = 0;
// Iterate through the oldEnemies array
foreach (GameObject oldEnemy in oldEnemies)
{
// Debug.Log("ON_TRIGGER_ENTER - ITERATE THROUGH OLDENEMIES ARRAY");
// assign the oldNeighbors to neighbors
enemyArray[i] = oldEnemy;
// increment the index
i++;
}
// Get the new enemy who has entered the collider
GameObject newEnemy = theCollider.gameObject;
Debug.Log("enemyCounter = " + enemyCounter);
// Add it to the array
enemyArray[enemyCounter - 1] = newEnemy;
}//ends else
}// ends if-
}
//-----------------------------------------------------
/* This function keeps track of the enemies exiting the trigger and removes them from the array.
*
* enemyArray holds the current enemies in the trigger.
*/
void OnTriggerExit(Collider theCollider)
{
// If the collider of the object that exited the trigger has tag "Enemy"..
if (theCollider.gameObject.tag == "Enemy")
{
// Debug.Log("CLOSESTENEMY - TRIGGER_EXIT");
// Debug.Log("Enemy Exited");
// decrement count since we have an enemy exiting the trigger
enemyCounter--;
// if there are other enemies in the trigger..
if (enemyCounter > 0)
{
// Debug.Log("ON_TRIGGER_EXIT - IF ENEMYCOUNTER > 0");
// Make a copy of the enemyArray in an array called oldEnemies
GameObject[] oldEnemies = enemyArray;
// Resize the enemyArray array to the new size after the enemy has left the trigger
enemyArray = new GameObject[enemyCounter];
// Initialize the index
int i = 0;
// Get enemy that has exited the collider and assign it to exEnemy
GameObject exEnemy = theCollider.gameObject;
// Iterate through the oldEnemies array, removing the enemy that left the trigger
foreach (GameObject oldEnemy in oldEnemies)
{
// Is the enemy that left, still part of the array (oldEnemies array, as that has been copied from
// enemyArray).
// Check if the enemy that has left the trigger, matches any of the enemies in the array.
if (exEnemy != oldEnemy)
{
// Debug.Log("ON_TRIGGER_EXIT - IF EXENEMY != OLDENEMY");
// Ie, we are copying all but the enemy that has left the trigger, back into the
// enemyArray again. Thereby, essentially removing that enemy from the enemyArray.
enemyArray[i] = oldEnemy;
// increment index
i++;
}
}
}
// Ie. If that enemy was the only one in the trigger/array..
else
// Set the enemyArray to have 0 elements - Empty it to make sure
enemyArray = new GameObject[0];
// if the array has 0 length, ie. empty..
if (enemyArray.Length == 0)
{
// Set the EnemyTargetted flag to flase
EnemyTargetted = false;
// Debug.Log("Inside OnTriggerExit() - Array is Empty");
}
}
}
//-----------------------------------------------------
// Calculates the closest enemy in the enemyArray (ie. the tube)
void FindClosestEnemy()
{
// Initially set distance to infinity
float distance = Mathf.Infinity;
// Find the Player object in the scene - so that we can access its position
// GameObject PlayerObj = GameObject.Find("Player");
// The position of the object the script is attached to (usually the Player)
Vector3 position = playerObj.transform.position;
// For each of the GameObjects in the GameObject array..
foreach (GameObject go in enemyArray)
{
// Find the distance from Player to the Enemy (enemy pos - Player pos)
Vector3 diff = go.transform.position - position;
// Calculating the squared magnitude instead of the magnitude is much faster.
// Often if you are comparing magnitudes of two vectors you can just compare their squared magnitudes.
// curDistance is the distance of the current enemy in the comparison
float curDistance = diff.sqrMagnitude;
// if the current distance is smaller than distance value..
if (curDistance < distance)
{
// Debug.Log("FIND CLOSEST ENEMY - FINDING CLOSEST ENEMY");
// Assign that GameObject as the closest enemy
closest = go;
// Assign the value of distance to be that Enemy's distance
distance = curDistance;
}
}
EnemyPosition = closest.transform.position;
//return closest;
}
You might find it easier to use a List ins$$anonymous$$d of Array as it doesn't require re-sizing.
Answer by speedything · Aug 08, 2012 at 02:46 PM
OnTriggerExit requires the object to leave the trigger before being destroyed or it won't register. A common work around is to do something like.
IEnumerator Die()
{
transform.Translate(Vector3.up * 10000);
yield return new WaitForFixedUpdate();
Destroy(gameObject);
}
This will make it trigger before destroying it.