Is this a bad practice?

I’ve got a script in an object, which uses (GetComponentInChildren) in Update to get a reference to a specific potential child.

public ScriptName scriptName;

void Update() {
    scriptName = gameObject.GetComponentInChildren<ScriptName>():
}

The reason I’m doing it in Update is that the child will not always be there. The object starts out empty, and the player can add and remove the child at runtime, so I need to make sure the script always has a reference.

What’s weird is I expected this to spew out errors whenever the object didn’t have the child (since it’s trying to get a component from something that isn’t there). But it doesn’t, and it seems to be working fine so far.

But I’m still worried about whether if I actually keep it this way, will there be any problems down the line.

GetComponent isn’t the quickest method to run. Personally, I would have ScriptName populate the field in Awake or OnEnable and have it remove itself in OnDisable or OnDestroy instead or when it is created/destroyed.

1 Like

GetComponent<> and ist siblings are very expensive performancewise. A better method is to ‘cache’ (store in a global variable) the reference, and test if the reference was lost (is null) before re-aquiring it:

if (cachedScript == null) {
    // warning: this will execute each update until
    // the script is reaquired
    cachedScript = this.gameObject.GetComponentInChildren<ScriptType>();
   // if not aquired, exit
   if (cachedScript == null)
        return

}

// if we get here, we have a valid script

Much better, of course would be if the children notified the parent of connecting and disconnection via Awake() and OnDestroy() as mentioned

1 Like

Why not call a public function that reassigns the script when the player adds the object at runtime?

public void reassign() {
    scriptName = gameObject.GetComponentInChildren<ScriptName>():
}

So when the player adds the object at runtime call reassign()?

And when the player removes the object, set scriptName to null.

I assume the Player Controller script is separate to that script, but you can call functions in other scripts easily.

Also, if you’re not getting errors when the object isn’t there, there is definitely something wrong.

1 Like

The dirty flag pattern to the rescue!
Make a private boolean and set it to true at declaration. In OnTransformHierarchyChanged event, always reset this flag to true. Whenever you want to use child ScriptName, check that flag. If true, update class level cached variable, if not true just return it.

3 Likes

Dang!!! That’s hell of great tip - can’t find any Info on OnTransformHierarchyChanged, though, can you link please?

You need one about children

1 Like