How to get all children of a Gameobject with a certain component
I am making a card game and when the cards are dealt they are attached to my Player1 Gameobject (This GO also has other things than cards attached to it). What I want to do is to find all the cards on the player and add them to an Array/List (The Card Gameobject have a "Card" class attached to them. This is what I have tried to do:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerGetCards : MonoBehaviour {
int x;
List<GameObject> Children;
TableMaster tMaster;
PlayerMaster pMaster;
string[] cards;
public List<GameObject> slots;
public void GetCards(bool durchgang)
{
pMaster = GetComponent<PlayerMaster>();
tMaster = pMaster.table.GetComponent<TableMaster>();
StartCoroutine(GetChildren(durchgang));
}
IEnumerator GetChildren(bool durchgang)
{
yield return new WaitForSeconds(1);
if(!durchgang)
{
x = 0;
foreach(Transform child in this.transform)
{
if(child.GetComponent<Card>())
{
AddChildCard(child.name);
x++;
}
}
}
else
{
x = 4;
foreach(Transform child in this.transform)
{
if (child.GetComponent<Card>())
{
AddChildCard(child.name);
x++;
}
}
}
}
void AddChildCard(string name)
{
cards.SetValue(name, x);
}
}
But for some Reason I get the following error two times:
NullReferenceException: Object reference not set to an instance of an object PlayerGetCards.AddChildCard (System.String name) (at Assets/Scripts/PlayerScripts/PlayerGetCards.cs:56) PlayerGetCards+c__Iterator0.MoveNext () (at Assets/Scripts/PlayerScripts/PlayerGetCards.cs:47) UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) (at C:/buildslave/unity/build/Runtime/Export/Coroutines.cs:17)
Thanks in advance!
Answer by Bunny83 · Sep 16, 2017 at 02:21 PM
You haven't initialized your "cards" array anywhere. So it's default value is "null" (no array). When you try to use the array you get a null reference exception inside your AddChildCard method. You should learn how to read the stacktrace you get in the error. It tells you exactly the line where the error occurred (Line 56).
Also if you want to set the element in an array you usually use:
cards[x] = name;
and not SetValue. Keep in mind that you have to create your array "large enough". Arrays can't be resized at runtime
Answer by StonedLover · Sep 16, 2017 at 03:20 PM
You can short your code a lot use getcompenentsinchildren() to get all cards Sry Im writing on mobilephone, so the formation is missing.
I though about this as well, however GetComponentsInChildren will also find deep children as well as components on the parent object. I think this shouldn't be a problem in his case but it can give you problems in other situations. Besides that GetComponentsInChildren will allocate a new array each time it's called while his method does not.
Though since his two foreach loops are completely identical he could have done this with just one loop
x = 0;
if(durchgang)
x = 5;
foreach(Transform child in this.transform)
{
if(child.GetComponent<Card>())
{
AddChildCard(child.name);
x++;
}
}
Though using a generic List would probably make more sense than a pre allocated array and tracking the current index manually.
There are methods without allocations from version 5.4 but they are only in documentatiion about GameObject:
https://docs.unity3d.com/ScriptReference/GameObject.GetComponentsInChildren.html
public void GetComponentsInChildren(List results);
public void GetComponentsInChildren(bool includeInactive, List results);
Bunny83 Does it really take the parent in count ? Didnt noticed it yet. If so, the $$anonymous$$ethode name isnt picked well from Unity.
Well I used it so far all the time, when I need to get the same Component from Children's. Didn't run into an issue yet. :P
Probably because you didn't have that component on the parent -.-. Sure in most cases it works just fine. Though if you have a deep / complicated hierarchy the performance hit could matter. GetComponentsInChildren has to traverse the whole hierachy tree downwards..
Any yes, it is a bad name for what it does. It's the same with "GetComponentInParent / GetComponentsInParent". It also includes the given object and not just it's parents. Though they now mention this in the documentation
Returns all components of Type type in the GameObject or any of its children.
Returns all components of Type type in the GameObject or any of its parents