Heart bar problem with list/array
Hi guys, I'm tryi'n to do a life bar with heart and not a slider. For that i've created an transform array to get child and then stack them in a list, and later call it to enable or disable the game object. Seems unity doesn't like the way i've done it, can anyone take a look to explain me my errors :D Thanks :)
public class Health : MonoBehaviour
{
public int health = 3;
int maxLife;
public Sprite fullHeart;
public Sprite emptyHeart;
[SerializeField] Transform[] Lifes;
List<GameObject> childObjects;
// Start is called before the first frame update
void Start()
{
Lifes = GetComponentsInChildren<Transform>();
List<GameObject> childObjects = new List<GameObject>();
foreach(Transform child in Lifes)
{
childObjects.Add(child.gameObject);
}
}
// Update is called once per frame
void Update()
{
SetLife();
}
void SetLife(){
for (int i = 1; i < Lifes.Length; i++)
{
if (i < health)
{
childObjects[i].SetActive(true);
}else{
childObjects[i].SetActive(false);
}
}
}
}
Answer by The_Three_Vs · Mar 31, 2020 at 03:29 PM
Lists are 0-indexed; you'll need to change your for loop to
for (int i = 1; i <= Lifes.Length; i++)
{
if (i <= health)
{
childObjects[i - 1].SetActive(true);
}else{
childObjects[i - 1].SetActive(false);
}
}
If, for example, the length of Lifes is 3 and current health is 2, this new loop will check if 1 is less than or equal to 2, which it is, and set the 1st childObject, which has a list index of 0, to be active. The loop will then check if 2 is less than or equal to 2, which it is, and set the 2nd childObject, which has a list index of 1, to be active. The loop will then check if 3 is less than or equal to 2, which it isn't, and set the 3rd and last childObject, which has a list index of 2, to be inactive. Since i is now 4 and greater than Lifes.Length, the loop won't try to access a nonexistent heart and will terminate.
Hope this helps!
Answer by Mrintoxx · Mar 31, 2020 at 05:44 PM
Done for that, i've understanded my mistake.
but the code you show me, it's the same doing that ? :
for (int i = **0**; i < Lifes.Length; i++)
{
if (i <= health)
{
childObjects[i].SetActive(true);
}else{
childObjects[i].SetActive(false);
}
But i think my problem is not here, i've got an error :"object reference not set" in this part of code :
void Start()
{
Lifes = GetComponentsInChildren<Transform>();
List<GameObject> childObjects = new List<GameObject>();
foreach(Transform child in Lifes)
{
childObjects.Add(child.gameObject);
}
}
I'm getting the child of the GameObject in an Transform array and then to a gameobject list.
But in the inspector the parent gets inside the array, for this reason the for loop was starting at 1.
any idea ?
GetComponentInChildren searches all the children, and the gameObject that called the function, for the specified component. You can fix the issue by adding if if statement if(child != transform)
when adding elements to childObjects. You can then use childObjects.Count ins$$anonymous$$d of Lifes.Length, since childObjects will have the correct length even if the objects are inactive. If you want to maintain Lifes, you will have to create a temporary array without the parent, then assign it to Lifes. For example:
Transform[] temp = new Transform[Lifes.Length - 1];
for(int i = 0; i < Lifes.Length; i++)
{
if(Lifes[i] != transform)
{
childObjects.Add(Lifes[i].gameObject);
temp[i - 1] = Lifes[i];
}
}
Lifes = temp;
Your answer
