Can you help me solve this ArgumentOutOfRangeException?

I just added a weapon room which should appear in a random spot in a sequence of randomly generated rooms.

The 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 <567df3e0919241ba98db88bec4c6696f>:0)
System.ThrowHelper.ThrowArgumentOutOfRangeException () (at <567df3e0919241ba98db88bec4c6696f>:0)
System.Collections.Generic.List`1[T].get_Item (System.Int32 index) (at <567df3e0919241ba98db88bec4c6696f>:0)
LevelGenerator.Start () (at Assets/Scripts/LevelGenerator.cs:87)

The error is happening at this line:
weaponRoom = layoutRoomObjects[weaponRoomSelector];

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class LevelGenerator : MonoBehaviour
{

    public GameObject layoutRoom;

    public Color startColor, endColor, shopColor, weaponRoomColor;

    public int distanceToEnd;
    public bool includeShop;
    public int minDistanceToShop, maxDistanceToShop;

    public bool includeWeaponRoom;
    public int minDistanceToWeaponRoom, maxDistanceToWeaponRoom;

    public Transform generatorPoint;

    public enum Direction { up, right, down, left};

    public Direction selectedDirection;

    public float xOffset = 18, yOffset = 10f;

    public LayerMask whatIsRoom;

    private GameObject endRoom, shopRoom, weaponRoom;

    private List<GameObject> layoutRoomObjects = new List<GameObject>();

    public RoomPrefabs rooms;

    private List<GameObject> generatedOutlines = new List<GameObject>();

    public RoomCenter centerStart, centerEnd, centerShop, centerWeaponRoom;
    public RoomCenter[] potentialCenters;

    // Start is called before the first frame update
    void Start()
    {
        Instantiate(layoutRoom, generatorPoint.position, generatorPoint.rotation).GetComponent<SpriteRenderer>().color = startColor;

        selectedDirection = (Direction)Random.Range(0, 4);

        MoveGenerationPoint();

        for (int i = 0; i < distanceToEnd; i++)
        {
            GameObject newRoom = Instantiate(layoutRoom, generatorPoint.position, generatorPoint.rotation);

            layoutRoomObjects.Add(newRoom);

            if(i + 1 == distanceToEnd)
            {
                newRoom.GetComponent<SpriteRenderer>().color = endColor;

                layoutRoomObjects.RemoveAt(layoutRoomObjects.Count - 1);
              
                endRoom = newRoom;
          
            }

            selectedDirection = (Direction)Random.Range(0, 4);
            MoveGenerationPoint();

            while(Physics2D.OverlapCircle(generatorPoint.position, .2f, whatIsRoom))
            {
                MoveGenerationPoint();
            }

        }

        if (includeShop)
        {
            int shopSelector = Random.Range(minDistanceToShop, maxDistanceToShop + 1);
            shopRoom = layoutRoomObjects[shopSelector];
            layoutRoomObjects.RemoveAt(shopSelector);
            shopRoom.GetComponent<SpriteRenderer>().color = shopColor;
        }

        if (includeWeaponRoom)
        {
            int weaponRoomSelector = Random.Range(minDistanceToWeaponRoom, maxDistanceToWeaponRoom + 1);
            weaponRoom = layoutRoomObjects[weaponRoomSelector];
            layoutRoomObjects.RemoveAt(weaponRoomSelector);
            weaponRoom.GetComponent<SpriteRenderer>().color = weaponRoomColor;
        }

        //create room outlines
        CreateRoomOutline(Vector3.zero);
        foreach (GameObject room in layoutRoomObjects)
        {
            CreateRoomOutline(room.transform.position);
        }
        CreateRoomOutline(endRoom.transform.position);

        if (includeShop)
        {
            CreateRoomOutline(shopRoom.transform.position);
        }

        if (includeWeaponRoom)
        {
            CreateRoomOutline(weaponRoom.transform.position);
        }

        foreach (GameObject outline in generatedOutlines)
        {
            bool generateCenter = true;

            if(outline.transform.position == Vector3.zero)
            {
                Instantiate(centerStart, outline.transform.position, transform.rotation).theRoom = outline.GetComponent<Room>();
                generateCenter = false;
            }

            if (outline.transform.position == endRoom.transform.position)
            {
                Instantiate(centerEnd, outline.transform.position, transform.rotation).theRoom = outline.GetComponent<Room>();
                generateCenter = false;
            }

            if (includeShop)
            {
                if (outline.transform.position == shopRoom.transform.position)
                {
                    Instantiate(centerShop, outline.transform.position, transform.rotation).theRoom = outline.GetComponent<Room>();
                    generateCenter = false;
                }
            }

            if (includeWeaponRoom)
            {
                if (outline.transform.position == weaponRoom.transform.position)
                {
                    Instantiate(centerWeaponRoom, outline.transform.position, transform.rotation).theRoom = outline.GetComponent<Room>();
                    generateCenter = false;
                }
            }

            if (generateCenter)
            {
                int centerSelect = Random.Range(0, potentialCenters.Length);

                Instantiate(potentialCenters[centerSelect], outline.transform.position, transform.rotation).theRoom = outline.GetComponent<Room>();
            }


        }  

    }

    // Update is called once per frame
    void Update()
    {

#if UNITY_EDITOR
        if (Input.GetKey(KeyCode.R))
        {
            SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        }
#endif
    }

    public void MoveGenerationPoint()
    {
        switch (selectedDirection)
        {
            case Direction.up:
                generatorPoint.position += new Vector3(0f, yOffset, 0f);
                break;

            case Direction.down:
                generatorPoint.position += new Vector3(0f, -yOffset, 0f);
                break;

            case Direction.right:
                generatorPoint.position += new Vector3(xOffset, 0f, 0f);
                break;

            case Direction.left:
                generatorPoint.position += new Vector3(-xOffset, 0f, 0f);
                break;
        }
    }

    public void CreateRoomOutline(Vector3 roomPosition)
    {
        bool roomAbove = Physics2D.OverlapCircle(roomPosition + new Vector3(0f, yOffset, 0f), .2f, whatIsRoom);
        bool roomBelow = Physics2D.OverlapCircle(roomPosition + new Vector3(0f, -yOffset, 0f), .2f, whatIsRoom);
        bool roomLeft = Physics2D.OverlapCircle(roomPosition + new Vector3(-xOffset, 0f, 0f), .2f, whatIsRoom);
        bool roomRight = Physics2D.OverlapCircle(roomPosition + new Vector3(xOffset, 0f, 0f), .2f, whatIsRoom);

        int directionCount = 0;
        if (roomAbove)
        {
            directionCount++;
        }

        if (roomBelow)
        {
            directionCount++;
        }

        if (roomLeft)
        {
            directionCount++;
        }

        if (roomRight)
        {
            directionCount++;
        }

        switch (directionCount)
        {
            case 0:
                Debug.LogError("Found no room exists!");
                break;

            case 1:

                if (roomAbove)
                {
                    generatedOutlines.Add( Instantiate(rooms.singleUp, roomPosition, transform.rotation));
                }

                if (roomBelow)
                {
                    generatedOutlines.Add(Instantiate(rooms.singleDown, roomPosition, transform.rotation));
                }

                if (roomLeft)
                {
                    generatedOutlines.Add(Instantiate(rooms.singleLeft, roomPosition, transform.rotation));
                }

                if (roomRight)
                {
                    generatedOutlines.Add(Instantiate(rooms.singleRight, roomPosition, transform.rotation));
                }

                break;

            case 2:
                if(roomAbove && roomBelow)
                {
                    generatedOutlines.Add(Instantiate(rooms.doubleUpDown, roomPosition, transform.rotation));
                }

                if (roomLeft && roomRight)
                {
                    generatedOutlines.Add(Instantiate(rooms.doubleLeftRight, roomPosition, transform.rotation));
                }

                if (roomAbove && roomRight)
                {
                    generatedOutlines.Add(Instantiate(rooms.doubleUpRight, roomPosition, transform.rotation));
                }

                if (roomBelow && roomRight)
                {
                    generatedOutlines.Add(Instantiate(rooms.doubleDownRight, roomPosition, transform.rotation));
                }

                if (roomBelow && roomLeft)
                {
                    generatedOutlines.Add(Instantiate(rooms.doubleDownLeft, roomPosition, transform.rotation));
                }

                if (roomAbove && roomLeft)
                {
                    generatedOutlines.Add(Instantiate(rooms.doubleUpLeft, roomPosition, transform.rotation));
                }

                break;


            case 3:

                if (roomAbove && roomBelow && roomRight)
                {
                    generatedOutlines.Add(Instantiate(rooms.tripleUpDownRight, roomPosition, transform.rotation));
                }

                if (roomBelow && roomLeft && roomRight)
                {
                    generatedOutlines.Add(Instantiate(rooms.tripleDownLeftRight, roomPosition, transform.rotation));
                }

                if (roomAbove && roomBelow && roomLeft)
                {
                    generatedOutlines.Add(Instantiate(rooms.tripleUpDownLeft, roomPosition, transform.rotation));
                }

                if (roomAbove && roomLeft && roomRight)
                {
                    generatedOutlines.Add(Instantiate(rooms.tripleUpLeftRight, roomPosition, transform.rotation));
                }

                break;

            case 4:

                if (roomAbove && roomBelow && roomLeft && roomRight)
                {
                    generatedOutlines.Add(Instantiate(rooms.quad, roomPosition, transform.rotation));
                }
                break;
        }
    }
}

[System.Serializable]
public class RoomPrefabs
{
    public GameObject singleUp, singleRight, singleLeft, singleDown,
        doubleUpDown, doubleLeftRight, doubleUpRight, doubleDownRight, doubleDownLeft, doubleUpLeft,
        tripleUpDownRight, tripleDownLeftRight, tripleUpDownLeft, tripleUpLeftRight,
        quad;
}

It’s this right here (check your line number in your error):

        int weaponRoomSelector = Random.Range(minDistanceToWeaponRoom, maxDistanceToWeaponRoom + 1);
        weaponRoom = layoutRoomObjects[weaponRoomSelector];

The value coming back from Random.Range is either < 0, or >= layoutRoomObjects.Count.

I don’t know what minDistanceToWeaponRoom and maxDistanceToWeaponRoom are exactly… but that’s your culprit.

I do notice you have a +1 to max, this reminds me of how MOST rng’s have their Range method min inclusive, max exclusive. And so one would have to add 1 to the max to include that max.

Thing is Unity’s implementation of Random.Range is NOT max exclusive, and is instead max inclusive:

So keep that in mind if you have that +1 for that reason.

Beg to differ Sir Lord… it’s actually BOTH!

The int flavor is exclusive at the top end, the float flavor is inclusive:

https://docs.unity3d.com/ScriptReference/Random.Range.html

OP: since your args are integers, then it will return up to but NOT including the upper integer.

OP: one more common thing to overlook is an array with zero elements, because no matter what you try to dereference it with (even zero) will throw an out-of-range exception.

And the easiest way to prove something like this is failing is to print both the argument you are using to index the array as well as the count / length of the array in the line immediately preceding where you see the bug.

So to clarify I have it set up in the inspector as
minDistanceToWeaponRoom = 6
maxDistanceToWeaponRoom = 8

The +1 ensures that it is inclusive of the 8.

It’s just the most peculiar thing and I’m not sure how to even debug this. Oddly, everything is showing up as black, which tells me something is up with the reveal of the minimap (which is covered by a black image that is removed piece by piece when entering each room).

That’s the
public GameObject layoutRoom;
near the top of the script.

But then what does that have to do with the Random.Range issue? I’m so perplexed.

The intent is definitely for it to be inclusive, hence the +1 (see my new response above).

I stand corrected. huh.

Even MORE confusion from Unity. Thanks Unity!

what is the value of layoutRoomObjects.Count, though? Remember that if the Count is 8, then the maximum index can only be 7.

First off, GREAT profile photo.

Second, what’s more important than the layoutRoomObjects.Count is the int distanceToEnd, which determines the count. I have distanceToEnd set in the inspector as 10.

I understand that’s the intent, but it weaponRoomSelector was really a number between 6 and 9 and LayoutRoomObjects.Count was really 10 than you shouldn’t be getting an error message. You should use debug.log to be sure what that all of these values are what they are supposed to be.

Well I adjusted the numbers in the inspector by dropping them down by one each. This seems to have done the job for now, but I’ll check back in if I have any more issues.

Thanks for helping me understand!