Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Bug AddListener seemingly doesn't work in my code?

Discussion in 'UGUI & TextMesh Pro' started by Aleg2012, May 19, 2024.

  1. Aleg2012

    Aleg2012

    Joined:
    Jan 4, 2022
    Posts:
    3
    Hello,
    I am trying to dynamically create buttons at runtime based on UI options which are given to me through Scriptable Objects that currently hold custom functions. Each of these functions is passed through an interface that is passed in the code down below.
    My problem is that the cardButton.onClick.AddListener doesn't do anything.

    Please help!

    Code (CSharp):
    1.         //Creates cards for construction, building and troop training
    2.         public GameObject CreateCard(UICardData cardData)
    3.         {
    4.             this.data = cardData;
    5.             GameObject cardPrefab = Resources.Load("UIActionCard", typeof(GameObject)) as GameObject;
    6.             GameObject card = GameObject.Instantiate(cardPrefab);
    7.             Image cardIcon = card.transform.Find("Button").GetComponent<Image>();
    8.             cardIcon.sprite = cardData.Image;
    9.             Button cardButton = card.transform.Find("Button").GetComponent<Button>();
    10.             //since it seemingly doesnt accept functions from non monobehavior classes, lets try this.
    11.             UIActionHandler uiCard = card.AddComponent<UIActionHandler>();
    12.             uiCard.data = cardData;
    13.             cardButton.onClick.AddListener(() => uiCard.TriggerCardAction());
    14.             return card;
    15.         }
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,394
    AddListener definitely works so isolate, isolate, isolate.

    I recommend making an "adaptor" for the things you are making (in this case cards) and a structure to call a factory to make those adaptors, either from a prefab or from an in-scene example.

    See the attached package.


    Keep in mind that using GetComponent<T>() and its kin (in Children, in Parent, plural, etc) to try and tease out Components at runtime is definitely deep into super-duper-uber-crazy-Ninja advanced stuff.

    Here's the bare minimum of stuff you absolutely MUST keep track of if you insist on using these crazy Ninja methods:

    - what you're looking for:
    --> one particular thing?
    --> many things?
    - where it might be located (what GameObject?)
    - where the Get/Find command will look:
    --> on one GameObject? Which one? Do you have a reference to it?
    --> on every GameObject?
    --> on a subset of GameObjects?
    - what criteria must be met for something to be found (enabled, named, etc.)

    If you are missing knowledge about even ONE of the things above, your call is likely to FAIL.

    This sort of coding is to be avoided at all costs unless you know exactly what you are doing.

    Botched attempts at using Get- and Find- are responsible for more crashes than useful code, IMNSHO.

    If you run into an issue with any of these calls, start with the documentation to understand why.

    There is a clear set of extremely-well-defined conditions required for each of these calls to work, as well as definitions of what will and will not be returned.

    In the case of collections of Components, the order will NEVER be guaranteed, even if you happen to notice it is always in a particular order on your machine.

    It is ALWAYS better to go The Unity Way(tm) and make dedicated public fields and drag in the references you want.
     

    Attached Files: