Generating Buttons Failing to Add Listener

Ok, I am stumped on this one. I’ve looked through many examples and cannot figure out what is going wrong with this one… so it’s probably something simple to make me look bad :eyes:

I am attempting to generate a grid of buttons on a panel and add a listener to each button. Ideally I want to make it so that each button will change color when selected, but I’d be happy with just a debug output at this point.

I started by creating a button prefab, emptied the text (the text object is still there, just empty), and made it a square. Then I attached it to my script along with a panel I created. (script below) I am seeing the grid of the buttons like I want, but I cannot get them to trigger the listener.

Anyone know what I’m doing wrong here? Any help would be much appreciated!

using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class SetupBoard : MonoBehaviour
{
    [SerializeField]
    private GameObject _cellPrefab;

    [SerializeField]
    private RectTransform _panel;

    [SerializeField]
    private float _rez = 10;

    [SerializeField]
    private float _buffer = 0.1f;

    // Start is called before the first frame update
    void Start()
    {
        Vector2 panelOffset = new Vector2(_panel.rect.width / 2, _panel.rect.height / 2);
        for(int x=0; x<_rez; x++)
        {
            for(int y=0; y<_rez; y++)
            {
                GameObject cell = (GameObject)Instantiate(_cellPrefab);
                cell.transform.SetParent(_panel, false);
                Vector3 cellSize = new Vector3(_panel.sizeDelta.x/_rez/100, _panel.sizeDelta.y/_rez/100, 1f);
                cell.transform.localScale = cellSize;
                cell.transform.localPosition = new Vector3(
                    x*((cellSize.x*100)+_buffer) - panelOffset.x,
                    y*((cellSize.y*100)+_buffer) - panelOffset.y,
                    0f);
                cell.GetComponent<Button>().onClick.AddListener(() => OnCellClick(x, y));
            }
        }
    }

    void OnCellClick(int x, int y)
    {
        Debug.Log("Cell (" + x + "," + y + ") selected");
    }

    // Update is called once per frame
    void Update()
    {

    }
}

Alas, because of variable capture, all of your delegates read as:

()=>OnCellClick(_rez,_rez);

In C# the delegate captures the variable at invocation of delegate, not at creation of delegate.

To fix, make two other temp vars inside your loop (even right before the delegate creation really):

int tempX = x;
int tempY = y;

Then make your delegate using those temp local vars. That will freeze the values because each time through the loop, those tempX/Y vars are a whole brand new variable that get x and y assigned to them.

That’s good to know. The problem is though that it’s not even getting that far. OnCellClick is never getting called when I run the scene and start clicking cells.

Figure out if the button is even touched: make a silly script that goes on the button and is hard wired in the inspector and it prints out “ping!” in the log.

Or make the button a default button so you can see it glow when touched. Is it being touched?

If it’s being touched and the hard-wired delegate is being called, put debug.log calls in the loop above that adds the soft-wired listeners. Is that code even running?

Etc, etc., Unity is really only 10% coding, the other 90% is scene and prefab setup.