Search Unity

Resolved Dynamic Button onClick handler assignment: method args incompatible

Discussion in 'Scripting' started by mcbauer, Feb 5, 2021.

  1. mcbauer

    mcbauer

    Joined:
    Oct 10, 2015
    Posts:
    524
    I read in from my database and spawn buttons based on elements in an array. Each button needs to fire off an onClick handler that passes a specific int, set for each button so I can know which button has been pressed.

    Here is the method which handles the button creation.

    Code (CSharp):
    1.  
    2. private void CreateButton(int buttonIndex, int btnIndex)
    3.     {
    4.         GameObject button = (GameObject)Instantiate(buttonPrefab);
    5.         button.name = $"Button:{btnIndex}";// set specific name
    6.         // ListUI is parent UI element which has Grid Layout Group assigned
    7.         GameObject ListUI = GameObject.Find("List");
    8.         button.transform.SetParent(ListUI.transform, false);//Setting button parent
    9.         button.GetComponent<Button>().onClick.AddListener(() => ButtonPressed(btnIndex));
    10.     }
    11.  
    12.     void ButtonPressed(int buttonIndex)
    13.     {
    14.         print("Button clicked: " + buttonIndex);
    15.     }
    16.  
    Buttons are spawned correctly, properly named and arranged based on the Grid Layout Group, but upon press I get
    Code (CSharp):
    1.  
    2. ArgumentException: method arguments are incompatible
    3. System.Delegate.CreateDelegate (System.Type type, System.Object firstArgument, System.Reflection.MethodInfo method, System.Boolean throwOnBindFailure, System.Boolean allowClosed) (at <fb001e01371b4adca20013e0ac763896>:0)
    4.  

    I'm following the suggestions from the documentation here

    I've tried all three of the recommendations, passing no specific parameters, using delegates, and the way shown above.

    What am I missing?

    Thanks in advance
     
  2. arfish

    arfish

    Joined:
    Jan 28, 2017
    Posts:
    782
    What happens if you copy the exact code from the example, and attach three UI buttons to it in the Inspector?
     
  3. mcbauer

    mcbauer

    Joined:
    Oct 10, 2015
    Posts:
    524
    Works as expected @arfish

    I'm wondering if I need to create a private List<Button> to store references to the buttons....and then add the listeners to the references...?

    seems like I shouldn't have to...
     
  4. mcbauer

    mcbauer

    Joined:
    Oct 10, 2015
    Posts:
    524
    Nope...same error
     
  5. mcbauer

    mcbauer

    Joined:
    Oct 10, 2015
    Posts:
    524
    Maybe something is wrong with how I'm creating the buttons?

    Code (CSharp):
    1.  
    2. // if I successfully retrieved my data...
    3. if (webRequest.responseCode == 200)
    4. {
    5. // grab the raw data
    6.   var data = webRequest.downloadHandler.text;
    7.   // now convert it to my serialized class      
    8.   targetData = JsonUtility.FromJson<DataTargets>(data);
    9.   // spawn all the buttons
    10.   foreach (TargetActor tgt in targetData.targetActors)
    11.        CreateButton(tgt.tgt_ID, tgt._Targets.Count);
    12. }
    13.  
    Seems straightforward to me and works in all other regards, but maybe I'm missing something?
     
  6. Elango

    Elango

    Joined:
    Jan 27, 2016
    Posts:
    107
    There is nothing wrong with your AddListener method, it should work fine.
    Check your prefab (buttonPrefab) if it has an incorrect Button OnClick event assignment in the inspector.
     
  7. arfish

    arfish

    Joined:
    Jan 28, 2017
    Posts:
    782

    It's probably easy to check in the Editor.
    Do the buttons look as you expect when they are instantiated (CreateButton())?
    Can you assign the OnClick event manually from the Editor? And so on.
     
  8. mcbauer

    mcbauer

    Joined:
    Oct 10, 2015
    Posts:
    524
    When I initially made the button and tested all the code it was applied via the editor. Once I was happy with all functionality I moved to dynamic creation, which obviously is when this issue arose.

    @Elango The prefab has nothing applied in the onClick, either before or after spawning. From what I understand, during runtime, the button prefab should still show an empty onClick handler, even if it properly gets applied...correct?

    @arfish everything looks the way it should, and I can add methods to the OnClick event at runtime via the inspector and they fire off properly.
     
  9. mcbauer

    mcbauer

    Joined:
    Oct 10, 2015
    Posts:
    524
    I'm pulling together a repo now
     
  10. mcbauer

    mcbauer

    Joined:
    Oct 10, 2015
    Posts:
    524
    So made a new repo, and built it up from scratch, and it works as expected.

    Then I went back into my project and did the same thing, only this time using the Button prefab I was using before.
    Same crash.

    Built a simple button and now it works.

    The only difference between the 2 buttons is I am using Modern Procedural UI Kit plugin. So for now, I'm marking this as closed.
     
  11. ziyadedris

    ziyadedris

    Joined:
    Mar 11, 2021
    Posts:
    8
    I had the same problem and error, I'm also using AddListener and I have the button as a prefab. All I needed to do to fix it was go to the button prefab, find the button component, find the onClick variable and selecting any random object here: upload_2022-12-27_20-37-52.png don't select a function though. In my case I replaced the None with the button itself and it started working. So it looked like this: upload_2022-12-27_20-42-12.png

    Such a weird error with such a weird fix, and took me soo much time to figure out.

    Thanks
     

    Attached Files: