OnTriggerStay2D

My turrets have some strange behaviour in situations like in below photo. I guess this happens because my turret rotates first to bottom enemy and after to second enemy and loop continues.
6489761--729590--upload_2020-11-4_13-51-47.png

So, my ideea is:

  1. The enemies in turret range will be stored in an array
  2. Every enemy which exit the turret range will be removed from the array
  3. The turret brain or rotation is triggered in Update function. It will check from index 0 to index 20. When it finds the first indexed which is NOT null, then it rotates and break so it wont rotate to the next enemy which is in the turret range (aka indexed in our array)

It relatively works, i mean it really works. At some point, when Unity triggers me an error like in the below photo and the turret doesn’t rotate anymore. This happens only to some turrets. Every turret has his own script.
6489761--729596--upload_2020-11-4_13-52-10.png

I’m just lost, idk what to do/think and i wasted already 4 hours on this crap.

Here are my scripts:

The error comes from this function.

    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.gameObject.CompareTag("Enemy"))
        {
            int ArrayIndex = Array.IndexOf(triggeredEnemies, collision);
            if (ArrayIndex != -1)
            {
                if (triggeredEnemies[ArrayIndex] != null)
                    triggeredEnemies[ArrayIndex] = null;
                enemiesInArray--;
            }
        }
    }
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.CompareTag("Enemy"))
            triggeredEnemies[enemiesInArray++] = collision;
    }
    Collider2D[] triggeredEnemies = new Collider2D[20];
    public int enemiesInArray = 0;

    void Update()
    {
        for (int i = 0; i < 20; i++)
        {
            if (triggeredEnemies[i] != null)
            {
                Vector3 enemyPosition = triggeredEnemies[i].transform.position;
                Vector3 vectorToTarget = (enemyPosition - transform.position).normalized;
                float Angle = Mathf.Atan2(vectorToTarget.y, vectorToTarget.x) * Mathf.Rad2Deg;
                Quaternion quaternion = Quaternion.AngleAxis(Angle, Vector3.forward);
                lerpPercent = Mathf.MoveTowards(lerpPercent, 1f, Time.deltaTime * 1.35f);
                transform.rotation = Quaternion.Slerp(transform.rotation, quaternion, Time.deltaTime * RotationSpeed);
                if (lerpPercent >= 0.8f)
                    inVision = true;
                break;
            }
        }
    }

6489761--729590--upload_2020-11-4_13-51-47.png

You should throw in some Debug.Logs within your OnTriggerEnter and Exit functions to show the index of the array or how big/small the array gets. The error you are getting is telling you the Index is outside the Array bounds, Aka it is either larger than 20 or less than 0. The Debug.Logs will help you see how they are entering/exiting your array and should give you an idea of what is going on.

The problem is whenever an enemy is getting destroyed, enemiesInArray won’t be decreased by 1 because onTriggerExit won’t know it actually exited the trigger. But still, my main problem isn’t really solved, I managed to somehow reduce the unwanted behaviour by creating an child with another trigger function like in the below photo:

6490327--729718--upload_2020-11-4_17-2-16.png

When the rectangle triggers an enemy,the circle collider will be deactivated and the rotation will be depending on what that rectangle collides with. When this collides with nothing, then circle collider will be again activated.

But still, my turrets are flickering fast sometimes, and i really don’t know why. Maybe my rotation function is bad?

You didnt mention a flicker issue originally so Im not sure with that. Glad you got the array issue fixed. If it is flickering than it probably is something wrong with the turret rotation. I havent worked with rotations like that much but maybe you could turn your rotation script into a State Machine and have various states like Idle, FoundEnemy, ShootingEnemy, etc. I like using state machines mainly because it breaks down behavior into small sections where it is easy to figure out what is happening when and easier to debug, but thats my opinion.

I know there are tons of turret defense videos out there so maybe watch a different one and see how they handle rotation before you try my suggestion.

1 Like

Just use a List instead of an array to add/remove Collider2D references as they enter/exit the turret’s collider.

List<Collider2D> triggeredEnemies = new List<Collider2D>();

void OnTriggerEnter2D(Collider2D collider){
   if(collider.gameObject.CompareTag("Enemy")) {
      triggeredEnemies.Add(collider);
   }
}

void OnTriggerExit2D(Collider2D collider){
   if(collider.gameObject.CompareTag("Enemy")) {
      triggeredEnemies.Remove(collider);
   }
}