Why does the onClick.AddListener() in Unity doesn't work while trying to loop through items in a list

Viewed 41

I am currently trying to build a shop for my game. The inventory is a list that will be displayed on screen. As I want every item of that list to be clickable, I add a Button component as well as an onClick.Addlistener(method), but see yourself:

for (int i = 0; i < inventoryT1.Container.Count; i++)
        {

            GameObject obj = Instantiate(inventoryT1.Container[i].item.DefaultPrefab, Vector3.zero, Quaternion.identity, transform);
            obj.GetComponent<RectTransform>().localPosition = GetPosition(i);
            obj.GetComponentInChildren<TextMeshProUGUI>().text = inventoryT1.Container[i].level.ToString();

            obj.GetComponent<Button>().onClick.AddListener(delegate { LoadPrisonerStore(inventoryT1.Container[i-1].item); });


        }

public void LoadPrisonerStore(PrisonerObject _prisObj)
    {
        //Updating the UI
        DescriptionForMenu.text = _prisObj.description;

        //Activating/Deactivating the panels
        ShopPrisonerContainer.SetActive(false);
        PrisonerPreviewContainer.SetActive(true);
    }

The inventoryT1 is a list of items and with the AddListener, I want to load the data of the item that is clicked on with the LoadPrisonerStore(PrisonerObject _prisObj) Method. The Problem that I'm having is that every Object that is created will only load data of the very last Object. Why is that and how can i fix this?

I also tried to just link the object with another Method after the AddListener() and this worked perfectly, but unfortunately I can't access the items data from it:

obj.GetComponent<Button>().onClick.AddListener(() => ReturnObject(obj)); 

Do you have any idea how I can fix this?

2 Answers

You should cache the index value before using it inside the anonymous function

int cachedIndex = i;
obj.GetComponent<Button>().onClick.AddListener(delegate { LoadPrisonerStore(inventoryT1.Container[cachedIndex -1].item); });

You can use while loop insted of for and write it something like this :

    int i = 0;
    while(i < inventoryT1.Container.Count)
        {

           int copyOfi = i;

            GameObject obj = Instantiate(inventoryT1.Container[i].item.DefaultPrefab, Vector3.zero, Quaternion.identity, transform);
            obj.GetComponent<RectTransform>().localPosition = GetPosition(i);
            obj.GetComponentInChildren<TextMeshProUGUI>().text = inventoryT1.Container[i].level.ToString();

            ***obj.GetComponent<Button>().onClick.AddListener(delegate { LoadPrisonerStore(inventoryT1.Container[copyOfi-1].item); });***

                 i++;
        }

       

Hope this solves the problem.

Related