Search Unity

ArgumenOutOfRangeException

Discussion in 'Scripting' started by ScamTheMan, Jan 30, 2020.

  1. ScamTheMan

    ScamTheMan

    Joined:
    Oct 4, 2018
    Posts:
    75
    Hello my problem is exactly the thread name. This error command box shows me everytime I try to play my quiz game after 3 rounds. The quiz is basically guessing japanese symbols and every odd round you have to convert symbol to romaji and every even round you have to convert word to Hiragana. I paused the game after every round and found out that after 3rd round answered, it just deletes my list of Romaji and of course without list of possible questions, it can't create new one.

    Code (CSharp):
    1. gm.currentQuestion = Random.Range(0, 45);
    2.         yield return new WaitForSeconds(2f);
    3.         gm.QuestionText.text = gm.Hiragana[gm.currentQuestion] + "\nConvert To Romaji";
    4.  
    5.         randomButton = Random.Range(0, 3); //Random Number where will be correct answer
    6.         gm.ButtonText[randomButton].text = gm.Romaji[gm.currentQuestion]; //Write correct answer to button[corresponding to randomButton]
    7.         AnswerIndex = gm.Romaji[gm.currentQuestion]; //Write to string variable current correct answer
    8.         gm.Romaji.RemoveAt(gm.currentQuestion); //Remove answer from list of all Romaji symbols
    9.  
    10.         randomSymbol1 = Random.Range(0, 44); //Choose random number corresponding to Romaji symbol from list
    11.         gm.ButtonText[0].text = gm.Romaji[randomSymbol1]; //Write symbol to button
    12.         gm.Romaji.RemoveAt(randomSymbol1); //Remove symbol from list of all Romaji symbols
    13.  
    14.         randomSymbol2 = Random.Range(0, 43);
    15.         gm.ButtonText[1].text = gm.Romaji[randomSymbol2];
    16.         gm.Romaji.RemoveAt(randomSymbol2);
    17.  
    18.         randomSymbol3 = Random.Range(0, 42);
    19.         gm.ButtonText[2].text = gm.Romaji[randomSymbol3];
    20.         gm.Romaji.RemoveAt(randomSymbol3);
    21.  
    22.         randomSymbol4 = Random.Range(0, 41);
    23.         gm.ButtonText[3].text = gm.Romaji[randomSymbol4];
    24.         gm.Romaji.RemoveAt(randomSymbol4);
    25.  
    26.         gm.ButtonText[randomButton].text = AnswerIndex; //Rewrite correct answer to button chosen in the beginning
    27.  
    28.         gm.Romaji.Clear(); //Clear the whole Romaji list
    29.         gm.Romaji = gm.RomajiBackUp; //Replace cleared Romaji list for RomajiBackUp list
    Romaji list and RomajiBackUp list are in the beginning the same length and content but after removing symbols from Romaji list I have to rewrite it with the back up one, because the symbols have to be on the exact element number it was on the beginning.
    I know this looks kinda dumb which is why I want a help from you. How to solve this error? And if possible, how can I make the code easier or not buggy like now.

    PS: The code is cut from IEnumerator because other code chunks in it are not important
     
  2. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    ArgumentOutOfRange usually means that you are trying to access an element in an array or a list with an index that is either higher than the maximum or less than 0. For example if I declare an array like this
    int[] array1 = new int[5];
    then I can write
    array1[1]=5 
    or
    array1[4]=0
    , but If I try to assign a value to array1[5] or array1[-1] then I will get an error.

    First thing is to look at what line the error occurs on. What's going on there?
     
  3. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    This error basically means that you have tried to access an item in an array outside of what the array allows - i.e. item 5 of a 3-item array. You're using a TON of arrays here, so the error could be at any one of the 14 array-accessing lines of code in this segment. In general, you should copy and paste the full error message, as it includes the line number of the error, though since you only included a portion of the script that wouldn't have helped. More to the point, any single one of the array uses here could be the culprit, because you're not using any safeguards on your array indices which would protect against these errors.

    First, is this pattern:
    Code (csharp):
    1. randomSymbol1 = Random.Range(0, 44); //Choose random number corresponding to Romaji symbol from list
    2.         ... = gm.Romaji[randomSymbol1];
    As written, we have no guarantee that randomSymbol1 is actually within the size of the gm.Romaji array. If you're off by even one, you'll get this problem. This is a safer way to access a random item from an array, because you 100% know the index will be a valid one:
    Code (csharp):
    1. randomSymbol = Random.Range(0,gm.Romaji.Count); //or .Length if it were a regular array like this[].
    You can do basically the same thing on line 5.

    And then there's this pattern
    Code (csharp):
    1. gm.ButtonText[0].text = ....
    Again, there are no safeguards here to ensure that any of these indices are within the bounds of the gm.ButtonText array. In this case, you're doing this over and over, once with each item in the list, and there's a way to ensure that the code gets called exactly once for each item in this array: a for loop. And if we combine this within the advice from above, we don't need our 44, 43, 42 numbers - the .Count will update itself. And that means that all those chunks are near identical, perfect for a loop:
    Code (csharp):
    1. for (int i=0;i<gm.ButtonText.Count; i++) { //again, use .Length if ButtonText is a builtin array
    2. randomSymbol = Random.Range(0, gm.Romaji.Count);
    3. gm.ButtonText[i].text = gm.Romaji[randomSymbol];
    4. gm.Romaji.RemoveAt(randomSymbol);
    5. }
     
  4. ScamTheMan

    ScamTheMan

    Joined:
    Oct 4, 2018
    Posts:
    75
    I think the error occurs at the 28th line when I try to clear the list and then I want to overwrite it with back up list, because when I was testing it while running, both lists had been cleared so then when it wanted to reach for an element, it couldn't because there were no elements to choose from.
     
  5. ScamTheMan

    ScamTheMan

    Joined:
    Oct 4, 2018
    Posts:
    75
    Thank you, I will definitely use this loop, but how can I bring Romaji list back to its original form? I try it in the 28th line with clearing it and then overwriting it with identical back up list but I think that's where it stops working. (I think it somehow clear both lists, not just the Romaji one)
     
  6. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    That doesn't really make sense because there is no indexer on that line. The error message in the console should tell you exactly what line the error is actually happening on, though.
     
  7. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    Ah, that'll do it. You need to copy the array. Both variables are pointing to the same object, so removing objects from the list means both variables will see the change. You need to actually copy the array, which IIRC you can do by feeding the old list into the new one's constructor:
    Code (csharp):
    1. gm.RomajiBackup = new List<whatever>(gm.Romaji);
     
  8. ScamTheMan

    ScamTheMan

    Joined:
    Oct 4, 2018
    Posts:
    75
    This is what console is returning
     

    Attached Files:

  9. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    So what's at BattleSystem.cs on line 354?
     
  10. ScamTheMan

    ScamTheMan

    Joined:
    Oct 4, 2018
    Posts:
    75
    This is what I was waiting for. Thank you so much, you made my day right now.