- Home /
Problem with List not filling using add method in a foreach loop
Hello i'm having a problem with the enemyHealth list inside the method SearchLowestEnemy. Basically, when i start the game the enemies array is filled with all the enemies in the scene. Then if they have a script called ExplosiveEnemyController (and they have without doubts) we take the health value from that script and add it to the list. Then it should print the list, but many errors occurs in unity, like if the list is empty but it shouldn't. Here is the code:
using Boo.Lang;
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.AI;
public class HealerEnemyController : MonoBehaviour
{
private NavMeshAgent navMeshAgent;
[SerializeField] private GameObject currentEnemy;
[SerializeField] GameObject[] enemies;
[SerializeField] List<int> enemyHealth;
[Header("Heal settings")]
[SerializeField] private float healRate, nextTimeToHeal;
[SerializeField] private int healQuantity;
private void Awake()
{
navMeshAgent = GetComponent<NavMeshAgent>();
}
private void Start()
{
InvokeRepeating("SearchLowestEnemy", 0, 15);
}
private void Update()
{
Heal();
}
private void SearchLowestEnemy()
{
enemies = GameObject.FindGameObjectsWithTag("Enemy");
foreach (GameObject enemy in enemies)
{
if (enemy.GetComponent<ExplosiveEnemyController>())
enemyHealth.Add(enemy.GetComponent<ExplosiveEnemyController>().health);
else
continue;
}
Debug.Log(enemyHealth);
if (enemyHealth.Count != 0)
{
enemyHealth = enemyHealth.Sort();
for (int i = 0; i < enemyHealth.Count; i++)
{
if (enemyHealth.ToArray()[0] == enemies[i].GetComponent<ExplosiveEnemyController>().health)
{
Debug.Log("Gameobject found: " + enemies[i].name);
currentEnemy = enemies[i].gameObject;
return;
}
else
continue;
}
}
}
private void Heal()
{
navMeshAgent.SetDestination(currentEnemy.transform.position);
navMeshAgent.stoppingDistance = 8;
if (healRate >= nextTimeToHeal)
{
currentEnemy.gameObject.GetComponent<ExplosiveEnemyController>().health += healQuantity;
healRate = 0;
}
else
healRate += Time.deltaTime;
if (currentEnemy.GetComponent<ExplosiveEnemyController>().health >= currentEnemy.GetComponent<ExplosiveEnemyController>().maxHealth)
{
return;
}
}
}
Answer by rh_galaxy · Sep 17, 2020 at 03:41 PM
It is doubtful that SearchLowestEnemy() has had a chance to run once before you run Heal() the first Update()... But I'm not sure. If so currentEnemy would be invalid the first time in Update().
Another note is that it is expensive to run GameObject.FindGameObjectsWithTag("Enemy"), and enemyHealth.Sort() just to find the enemy with the lowest health... Couldn't you just loop through enemies once and save the one with the lowest health? Why create the enemyHealth list and sort it... Bear in mind that all of this must be able to run within the time of a single frame, or you will not have smooth frame rate. I suggest this and that instead of FindGameObjectsWithTag() you keep an up to date list of your enemies so you don't need it created:
private void SearchLowestEnemy()
{
enemies = GameObject.FindGameObjectsWithTag("Enemy");
int lowest = 50000000; //a very high value
foreach (GameObject enemy in enemies)
{
if (enemy.GetComponent<ExplosiveEnemyController>()) {
int current = enemy.GetComponent<ExplosiveEnemyController>().health;
if(current < lowest) {
lowest = current;
currentEnemy = enemy.gameObject;
}
}
}
}
Oh i didn't think of this solution. I tried doing this and now everything works fine. Thank you very much for your help.
Your answer
Follow this Question
Related Questions
Can´t instantiate objects in list correctly 1 Answer
Cannot convert float to int when only using floats (C#) 3 Answers
An array or list of hashtables C# 2 Answers
How can I make this GameObjects array remain permanent when i activate? 1 Answer
How to send/copy array from dictionary to class and further to list of class 0 Answers