Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question ArgumentOutOfRangeException: Index was out of range.

Discussion in 'Editor & General Support' started by uddhavjindal2001, Dec 11, 2022.

  1. uddhavjindal2001

    uddhavjindal2001

    Joined:
    Jun 23, 2022
    Posts:
    2
    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4.  
    5. public class ButtonManager : MonoBehaviour
    6. {
    7.     #region Variables
    8.     [Header("Scroll Settings")]
    9.     [SerializeField] private Scrollbar scrollbarHorizontal;
    10.  
    11.     [Header("Buttons Reference")]
    12.     [SerializeField] private GameObject bottomPanel;
    13.  
    14.     private List<Button> bottomPanelButtonsList = new();
    15.     private List<float> scrollbarValuesList = new();
    16.  
    17.     private float listCount;
    18.  
    19.     private const float scrollbarValueForShop = 0f;
    20.     private const float scrollbarValueForLeaderboard = 0.25f;
    21.     private const float scrollbarValueForHome = 0.5f;
    22.     private const float scrollbarValueForFriends = 0.75f;
    23.     private const float scrollbarValueForSettings = 1;
    24.     #endregion
    25.  
    26.     #region In-Built Functions
    27.     private void Awake()
    28.     {
    29.         scrollbarHorizontal.value = scrollbarValueForHome;  //To always start from Home
    30.  
    31.         PopulateButtonList();
    32.         PopulateScrollbarValueList();
    33.         //AddListenerToButtons();
    34.     }
    35.  
    36.     private void Start()
    37.     {
    38.         //AddListenerToButtons();
    39.         OnButtonClick();
    40.     }
    41.     #endregion
    42.  
    43.     #region Custom Functions
    44.     private void PopulateButtonList()
    45.     {
    46.         if (bottomPanelButtonsList != null)
    47.         {
    48.             bottomPanelButtonsList.AddRange(bottomPanel.GetComponentsInChildren<Button>());
    49.             Debug.Log("Button List Populated");
    50.         }
    51.         else
    52.         {
    53.             bottomPanelButtonsList = new();
    54.         }
    55.     }
    56.  
    57.     private void PopulateScrollbarValueList()
    58.     {
    59.         if (scrollbarValuesList != null)
    60.         {
    61.             scrollbarValuesList.Add(scrollbarValueForShop);
    62.             scrollbarValuesList.Add(scrollbarValueForLeaderboard);
    63.             scrollbarValuesList.Add(scrollbarValueForHome);
    64.             scrollbarValuesList.Add(scrollbarValueForFriends);
    65.             scrollbarValuesList.Add(scrollbarValueForSettings);
    66.             Debug.Log("Float List Populated");
    67.         }
    68.         else
    69.         {
    70.             scrollbarValuesList = new();
    71.         }
    72.     }
    73.  
    74.     private void OnButtonClick()
    75.     {
    76.         if (bottomPanelButtonsList.Count == scrollbarValuesList.Count)
    77.         {
    78.             listCount = bottomPanelButtonsList.Count;
    79.             Debug.Log($"{listCount}");  //5
    80.             for (int i = 0; i < listCount; i++)
    81.             {
    82.                 //bottomPanelButtonsList[0].onClick.AddListener(() => scrollbarHorizontal.value = scrollbarValuesList[0]);
    83.                 //bottomPanelButtonsList[1].onClick.AddListener(() => scrollbarHorizontal.value = scrollbarValuesList[1]);
    84.                 //bottomPanelButtonsList[2].onClick.AddListener(() => scrollbarHorizontal.value = scrollbarValuesList[2]);
    85.                 //bottomPanelButtonsList[3].onClick.AddListener(() => scrollbarHorizontal.value = scrollbarValuesList[3]);
    86.                 //bottomPanelButtonsList[4].onClick.AddListener(() => scrollbarHorizontal.value = scrollbarValuesList[4]);
    87.  
    88.                 bottomPanelButtonsList[i].onClick.AddListener(() => scrollbarHorizontal.value = scrollbarValuesList[i]);
    89.             }
    90.         }
    91.     }
    92.     #endregion
    93. }
    94.  
    Error Message:
    ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
    Parameter name: index
    System.Collections.Generic.List`1[T].get_Item (System.Int32 index) (at <9aad1b3a47484d63ba2b3985692d80e9>:0)
    ButtonManager+<>c__DisplayClass14_0.<OnButtonClick>b__0 () (at Assets/Scripts/ButtonManager.cs:88)
    UnityEngine.Events.InvokableCall.Invoke () (at <86acb61e0d2b4b36bc20af11093be9a5>:0)
    UnityEngine.Events.UnityEvent.Invoke () (at <86acb61e0d2b4b36bc20af11093be9a5>:0)
    UnityEngine.UI.Button.Press () (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:70)
    UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:114)
    UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:57)
    UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction`1[T1] functor) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:272)
    UnityEngine.EventSystems.EventSystem:Update() (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:501)
     
  2. tomfulghum

    tomfulghum

    Joined:
    May 8, 2017
    Posts:
    69
    A lambda expression captures a variable, not the value it holds when the lambda is created. In this case, after the loop runs, the value of i is 5. Therefore, every onClick listener you add uses the index 5 to access scrollbarValuesList when invoked, which obviously throws an error since it's out of range. To fix this, you need to create a local copy of i for every iteration and use it instead of i in the lambda.

    Code (CSharp):
    1.     private void OnButtonClick()
    2.     {
    3.         if (bottomPanelButtonsList.Count == scrollbarValuesList.Count)
    4.         {
    5.             listCount = bottomPanelButtonsList.Count;
    6.             for (int i = 0; i < listCount; i++)
    7.             {
    8.                 int local = i;
    9.                 bottomPanelButtonsList[i].onClick.AddListener(() => scrollbarHorizontal.value = scrollbarValuesList[local]);
    10.             }
    11.         }
    12.     }
     
  3. uddhavjindal2001

    uddhavjindal2001

    Joined:
    Jun 23, 2022
    Posts:
    2
    How do you use DoTween for ScrollReact?