Search code examples
c#unity-game-engineindexoutofrangeexception

Increase enemy health every wave


As the title says, I want to increase my enemy hp after every wave, however after wave 1 i get "IndexOutOfRangeException: Index was outside the bounds of the array." error

note: i'm still a beginner and this is the first project i'm working on, i followed a tutorial for this script (i wrote some stuff myself too)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

public class WaveSpawner : MonoBehaviour
{
    public enum SpawnState { SPAWNING, WAITING, COUNTING };
    public int waveNumber = 0;
    [SerializeField] public TMP_Text waveNumberTextValue;
    public bool waveEnded = false;

    [System.Serializable]
    public class Wave
    {
        public string name;
        public Transform enemy;
        public int count;
        public float rate;
    }

    public Wave[] waves;
    private int nextWave = 0;

    public Transform[] spawnPoints;

    public float timeBetweenWaves = 5f;
    private float waveCountdown;

    private float searchCountdown = 1f;

    private SpawnState state = SpawnState.COUNTING;


    void Start()
    {

        waveNumber = 1;
        waveCountdown = timeBetweenWaves;
    }
    
    public void EnemyHpIncrease()
    {
        if (waveEnded == true)
        {
            if(waveNumber <= 10)
            {
                FindObjectsOfType<EnemyHealth>()[0].enemyHealth += 100f;
            }
            else
            {
                FindObjectsOfType<EnemyHealth>()[0].enemyHealth *= 1.1f;
            }
        }
    }

    void Update()
    {
        waveNumberTextValue.text = "Wave " + waveNumber.ToString("0");
        if(state == SpawnState.WAITING)
        {
            if(!EnemyIsAlive())
            {
                WaveCompleted();
                Debug.Log("hp increased by 100hp");
                waveEnded = true;
                waveNumber++; 
                
                
            }
            else
            {
                return;
            }
        }

        if(waveCountdown <= 0)
        {
            if(state != SpawnState.SPAWNING)
            {
                StartCoroutine(SpawnWave(waves[nextWave]));
            }
        }
        else
        {
            waveCountdown -= Time.deltaTime;
        }
    }

    public void WaveCompleted()
    {
        waveEnded = true;
        EnemyHpIncrease();
        state = SpawnState.COUNTING;
        waveCountdown = timeBetweenWaves;

        if(nextWave + 1 > waves.Length - 1)
        {
            nextWave = 0;
            Debug.Log("ALL WAVES COMPLETED!");
        }
            else
        {
            nextWave++;
        }
    }

    bool EnemyIsAlive()
    {
        searchCountdown -= Time.deltaTime;
        if(searchCountdown <= 0f)
        {
            searchCountdown = 1f;
            if(GameObject.FindGameObjectWithTag("Enemy") == null)
            {
                
                return false;
            }
        }
        return true;
    }

    IEnumerator SpawnWave (Wave _wave)
    {
        Debug.Log("Spawning Wave" + _wave.name);
        state = SpawnState.SPAWNING;
        waveEnded = false;

        for (int i = 0; i < _wave.count; i++)
        {
            SpawnEnemy(_wave.enemy);
            yield return new WaitForSeconds( 1f/_wave.rate );
        }

        state = SpawnState.WAITING;
        yield break;
    }

    void SpawnEnemy(Transform _enemy)
    {
        Debug.Log("Spawning Enemy" + _enemy.name);
        Transform _sp = spawnPoints[Random.Range(0, spawnPoints.Length)];
        Instantiate (_enemy, _sp.position, _sp.rotation);
    }
}

i tried putting debug.log everywhere and it doesnt show anymore after WaveCompleted(); in

                WaveCompleted();
                Debug.Log("hp increased by 100hp");
                waveEnded = true;
                waveNumber++; 
         

errors:

IndexOutOfRangeException: Index was outside the bounds of the array.
WaveSpawner.EnemyHpIncrease () (at Assets/scripts/WaveSpawner.cs:48)
WaveSpawner.WaveCompleted () (at Assets/scripts/WaveSpawner.cs:93)
WaveSpawner.Update () (at Assets/scripts/WaveSpawner.cs:65)

Solution

  • The IndexOutOfRangeException is on line 48:

    IndexOutOfRangeException: Index was outside the bounds of the array.
    WaveSpawner.EnemyHpIncrease () (at Assets/scripts/WaveSpawner.cs:48) <-- line number here
    

    Copying your code into Notepad++, line 48 appears to be the following:

    FindObjectsOfType<EnemyHealth>()[0].enemyHealth += 100f;
    

    The code is assuming that the result of the FindObjectsOfType<> method is returning an array with at least one element. I assume that the result in this case is an empty array, so there is no element at position 0.

    If the return value of FindObjectsOfType is supposed to be one object, and you only want to update one object, then you could perform the action only when there is at least one element in the array. If you want to change all of the returned objects, you will need to iterate over the array using, say, a foreachloop.