0

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?

Josh
  • 17
  • 3

2 Answers2

1

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); });
Yuri
  • 46
  • 6
-1

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.

Omkar P
  • 29
  • 5
  • This code will not work. It is endless loop. You don't need to change the loop type. The problem is only in `i` capturing. – Nikolai Sep 16 '22 at 11:30
  • @Nikolay I have done the some capturing method my making it copy of i and using the copy into delegate something like this -> *obj.GetComponent – Omkar P Sep 16 '22 at 11:39
  • I uderstnad. But it doesn't chage the fact that the code above contains infinite loop, and variable capturing in C# has nothing common with loop types. – Nikolai Sep 16 '22 at 11:45
  • @Nikolay Hope it works now, I have changed the code. – Omkar P Sep 16 '22 at 11:51
  • 1
    @OmkarP maybe it works now ... but still how is this any less complex than the original `for` loop? Why introduce an additional variable out of the scope and later potentially forget to increase it if the for loop had already covered that in a cleaner way? – derHugo Sep 16 '22 at 14:03
  • 1
    caching i worked perfectly fine for me – Josh Sep 16 '22 at 18:20