Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question How initialize disabled GameObjects?

Discussion in 'Scripting' started by compyler, May 1, 2023.

  1. compyler

    compyler

    Joined:
    Mar 30, 2020
    Posts:
    94
    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<Image>()) 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:
    Code (CSharp):
    1. Game.Start() {
    2.    ...
    3.    shopDialog.Initialize() // shopDialog is disabled (and thus all child buttons)
    4.        calls buttonClickHandler.SetEnabled() on a few child items
    5.              SetEnabled() crashes cause buttonImage is null, cause ButtonClickHandler.Start() was never executed
    6.  
    7.  
    8. }
    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!
     
  2. meredoth

    meredoth

    Joined:
    Jan 29, 2014
    Posts:
    7
  3. compyler

    compyler

    Joined:
    Mar 30, 2020
    Posts:
    94
    I don't think that will work. Awake() is also NOT called on disabled GameObjects
     
  4. meredoth

    meredoth

    Joined:
    Jan 29, 2014
    Posts:
    7
    Did you try it ? Did you read the link I gave you ? Check the example in the link
     
  5. compyler

    compyler

    Joined:
    Mar 30, 2020
    Posts:
    94
    Yes, I tried it. Awake is NOT called for the disabled objects
     
  6. meredoth

    meredoth

    Joined:
    Jan 29, 2014
    Posts:
    7
    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."
     
  7. Adrian

    Adrian

    Joined:
    Apr 5, 2008
    Posts:
    1,051
    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.
     
  8. compyler

    compyler

    Joined:
    Mar 30, 2020
    Posts:
    94
    @meredoth I think you don't understand my problem.

    @Adrian. 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.