Search code examples
c#unity-game-engineuser-interface

How do I make multiple Unity buttons with UnityActions that depend on a variable?


I am trying to instantiate multiple buttons in Unity. Each button has a UnityAction attached to it - on click it should call a function PlayLevel which depends on an int.

for (int i = 1; i <= 5; i++)
{
    GameObject button = Instantiate(buttonPrefab, buttonParent.transform);

    UnityAction action = new UnityAction(() => PlayLevel(i));
    button.GetComponent<UnityEngine.UI.Button>().onClick.AddListener(action);
    
}

buttonPrefab is an already assigned prefab dictating how the button should look, and buttonParent.transform is the parent object, again already assigned.

When I click any of the buttons, they all call PlayLevel with the parameter 6. It seems the UnityAction is not per object and is being reassigned each time i is changed, all the actions change.

How may I get this to work correctly?


Solution

  • There are two problems. First, new UnityAction(() => Play Level(i)) This is the lambda method that our friend mentioned

    Second, the ring works incorrectly

    For the first problem, we create a separate function to send UnityAction

    public UnityAction GetUnityAction(int _lvl) => new UnityAction(() => { PlayLevel(_lvl); });
    

    Second, you have changed the step count variable of the loop you wrote, you can change it to this loop

    levelNumber = 5;
    for (int i = 1; i <= levelNumber; i++)
    

    This loop navigates from level 1 to the level you want. It can be changed depending on the variable.

    Final code:

    int levelNumber = 5;
    
    public void SetButtons()
    {
        for (int i = 1; i <= levelNumber; i++)
        {
            GameObject button = Instantiate(buttonPrefab, buttonParent.transform);
            button.GetComponent<UnityEngine.UI.Button>().onClick.AddListener(GetAction(i));
        }
    }
    
    public UnityAction GetAction(int _lvl) => new UnityAction(() => { PlayLevel(_lvl); });