How initialize disabled GameObjects?

Hello,

I have a simple problem but struggle to find an elegant solution.

I have a canvas with GameObject that has script “ShopDialog” (the GameObject represents an UI dialog)…
Underneath the ShopDialog GameObject are several UI buttons with script “ButtonClickHandler.”
In ButtonClickHandler.Start() I fetch the image of the button (buttonImage=GetComponent()) and use member buttonImage in method SetEnabled().

Now comes the problem: When the scene loads, the ShopDialog GameObject is inactive and thus ButtonClickHandler.Start() does not run on the child buttons. In the Initialization of the scene I call ShopDialog.Init() which calls ButtonClickHandler.SetEnabled() on a few buttons and then the game crashes cause buttonImage is null (cause Start didn’t run).
Visualized:

Game.Start() {
   ...
   shopDialog.Initialize() // shopDialog is disabled (and thus all child buttons)
       calls buttonClickHandler.SetEnabled() on a few child items
             SetEnabled() crashes cause buttonImage is null, cause ButtonClickHandler.Start() was never executed


}

So my question is: How can I solve this? How can I initialize disabled GameObjects? I heard using the Constructor is NOT save.

Thanks for help!

You can try calling the GetComponent in the awake method instead. Unity - Scripting API: MonoBehaviour.Awake()

I don’t think that will work. Awake() is also NOT called on disabled GameObjects

Did you try it ? Did you read the link I gave you ? Check the example in the link

Yes, I tried it. Awake is NOT called for the disabled objects

Of course it isn’t, but if you see the example in the link it will get called before OnEnable when you call the SetActive to enable it. Quote from the link example “pressing the space key will execute code in Example2.Update that activates Cube1, and causes Example1.Awake() to be called.”

Scripts on deactivated game objects are not initialized, there’s no way around that.

I could see a few workarounds for your case:

  • Make the game objects active in the scene and only deactivate them after the scene loads in Awake or OnEnable.
  • Make buttonImage a public field and set it in the inspector, so it’s set even if the object hasn’t initialized.
  • Make buttonImage a property instead that loads and caches the component the first time it’s called.
  • Defer the operation. If SetEnabled is called on an non-initialized script, it only caches the enabled state and later sets up buttonImage once the game object is activated.

@meredoth I think you don’t understand my problem.

@ Thanks for your response. Thanks for your suggestions. I tried another approach that works (not sure if its good). I added a public Initialize() method to ButtonClickHandler() which is called explicitly by ShopDialog.

But I also like your deferred idea.