- Home /
The question is answered, right answer was accepted
Parent "Start" running before children are created
I have a parent element with many nested children. Several children and grandchildren have Start() scripts similar to what I've posted below.
The problem is that when the root transform runs it's start script, it will throw nulls when looking for children. Sometimes there is no error, sometimes it won't find child1, and sometimes it won't find a different child. Even when it throws the null reference errors, it still correctly changes the textures for the objects it 'couldn't find.'
Here is the code from the root parent.
// Use this for initialization
void Start () {
//declare connected objects
infoObject = transform.Find("Info");
statsObject = infoObject.Find ("Stats");
statsBoxObject = statsObject.Find ("Box");
nameObject = infoObject.Find ("Name");
movementObject = statsBoxObject.Find ("Movement");
attackObject = statsBoxObject.Find ("Attack");
defenseObject = statsBoxObject.Find ("Defense");
abilitiesObject = infoObject.Find ("Abilities");
detailsObject = infoObject.Find ("Details");
type0Object = detailsObject.Find ("Type 0");
type1Object = detailsObject.Find ("Type 1");
type2Object = detailsObject.Find ("Type 2");
backgroundObject = transform.Find ("Background");
imageObject = transform.Find ("Image");
summonObject = infoObject.Find ("Summon Cost");
graphicsHandler = GameObject.Find ("Handler Graphics").transform;
abilityList = new AbilityList ();
tools = new Tools ();
UpdateInformation ();
}
So with the first few lines of this code:
//declare connected objects
infoObject = transform.Find("Info");
statsObject = infoObject.Find ("Stats"); <==Throws a null reference error
statsBoxObject = statsObject.Find ("Box"); <==No error
nameObject = infoObject.Find ("Name"); <==No error
I get null reference error, but then when the variables are used later to change textures on these objects everything works just fine.
You don't show definition of infoObject or statsObject which are unfamiliar to me - are those setup in Awake() on parent, or public drag/drop, etc?
All of those variables are private variables declared globally.
public class CreatureCard : $$anonymous$$onoBehaviour {
//tie into children
private Transform infoObject;
private Transform nameObject;
private Transform movementObject;
private Transform attackObject;
private Transform defenseObject;
private Transform abilitiesObject;
private Transform detailsObject;
private Transform type0Object;
private Transform type1Object;
private Transform type2Object;
private Transform backgroundObject;
private Transform imageObject;
private Transform summonObject;
private Transform statsObject;
private Transform statsBoxObject;
//tie into tools
private Tools tools;
private AbilityList abilityList;
private Transform graphicsHandler;
public void Start(){
//this script is in the question above
}
}
I'm stumped. I thought it might be a racing condition, but by the time Parent starts looking for things in Start(), children objects would have run their Awake() I assume.
You assumed right.
Awake is called before any Start.
http://docs.unity3d.com/$$anonymous$$anual/ExecutionOrder.html
might be a stupid question, but are the child transforms enabled?
Answer by DiegoSLTS · Sep 03, 2015 at 05:32 PM
Are you sure the error is in that line of the script? The next line will never work if that line throws an error, it's just impossible. Could it be that the same script is also in a different object by mistake and the instance on that object is giving you an error?
Add some debug code, something like:
infoObject = transform.Find("Info");
if (infoObject == null)
Debug.Log("infoObject is NOT a child of: " + gameObject.name);
else
Debug.Log("infoObject IS a child of: " + gameObject.name);
Answer by Suddoha · Sep 03, 2015 at 10:34 PM
Is there any special reason whyyou use transform.Find() calls, and on top of that, so many?
they are inefficient
typos happen alot
difficult to maintain when a name changes which is used in several places
difficult to mainain when you decide to have a different hierarchy
all instances of your class will depend on the same names (several disadvantages in other situations)
one missing transform (not found or typo in the name) makes the whole chain fail
I really recommend to approach this in a different way. As for the current set up, you have to add log statements and determine which transform cannot be found. Then, check the names, check your object hierarchy when hitting play and compare again.
Is there a better way to store a link to a child transform?
This is one prefab that, when initialized, changes texture/text/color/rotation/and visibility of its children depending on public variables that are changed when it is initialized. I figured this would be easier than having hundreds of prefabs that are only slightly different from each other.
So the point of all the transform.Find() is that the root parent changes properties of its children during runtime when it is initialized, damaged, moved, buffed, etc. Is there a better approach?
You put your fields public and assign them in editor. If this is in a prefab, references will remain good after instantiation.
If these fields refers to the same references and are loaded in every new prefabs, you can create an object specifically for this purpose and reference this one ins$$anonymous$$d of your huge Start.
Follow this Question
Related Questions
Unity Player Crashing On Windows Startup 1 Answer
Parameters at Startup 1 Answer
Unity 4.2 editor crashes on startup when importing image files 1 Answer
i'm having trouble starting unity how do i fix it 0 Answers
I really ned help at startup 0 Answers