Search Unity

Can you help me solve this ArgumentOutOfRangeException?

Discussion in 'Scripting' started by jleven22, Jan 14, 2020.

  1. jleven22

    jleven22

    Joined:
    Mar 26, 2019
    Posts:
    421
    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];

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.SceneManagement;
    5.  
    6. public class LevelGenerator : MonoBehaviour
    7. {
    8.  
    9.     public GameObject layoutRoom;
    10.  
    11.     public Color startColor, endColor, shopColor, weaponRoomColor;
    12.  
    13.     public int distanceToEnd;
    14.     public bool includeShop;
    15.     public int minDistanceToShop, maxDistanceToShop;
    16.  
    17.     public bool includeWeaponRoom;
    18.     public int minDistanceToWeaponRoom, maxDistanceToWeaponRoom;
    19.  
    20.     public Transform generatorPoint;
    21.  
    22.     public enum Direction { up, right, down, left};
    23.  
    24.     public Direction selectedDirection;
    25.  
    26.     public float xOffset = 18, yOffset = 10f;
    27.  
    28.     public LayerMask whatIsRoom;
    29.  
    30.     private GameObject endRoom, shopRoom, weaponRoom;
    31.  
    32.     private List<GameObject> layoutRoomObjects = new List<GameObject>();
    33.  
    34.     public RoomPrefabs rooms;
    35.  
    36.     private List<GameObject> generatedOutlines = new List<GameObject>();
    37.  
    38.     public RoomCenter centerStart, centerEnd, centerShop, centerWeaponRoom;
    39.     public RoomCenter[] potentialCenters;
    40.  
    41.     // Start is called before the first frame update
    42.     void Start()
    43.     {
    44.         Instantiate(layoutRoom, generatorPoint.position, generatorPoint.rotation).GetComponent<SpriteRenderer>().color = startColor;
    45.  
    46.         selectedDirection = (Direction)Random.Range(0, 4);
    47.  
    48.         MoveGenerationPoint();
    49.  
    50.         for (int i = 0; i < distanceToEnd; i++)
    51.         {
    52.             GameObject newRoom = Instantiate(layoutRoom, generatorPoint.position, generatorPoint.rotation);
    53.  
    54.             layoutRoomObjects.Add(newRoom);
    55.  
    56.             if(i + 1 == distanceToEnd)
    57.             {
    58.                 newRoom.GetComponent<SpriteRenderer>().color = endColor;
    59.  
    60.                 layoutRoomObjects.RemoveAt(layoutRoomObjects.Count - 1);
    61.              
    62.                 endRoom = newRoom;
    63.          
    64.             }
    65.  
    66.             selectedDirection = (Direction)Random.Range(0, 4);
    67.             MoveGenerationPoint();
    68.  
    69.             while(Physics2D.OverlapCircle(generatorPoint.position, .2f, whatIsRoom))
    70.             {
    71.                 MoveGenerationPoint();
    72.             }
    73.  
    74.         }
    75.  
    76.         if (includeShop)
    77.         {
    78.             int shopSelector = Random.Range(minDistanceToShop, maxDistanceToShop + 1);
    79.             shopRoom = layoutRoomObjects[shopSelector];
    80.             layoutRoomObjects.RemoveAt(shopSelector);
    81.             shopRoom.GetComponent<SpriteRenderer>().color = shopColor;
    82.         }
    83.  
    84.         if (includeWeaponRoom)
    85.         {
    86.             int weaponRoomSelector = Random.Range(minDistanceToWeaponRoom, maxDistanceToWeaponRoom + 1);
    87.             weaponRoom = layoutRoomObjects[weaponRoomSelector];
    88.             layoutRoomObjects.RemoveAt(weaponRoomSelector);
    89.             weaponRoom.GetComponent<SpriteRenderer>().color = weaponRoomColor;
    90.         }
    91.  
    92.         //create room outlines
    93.         CreateRoomOutline(Vector3.zero);
    94.         foreach (GameObject room in layoutRoomObjects)
    95.         {
    96.             CreateRoomOutline(room.transform.position);
    97.         }
    98.         CreateRoomOutline(endRoom.transform.position);
    99.  
    100.         if (includeShop)
    101.         {
    102.             CreateRoomOutline(shopRoom.transform.position);
    103.         }
    104.  
    105.         if (includeWeaponRoom)
    106.         {
    107.             CreateRoomOutline(weaponRoom.transform.position);
    108.         }
    109.  
    110.         foreach (GameObject outline in generatedOutlines)
    111.         {
    112.             bool generateCenter = true;
    113.  
    114.             if(outline.transform.position == Vector3.zero)
    115.             {
    116.                 Instantiate(centerStart, outline.transform.position, transform.rotation).theRoom = outline.GetComponent<Room>();
    117.                 generateCenter = false;
    118.             }
    119.  
    120.             if (outline.transform.position == endRoom.transform.position)
    121.             {
    122.                 Instantiate(centerEnd, outline.transform.position, transform.rotation).theRoom = outline.GetComponent<Room>();
    123.                 generateCenter = false;
    124.             }
    125.  
    126.             if (includeShop)
    127.             {
    128.                 if (outline.transform.position == shopRoom.transform.position)
    129.                 {
    130.                     Instantiate(centerShop, outline.transform.position, transform.rotation).theRoom = outline.GetComponent<Room>();
    131.                     generateCenter = false;
    132.                 }
    133.             }
    134.  
    135.             if (includeWeaponRoom)
    136.             {
    137.                 if (outline.transform.position == weaponRoom.transform.position)
    138.                 {
    139.                     Instantiate(centerWeaponRoom, outline.transform.position, transform.rotation).theRoom = outline.GetComponent<Room>();
    140.                     generateCenter = false;
    141.                 }
    142.             }
    143.  
    144.             if (generateCenter)
    145.             {
    146.                 int centerSelect = Random.Range(0, potentialCenters.Length);
    147.  
    148.                 Instantiate(potentialCenters[centerSelect], outline.transform.position, transform.rotation).theRoom = outline.GetComponent<Room>();
    149.             }
    150.  
    151.  
    152.         }  
    153.  
    154.     }
    155.  
    156.     // Update is called once per frame
    157.     void Update()
    158.     {
    159.  
    160. #if UNITY_EDITOR
    161.         if (Input.GetKey(KeyCode.R))
    162.         {
    163.             SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    164.         }
    165. #endif
    166.     }
    167.  
    168.     public void MoveGenerationPoint()
    169.     {
    170.         switch (selectedDirection)
    171.         {
    172.             case Direction.up:
    173.                 generatorPoint.position += new Vector3(0f, yOffset, 0f);
    174.                 break;
    175.  
    176.             case Direction.down:
    177.                 generatorPoint.position += new Vector3(0f, -yOffset, 0f);
    178.                 break;
    179.  
    180.             case Direction.right:
    181.                 generatorPoint.position += new Vector3(xOffset, 0f, 0f);
    182.                 break;
    183.  
    184.             case Direction.left:
    185.                 generatorPoint.position += new Vector3(-xOffset, 0f, 0f);
    186.                 break;
    187.         }
    188.     }
    189.  
    190.     public void CreateRoomOutline(Vector3 roomPosition)
    191.     {
    192.         bool roomAbove = Physics2D.OverlapCircle(roomPosition + new Vector3(0f, yOffset, 0f), .2f, whatIsRoom);
    193.         bool roomBelow = Physics2D.OverlapCircle(roomPosition + new Vector3(0f, -yOffset, 0f), .2f, whatIsRoom);
    194.         bool roomLeft = Physics2D.OverlapCircle(roomPosition + new Vector3(-xOffset, 0f, 0f), .2f, whatIsRoom);
    195.         bool roomRight = Physics2D.OverlapCircle(roomPosition + new Vector3(xOffset, 0f, 0f), .2f, whatIsRoom);
    196.  
    197.         int directionCount = 0;
    198.         if (roomAbove)
    199.         {
    200.             directionCount++;
    201.         }
    202.  
    203.         if (roomBelow)
    204.         {
    205.             directionCount++;
    206.         }
    207.  
    208.         if (roomLeft)
    209.         {
    210.             directionCount++;
    211.         }
    212.  
    213.         if (roomRight)
    214.         {
    215.             directionCount++;
    216.         }
    217.  
    218.         switch (directionCount)
    219.         {
    220.             case 0:
    221.                 Debug.LogError("Found no room exists!");
    222.                 break;
    223.  
    224.             case 1:
    225.  
    226.                 if (roomAbove)
    227.                 {
    228.                     generatedOutlines.Add( Instantiate(rooms.singleUp, roomPosition, transform.rotation));
    229.                 }
    230.  
    231.                 if (roomBelow)
    232.                 {
    233.                     generatedOutlines.Add(Instantiate(rooms.singleDown, roomPosition, transform.rotation));
    234.                 }
    235.  
    236.                 if (roomLeft)
    237.                 {
    238.                     generatedOutlines.Add(Instantiate(rooms.singleLeft, roomPosition, transform.rotation));
    239.                 }
    240.  
    241.                 if (roomRight)
    242.                 {
    243.                     generatedOutlines.Add(Instantiate(rooms.singleRight, roomPosition, transform.rotation));
    244.                 }
    245.  
    246.                 break;
    247.  
    248.             case 2:
    249.                 if(roomAbove && roomBelow)
    250.                 {
    251.                     generatedOutlines.Add(Instantiate(rooms.doubleUpDown, roomPosition, transform.rotation));
    252.                 }
    253.  
    254.                 if (roomLeft && roomRight)
    255.                 {
    256.                     generatedOutlines.Add(Instantiate(rooms.doubleLeftRight, roomPosition, transform.rotation));
    257.                 }
    258.  
    259.                 if (roomAbove && roomRight)
    260.                 {
    261.                     generatedOutlines.Add(Instantiate(rooms.doubleUpRight, roomPosition, transform.rotation));
    262.                 }
    263.  
    264.                 if (roomBelow && roomRight)
    265.                 {
    266.                     generatedOutlines.Add(Instantiate(rooms.doubleDownRight, roomPosition, transform.rotation));
    267.                 }
    268.  
    269.                 if (roomBelow && roomLeft)
    270.                 {
    271.                     generatedOutlines.Add(Instantiate(rooms.doubleDownLeft, roomPosition, transform.rotation));
    272.                 }
    273.  
    274.                 if (roomAbove && roomLeft)
    275.                 {
    276.                     generatedOutlines.Add(Instantiate(rooms.doubleUpLeft, roomPosition, transform.rotation));
    277.                 }
    278.  
    279.                 break;
    280.  
    281.  
    282.             case 3:
    283.  
    284.                 if (roomAbove && roomBelow && roomRight)
    285.                 {
    286.                     generatedOutlines.Add(Instantiate(rooms.tripleUpDownRight, roomPosition, transform.rotation));
    287.                 }
    288.  
    289.                 if (roomBelow && roomLeft && roomRight)
    290.                 {
    291.                     generatedOutlines.Add(Instantiate(rooms.tripleDownLeftRight, roomPosition, transform.rotation));
    292.                 }
    293.  
    294.                 if (roomAbove && roomBelow && roomLeft)
    295.                 {
    296.                     generatedOutlines.Add(Instantiate(rooms.tripleUpDownLeft, roomPosition, transform.rotation));
    297.                 }
    298.  
    299.                 if (roomAbove && roomLeft && roomRight)
    300.                 {
    301.                     generatedOutlines.Add(Instantiate(rooms.tripleUpLeftRight, roomPosition, transform.rotation));
    302.                 }
    303.  
    304.                 break;
    305.  
    306.             case 4:
    307.  
    308.                 if (roomAbove && roomBelow && roomLeft && roomRight)
    309.                 {
    310.                     generatedOutlines.Add(Instantiate(rooms.quad, roomPosition, transform.rotation));
    311.                 }
    312.                 break;
    313.         }
    314.     }
    315. }
    316.  
    317. [System.Serializable]
    318. public class RoomPrefabs
    319. {
    320.     public GameObject singleUp, singleRight, singleLeft, singleDown,
    321.         doubleUpDown, doubleLeftRight, doubleUpRight, doubleDownRight, doubleDownLeft, doubleUpLeft,
    322.         tripleUpDownRight, tripleDownLeftRight, tripleUpDownLeft, tripleUpLeftRight,
    323.         quad;
    324. }
    325.  
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
    It's this right here (check your line number in your error):
    Code (csharp):
    1.         int weaponRoomSelector = Random.Range(minDistanceToWeaponRoom, maxDistanceToWeaponRoom + 1);
    2.         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:
    https://docs.unity3d.com/ScriptReference/Random.Range.html

    So keep that in mind if you have that +1 for that reason.
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    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.
     
    Last edited: Jan 15, 2020
  4. jleven22

    jleven22

    Joined:
    Mar 26, 2019
    Posts:
    421
    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.
     
  5. jleven22

    jleven22

    Joined:
    Mar 26, 2019
    Posts:
    421
    The intent is definitely for it to be inclusive, hence the +1 (see my new response above).
     
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,537
  7. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    what is the value of layoutRoomObjects.Count, though? Remember that if the Count is 8, then the maximum index can only be 7.
     
  8. jleven22

    jleven22

    Joined:
    Mar 26, 2019
    Posts:
    421
    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.
     
  9. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    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.
     
  10. jleven22

    jleven22

    Joined:
    Mar 26, 2019
    Posts:
    421
    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!