x


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;
    }
more ▼

asked Aug 08 '12 at 11:33 AM

asimov gravatar image

asimov
157 19 36 40

You might find it easier to use a List instead of Array as it doesn't require re-sizing.

Aug 08 '12 at 02:48 PM speedything
(comments are locked)
10|3000 characters needed characters left

1 answer: sort voted first

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.

more ▼

answered Aug 08 '12 at 02:46 PM

speedything gravatar image

speedything
425 1 4

(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x986
x356
x355
x61

asked: Aug 08 '12 at 11:33 AM

Seen: 314 times

Last Updated: Aug 08 '12 at 02:48 PM