Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

How do I detect the index of a button in a list when clicked using AddListener?

Discussion in 'Scripting' started by The702Guy1, Jun 2, 2022.

  1. The702Guy1

    The702Guy1

    Joined:
    Apr 24, 2022
    Posts:
    48
    I'm sure my brain is just fried because its late, but having trouble with this one. I have a group of buttons in a list and basically I want to call a function using a the index of the button pressed. How can I get the index of a button pressed when it is clicked and use it as a variable using AddListener?

    Edited for clarity.
     
    Last edited: Jun 2, 2022
  2. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,192
  3. The702Guy1

    The702Guy1

    Joined:
    Apr 24, 2022
    Posts:
    48
    Apologies, should have been a little more clear. I want to get the index of a button in a list of buttons when it is clicked by the user and log that index as a variable that will then be immediately used to call a function. I figured AddListener is the way to go but I'm struggling implementing it
     
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    8,192
    Define 'list of buttons', because when you say that in a scripting context we think
    List<Button> listOfButtons;
    , but do you mean a list of buttons in the scene hierarchy?
     
  5. The702Guy1

    The702Guy1

    Joined:
    Apr 24, 2022
    Posts:
    48
    Correct I do mean it in the scripting context.
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,033
    Here is a totally dynamic approach to creating buttons and accessing them in useful relevant ways.

    It could easily be adapted to support an index.
     

    Attached Files:

  7. R1PFake

    R1PFake

    Joined:
    Aug 7, 2015
    Posts:
    551
    I assume you use the click event, which doesn't pass any parameter? In that case you could capture the index with a lambda

    Warning pseudo code, might contain syntax errors:

    Code (CSharp):
    1. for(var i = 0; i < yourButtonList.Count; ++i)
    2. {
    3.     var capturedButtonIndex = i;
    4.     yourButtonList[i].onClick.AddListener(() => { Debug.Log(capturedButtonIndex); });
    5. }
     
    Mo_Zarara and Bunny83 like this.
  8. Hozgen90

    Hozgen90

    Joined:
    Jan 20, 2021
    Posts:
    19
    you can also assign button index number with a script manually.
     
  9. KRUM3

    KRUM3

    Joined:
    Mar 2, 2019
    Posts:
    5
    I tried that and it prints the last value that "i" was so it doesn't work. If I have 8 buttons it always prints 8. I don't know why but that's what happens.
     
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,033
    Then you have failed to copy the code properly.

    The code you even quoted in your message does NOT print
    i
    , it prints
    capturedButtonIndex
    :

    Code (csharp):
    1. Debug.Log(capturedButtonIndex);
    Please don't necro-post. If you have a new question, make a new post. It's FREE!!

    How to report your problem productively in the Unity3D forums:

    http://plbm.com/?p=220

    This is the bare minimum of information to report:

    - what you want
    - what you tried
    - what you expected to happen
    - what actually happened, log output, variable values, and especially any errors you see
    - links to actual Unity3D documentation you used to cross-check your work (CRITICAL!!!)

    The purpose of YOU providing links is to make our job easier, while simultaneously showing us that you actually put effort into the process. If you haven't put effort into finding the documentation, why should we bother putting effort into replying?
     
  11. Nad_B

    Nad_B

    Joined:
    Aug 1, 2021
    Posts:
    730
    Yes you need to capture the value of i (i.e. create a snapshot at that exact moment) into a new variable and use it instead of i, or else all the callbacks will use the same i (a reference), which of course will end up having the last value assigned when the loop ends. Don't forget that when you write a lambda (
    () =>
    ) the code inside it will not run right away, but somewhere in the future when the method that asks for that lambda decides to. And if your lambda access anything outside it (in this case i), it becomes what's called a Closure, and a new object is created under the hood that holds references to all the external variables so the lambda can work properly. The keyword here is reference. And this is the reason why Closures (i.e. lambdas that captures external objects) allocate memory.

    It's important to understand all of this (i.e. Scopes) to avoid having weird behaviors, bugs and ultimately headaches.
     
    Last edited: Apr 14, 2024