[Solved] Index was out of range. Must be non-negative and less than the size of the collection.

Good day everyone. I’m still fairly new to unity and C#, and as my very first game I have been working on creating a visual memory card game.

I wanted to implement a restart button in my game that would reset the score count, however whenever I try to click on something in the scene that is NOT a card (e.g the game board or the restart button), I’m faced with an error, and I’m not sure what exactly is wrong with my code.

This is the part of my code in which I’m getting the error at:

    public Sprite board;

    public GameObject token;

    List<int> frontIndexes = new List<int>() { 0, 1, 2, 3, 0, 1, 2, 3 };

    public static System.Random random = new System.Random();
    public int shuffleNumber;
    int[] visibleFaces = { -1, -2 };

    SpriteRenderer spriteRenderer;

    void OnMouseDown()
    {
        int originalLength = frontIndexes.Count;
        float yPosition = 2.3f;
        float xPosition = -2.2f;

        if (spriteRenderer.sprite == board)
        {

            //creating this for loop in order to generate more clones
            for (int i = 0; i < 7; i++)
            {
                shuffleNumber = random.Next(0, frontIndexes.Count);
                Debug.Log(shuffleNumber);
                var temp = Instantiate(token, new Vector3(xPosition, yPosition, 0f),
                            Quaternion.identity);

                temp.GetComponent<FlippingCard>().frontIndex = frontIndexes[shuffleNumber];
                frontIndexes.Remove(frontIndexes[shuffleNumber]);

                xPosition = xPosition + 4;
                if (i == (originalLength/2 - 2))
                {
                    yPosition = -2.3f;
                    xPosition = -6.2f;
                }

            }
            token.GetComponent<FlippingCard>().frontIndex = frontIndexes[0];
        }
    }

The error I get is on this line, where it says:temp.GetComponent<FlippingCard>().frontIndex = frontIndexes[shuffleNumber];

Error:

 ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
System.ThrowHelper.ThrowArgumentOutOfRangeException (System.ExceptionArgument argument, System.ExceptionResource resource) (at <9577ac7a62ef43179789031239ba8798>:0)
System.ThrowHelper.ThrowArgumentOutOfRangeException () (at <9577ac7a62ef43179789031239ba8798>:0)
System.Collections.Generic.List`1[T].get_Item (System.Int32 index) (at <9577ac7a62ef43179789031239ba8798>:0)
MakeVisible.OnMouseDown () (at Assets/Scripts/MakeVisible.cs:36)

I’ve been trying to fix it but I was unable to come up with a solution. I’d really appreciate the help!

The problem is: shuffleNumber = random.Next(0, frontIndexes.Count);

change it to: shuffleNumber = random.Next(0, frontIndexes.Count - 1);

It´s important to know, that a index (of a list or array or whatever) always starts with 0, while count gives you the total amount of values and starts with 1. So the index is always Count - 1.

For your code: The amount of values in your list “frontIndexes” is 8, but the index range is from 0-7.

I was going to write the same, but C# Random.Next(Int, Int) documentation notes that the maxValue is exclusive. So that should not be the problem. https://docs.microsoft.com/en-us/dotnet/api/system.random.next?view=netcore-3.1

Change your line 26 to this and tell us what it says before the error:

Debug.Log("Current Index: " + shuffleNumber + " , Max Allowed Index: " + (frontIndexes.Count - 1));

Oh ok, didn´t check that before, thanks very much for the hint.

So let´s see what the console output says then :slight_smile:

Okay so I did this, and when I run my game and try to click on, let’s say the background instead of a card, this is my output:
Current Index: 0 , Max Allowed Index: -1
UnityEngine.Debug:Log(Object)
MakeVisible:OnMouseDown() (at Assets/Scripts/MakeVisible.cs:32)
UnityEngine.SendMouseEvents:smile:oSendMouseEvents(Int32)

And then I get the same index out of range error.

Ok, so your list is always empty.

I´m not sure if this works: List<int> frontIndexes = new List<int>() { 0, 1, 2, 3, 0, 1, 2, 3 };

I´m not sure, if a list can be filled like that or if that only works for arrays.

I Created that list in order to check if two cards match when they’re faced up, and it seems to work fine except when I try to click the restart button, or even the background, I get the out of index range error. :frowning: I don’t get this error when I click on the cards.

Could it be, that your event “OnMouseDown” is fired if you click on any place, but your script is not fully loaded (the values for them are not set) ?

Can you try to add the code of line 5 into the OnMouseDown (just move it to line 15) ?

1 Like

The list is empty because you remove the elements. You never re-add them!
At the end of your OnMouseDown you need to fill it / reset it to its original state again.

Edit: It’s probably best to create a temporary list inside of your function which is a copy of your original list. Then you can do with that whatever you want, without any effect on the following function calls.
Or, since the list is hardcoded anyways, do what @Sphinks told you and just declare it inside the function.

2 Likes

oh. my. god. THIS DID IT!!! I’ve been struggling on how to fix it for DAYS and all I had to do was move it inside… thank you, thank you so much! and thanks to @Yoreki for helping out too! big big thanks! :smile:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Pathfinding;

public class EnemyAI : MonoBehaviour
{
    public Transform target;
    public float updateRate = 2f;

    private Seeker seeker;
    private Rigidbody2D rb;

    public Path path;
    public float speed = 300f;
    public ForceMode2D fmode;
    [HideInInspector]
    public bool pathIsEnded = false;

    public float nextwaypointDistance = 3;
   
    private int currentWayPoint = 0;

    Vector2 movement;
    public Transform enemy;

    void Start()
    {
        seeker = GetComponent<Seeker>();
        rb = GetComponent<Rigidbody2D>();

        if (target == null)
        {
            Debug.LogError("Panic! Panic!");
            return;
        }
        seeker.StartPath(transform.position, target.position, OnPathComplete);

        StartCoroutine(Updatepath());

    }

    IEnumerator Updatepath()
    {
        seeker.StartPath(transform.position, target.position, OnPathComplete);

        yield return new WaitForSeconds(1f / updateRate);
        StartCoroutine(Updatepath());

    }

    public void OnPathComplete(Path p)
    {
        //Debug.Log("We got a path. Did it have an error ?" + p.error);
        if(!p.error)
        {
            path = p;
            currentWayPoint = 0;
        }
    }

    void FixedUpdate()
    {
        if (target == null)
        {
            return;
        }

        Vector3 lookDir = enemy.position - transform.position;
        float angle = Mathf.Atan2(lookDir.y, lookDir.x) * Mathf.Rad2Deg - 90f;
        rb.rotation = angle;
        lookDir.Normalize();
        movement = lookDir;

        if (path == null) return;

        if (currentWayPoint >= path.vectorPath.Count)
        {
            if (pathIsEnded) return;

            Debug.Log("End of path reached");

            pathIsEnded = true;
        }

        pathIsEnded = false;

        Vector3 dir = (path.vectorPath[currentWayPoint] - transform.position).normalized;
        dir *= speed * Time.fixedDeltaTime;

        rb.AddForce(dir, fmode);

        float dist = Vector3.Distance(transform.position, path.vectorPath[currentWayPoint]);
        if (dist < nextwaypointDistance)
        {
            currentWayPoint++;
            return;
        }


    }




} //class

Same problem here;
ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
System.ThrowHelper.ThrowArgumentOutOfRangeException (System.ExceptionArgument argument, System.ExceptionResource resource) (at <695d1cc93cca45069c528c15c9fdd749>:0)
System.ThrowHelper.ThrowArgumentOutOfRangeException () (at <695d1cc93cca45069c528c15c9fdd749>:0)
EnemyAI.FixedUpdate () (at Assets/Scripts/EnemyAI.cs:101)

What should i do?

Create your own thread. The same error doesn’t mean it’s the same problem or related to an existing thread.

The answer to what this means can be found with a quick search though! Search for “ArgumentOutOfRange” on Google. An array or collection has a size, you specify what you want by index but I guess you know this as it’s used in the code above. If the index is out of those bounds you get this. Pretty simple. It’s now your job to look at why this is. Line 101 above is an empty line so doesn’t relate to the error you posted so you’ve modified it in relation to the error.

2 Likes