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. Dismiss Notice

Question ArgumentOutOfRangeException

Discussion in 'Scripting' started by donbonbon, Jun 14, 2023.

  1. donbonbon

    donbonbon

    Joined:
    May 28, 2023
    Posts:
    20
    I receive the following error message and I cannot find my bug.


    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 <1c8569827291471e9db0dcd976e97952>:0)
    DisplayCard.Update () (at Assets/Scripts/DisplayCard.cs:33)


    I develop a multiplayer card game. So far I create three scripts. The DisplayCard.cs, in which the error appears, CardDatabase.cs and Card.cs which are also related to the problematic script.

    I include the other two scripts in case it can help detect my error.

    According to google this error indicates one of my variables is wrongly defined. I spent half a night trying to locate my error, I'm still at square one. Any tip or return would be highly appreciated.

    DisplayCard.cs
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.EventSystems;
    6.  
    7. public class DisplayCard : MonoBehaviour
    8. {
    9.     public List<Card> displayCard = new List<Card>();
    10.     public int displayId;
    11.  
    12.     public int id;
    13.     public string cardName;
    14.     public int cost;
    15.     public int power;
    16.     public string cardDescription;
    17.  
    18.     public Text nameText;
    19.     public Text costText;
    20.     public Text powerText;
    21.     public Text descriptionText;
    22.    
    23.     // Start is called before the first frame update
    24.     void Start()
    25.     {
    26.         //cardList is the database name at the respective script
    27.         displayCard[0] = CardDatabase.cardList[displayId];
    28.     }
    29.  
    30.     // Update is called once per frame
    31.     void Update()
    32.     {
    33.         id = displayCard[0].id;
    34.         cardName = displayCard[0].cardName;
    35.         cost = displayCard[0].cost;
    36.         power = displayCard[0].cost;
    37.         cardDescription = displayCard[0].cardDescription;
    38.  
    39.         nameText.text = " " + cardName;
    40.         costText.text = " " + cost;
    41.         powerText.text = " " + power;
    42.         descriptionText.text = " " + descriptionText;
    43.     }
    44. }
    45.  
    Card.cs
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. [System.Serializable]
    5.  
    6. public class Card : MonoBehaviour
    7. {
    8.     public int id;
    9.     public string cardName;
    10.     public int cost;
    11.     public int power;
    12.     public string cardDescription;
    13.  
    14.  
    15.  
    16.     public Card()
    17.     {
    18.  
    19.     }
    20.  
    21.     public Card(int Id, string CardName, int Cost, int Power, string CardDescription)
    22.     {
    23.         id = Id;
    24.         cardName = CardName;
    25.         cost = Cost;
    26.         power = Power;
    27.         cardDescription = CardDescription;
    28.     }
    29.  
    30. }
    31.  
    CardDatabase.cs
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class CardDatabase : MonoBehaviour
    6. {
    7.     public static List<Card> cardList = new List<Card>();
    8.  
    9.     void awake()
    10.     {
    11.  
    12.         cardList.Add(new Card(0, "None", 0, 0, "None"));
    13.         cardList.Add(new Card(1, "Human", 2, 1, "This is a human"));
    14.         cardList.Add(new Card(2, "Elf", 3, 3, "This is an elf"));
    15.         cardList.Add(new Card(3, "Dwarf", 4, 4, "This is an dwarf"));
    16.         cardList.Add(new Card(4, "Troll", 5, 5, "This is an troll"));
    17.  
    18.  
    19.     }  
    20. }
     
  2. CodeRonnie

    CodeRonnie

    Joined:
    Oct 2, 2015
    Posts:
    280
    I'm not sure how you're even reaching Update() without a previous error in Start(). You should call displayCard.Add() in Start(), not displayCard[0] = . That should at least get your error to go away.
     
  3. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,140
    Caps matter! Get in the habit of capitalizing the first letter of your methods. Not only is it good practice, it's the difference between Unity saying "Hey, I can run this for you." vs "Hey, this is your own method." Especially when dealing with Awake and Start. But you should always make sure if it's a Unity Magic method that you watch the caps exactly.

    upload_2023-6-13_20-0-12.png
     
    CodeRonnie likes this.
  4. donbonbon

    donbonbon

    Joined:
    May 28, 2023
    Posts:
    20
    Thanks for your reply. I'm not I had understood your proposal. If I add displayCard.Add() instead of displayCard[0] = CardDatabase.cardList[displayId]; I cannot comply the scripts, i.e. unity refuses to play it. As to how it reached Update(), I only know that it reached. I apply the code from the following tutorial. I checked it again and it seems I copied it as is.
     
  5. donbonbon

    donbonbon

    Joined:
    May 28, 2023
    Posts:
    20
    Thanks for your input. I thought cardList is the name of my database, not a method. I however, tried to apply your input and changed it to CardList. The error message stays the same.
     
  6. donbonbon

    donbonbon

    Joined:
    May 28, 2023
    Posts:
    20
    When I add displayCard.Add(CardDatabase.cardList[displayId]); instead of displayCard[0] = CardDatabase.cardList[displayId]; Unity runs the scripts. Though, the error message stays the same.
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    The error message WILL stay the same until you fix your mis-capitalization of the Awake() method.

    Read what Brathnann posted above.
     
  8. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,140
    I guess I need to trim down my screenshots for laser focus. Because I didn't say anything about cardList and as you said, cardList is not a method. I even mentioned Start and Awake specifically cause those get mistyped all the time.
     
  9. donbonbon

    donbonbon

    Joined:
    May 28, 2023
    Posts:
    20
    No need to trim down. It was the way I understood. You were kind enough trying to help me, so any misunderstanding remains in my side. I tried to provide information so you can better help me/that I can better grasp your comment. Sorry if my wording delivered other intentions.
     
  10. donbonbon

    donbonbon

    Joined:
    May 28, 2023
    Posts:
    20
    I fixed the capitalization of the Awake method. I still get the same error. I re-read the script to verify I didn't miss another capitalization, either it's not there, or my eyes are still missing it. I'd be more than grateful to understand how to fix it.
     
  11. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    9,900
    The
    Card
    class shouldn't inherit from
    MonoBehaviour
    . You set it
    System.Serializeable
    , you have a constructor (albeit it's empty) and you instantiate it with the
    new
    keyword. None of those should apply to a
    MonoBehaviour
    .
     
    Brathnann and CodeRonnie like this.
  12. donbonbon

    donbonbon

    Joined:
    May 28, 2023
    Posts:
    20
    The MonoBehaviour would be removed as you mentioned. But, this however should raise another type of error. Even if I remove Monobehaviour the problem remains. I constantly get an error message our of range, and I still cannot tell why.

    error:
    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 <1c8569827291471e9db0dcd976e97952>:0)
    DisplayCard.Update () (at Assets/Scripts/DisplayCard.cs:34)
     
  13. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    9,900
    Did you replace the line
    displayCard[0] = CardDatabase.cardList[displayId];
    with the line
    displayCard.Add(CardDatabase.cardList[displayId]);

    Are you sure the
    displayId
    contains an existing index? Put a
    Debug.Log($"{displayId} -> {CardDatabase.cardList[displayId]}");
    on the 33rd line and check what the console says.
    Also if everything checks out, post a new set of code here, so we see what is really running.

    What another type of error?
     
  14. donbonbon

    donbonbon

    Joined:
    May 28, 2023
    Posts:
    20
    Thanks for the feedback.
    It still bugs but this time it provides another type of error.

    'DisplayCard' is missing the class attribute 'ExtensionOfNativeClass'!

    Herein below are the scripts, in case it helps, I comment the following:

    1. I removed the Monoehavior and added the
    displayCard.Add(CardDatabase.cardList[displayId]);

    2. As for the console.log,
    Debug.Log($"{displayId} -> {CardDatabase.cardList[displayId]}");

    I wasn't sure exactly where to add it.

    If it was inside the update() and/or the Start() it raised the same NativeClass error, i.e it seems no log.

    If it was out of these functions and justs above the update() it raised the error:
    Assets\Scripts\DisplayCard.cs(31,15): error CS1519: Invalid token '$"{displayId} -> {CardDatabase.cardList[displayId]}"' in class, record, struct, or interface member declaration


    Scripts:
    DisplayCard.cz
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.EventSystems;
    6.  
    7. public class DisplayCard
    8. {
    9.     public List<Card> displayCard = new List<Card>();
    10.     public int displayId;
    11.  
    12.     public int id;
    13.     public string cardName;
    14.     public int cost;
    15.     public int power;
    16.     public string cardDescription;
    17.  
    18.     public Text nameText;
    19.     public Text costText;
    20.     public Text powerText;
    21.     public Text descriptionText;
    22.    
    23.     // Start is called before the first frame update
    24.     void Start()
    25.     {
    26.        
    27.         displayCard.Add(CardDatabase.cardList[displayId]);
    28.     }
    29.  
    30.     // Update is called once per frame
    31.     Debug.Log($"{displayId} -> {CardDatabase.cardList[displayId]}");
    32.     void Update()
    33.    
    34.     {
    35.        
    36.         id = displayCard[0].id;
    37.         cardName = displayCard[0].cardName;
    38.         cost = displayCard[0].cost;
    39.         power = displayCard[0].cost;
    40.         cardDescription = displayCard[0].cardDescription;
    41.  
    42.         nameText.text = " " + cardName;
    43.         costText.text = " " + cost;
    44.         powerText.text = " " + power;
    45.         descriptionText.text = " " + descriptionText;
    46.     }
    47. }
    48.  

    Card.cz
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. [System.Serializable]
    5.  
    6. public class Card
    7. {
    8.     public int id;
    9.     public string cardName;
    10.     public int cost;
    11.     public int power;
    12.     public string cardDescription;
    13.  
    14.     public Card()
    15.     {
    16.  
    17.     }
    18.  
    19.     public Card(int Id, string CardName, int Cost, int Power, string CardDescription)
    20.     {
    21.         id = Id;
    22.         cardName = CardName;
    23.         cost = Cost;
    24.         power = Power;
    25.         cardDescription = CardDescription;
    26.     }
    27.  
    28. }


    CardDatabase.cz
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class CardDatabase : MonoBehaviour
    6. {
    7.     public static List<Card> cardList = new List<Card>();
    8.  
    9.     void Awake()
    10.     {
    11.        
    12.         cardList.Add(new Card(0, "None", 0, 0, "None"));
    13.         cardList.Add(new Card(1, "Human", 2, 1, "This is a human"));
    14.         cardList.Add(new Card(2, "Elf", 3, 3, "This is an elf"));
    15.         cardList.Add(new Card(3, "Dwarf", 4, 4, "This is an dwarf"));
    16.         cardList.Add(new Card(4, "Troll", 5, 5, "This is an troll"));
    17.  
    18.     }  
    19. }
    20.  
     
  15. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    9,900
    But why?
    Who said you should remove MonoBehaviour from the DisplayCard class?
    And why would you put a command outside of the method? You really should go through a C# and coding for beginners course before you start to write any kind of basic code.
     
    Kurt-Dekker likes this.
  16. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    897
    funnily enough if you watch that tutorial he posted, the guy in the video literally brings up that the code he wrote will cause these very issues. and goes over it and fixes it in the latter half of the video.

    Also, if you watch carefully in the video... the guy also set the size of the displayCard list in the inspector to specifically avoid the ArgumentOutOfRangeException (also in the latter half, at 11:21) but he wasn't being very clear to the viewers as to why he did it.

    I think thats why he is following that video tutorial, he is trying to learn. However, I think the main problem is that it seems he only speaks Czech (based on his .cz file extensions) and is using a translator to translate to English. however a lot is getting lost in translation so he is having difficulty following both us and the tutorial.

    I think we would be more productive if the code fixes were explicitly posted back in addition to the suggestions.

    @donbonbon look closely in that video at 11:21. He press the '+' button to add an empty field in the inspector, if you are following along and did not also add an empty field like he did, this would be why you are getting this error. However the code in this tutorial is poorly written, likely because he wants to keep it simple for new people learning C#.

    If you follow him exactly you should not get any errors (beside the ones he intentionally added in and later removed) , but if you mess anything up or change something while the game is playing it is very easy for these errors to happen. So I will post some changes to the code that should make the code a little more stable, with the added benefit where you do not need to re-enter play to change cards like the guy in the video was doing.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.EventSystems;
    6. public class DisplayCard:MonoBehaviour
    7. {
    8.     public Card displayedCard;
    9.     public int displayId;
    10.     public int id;
    11.     public string cardName;
    12.     public int cost;
    13.     public int power;
    14.     public string cardDescription;
    15.     public Text nameText;
    16.     public Text costText;
    17.     public Text powerText;
    18.     public Text descriptionText;
    19.     // Update is called once per frame
    20.     void Update()
    21.     {
    22.         if(displayId<0)return;
    23.         if(CardDatabase.cardList.Count < displayId)return;
    24.  
    25.         displayedCard = CardDatabase.cardList[displayId];
    26.         id = displayedCard.id;
    27.         cardName = displayedCard.cardName;
    28.         cost = displayedCard.cost;
    29.         power = displayedCard.cost;
    30.         cardDescription = displayedCard.cardDescription;
    31.  
    32.         nameText.text = " " + cardName;
    33.         costText.text = " " + cost;
    34.         powerText.text = " " + power;
    35.         descriptionText.text = " " + descriptionText;
    36.     }
    37. }

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [System.Serializable]
    4. public class Card
    5. {
    6.     public int id;
    7.     public string cardName;
    8.     public int cost;
    9.     public int power;
    10.     public string cardDescription;
    11.     public Card()
    12.     {
    13.  
    14.     }
    15.     public Card(int Id, string CardName, int Cost, int Power, string CardDescription)
    16.     {
    17.         id = Id;
    18.         cardName = CardName;
    19.         cost = Cost;
    20.         power = Power;
    21.         cardDescription = CardDescription;
    22.     }
    23. }

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class CardDatabase : MonoBehaviour
    6. {
    7.     public static List<Card> cardList = new List<Card>();
    8.  
    9.     void Awake()
    10.     {
    11.         cardList.Add(new Card(0, "None", 0, 0, "None"));
    12.         cardList.Add(new Card(1, "Human", 2, 1, "This is a human"));
    13.         cardList.Add(new Card(2, "Elf", 3, 3, "This is an elf"));
    14.         cardList.Add(new Card(3, "Dwarf", 4, 4, "This is an dwarf"));
    15.         cardList.Add(new Card(4, "Troll", 5, 5, "This is an troll"));
    16.     }
    17. }

    I'm also keeping the changes simple for you. Normally I would be using ScriptableObjects, Properties, Ternarys and so on. But think that is a bit too much for you to learn at once, for your first dive into C#.
     
    Lurking-Ninja likes this.
  17. donbonbon

    donbonbon

    Joined:
    May 28, 2023
    Posts:
    20
     
  18. donbonbon

    donbonbon

    Joined:
    May 28, 2023
    Posts:
    20
    a.)The command line out of the method was intentional. since you said to add it to line line 33, which in my case was in the Update method, and thus didn't provide any output, I simply wanted to flag it out, as I mentioned in my comments. Sorry if that wasn't clear.

    b.) The MonoBehaviour was removed from the DisplayCard class and not the Card class because of misunderstanding.

    I corrected it.

    c.) With regard to the [System.Serializable]

    This isn't used in the scripts. But it is needed to add an empty DisplayCard script which is added as component to the Card image in the hierarchy.

    d.) With that all in place, I still get the following errors:

    1
    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 <1c8569827291471e9db0dcd976e97952>:0)
    DisplayCard.Start () (at Assets/Scripts/DisplayCard.cs:26)

    2.
    NullReferenceException: Object reference not set to an instance of an object
    DisplayCard.Update () (at Assets/Scripts/DisplayCard.cs:40)

    The second error is expected, as indicated in the tutorial. The first is the one at the origin of my thread, i.e. for which I asked for your support.


    e.) Above there was a comment I should have stick to the original script in the tutorial. That wasn't possible however. First, I applied two changes that were suggested here, and one was forced because of change of Unity version. I note them here in case it helps:

    i.) Remove MonoBehaviour from the Card class - in the tutorial it appears intentionally. So I should remove it after.

    ii.) I added Text - Text Mesh Pro, rather than Text - as Unity updated the version from the tutorial.

    iii) displayCard.Add(CardDatabase.cardList[displayId]);

    f. Cz was cs. was due to the late hour I wrote my reply. I don't speak Czech.
     
  19. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    897
    That is not how you "flag out" a line of code. If you want to prevent a line of code from running you can simply comment it out like so
    Code (CSharp):
    1.     void Update()
    2.     {
    3.         //Debug.Log($"{displayId} -> {CardDatabase.cardList[displayId]}");
    we know what it is and why you need it, there is no debate about this

    Judging from the most recent code you've posted there is no code on line 26 so we can only give a best guess as to the cause. It looks like the CardDatabase.cardList is empty. this can be because you do not have a CardDatabase component on a active gameobject in the scene.

    EDIT: In fact thinking about it more and re-reading your posts i think that is the problem you are having, and why as you've said previously the log @Lurking-Ninja had you add was adding the same "native error". CardDatabase.cardList is empty. (which it would be since in your first post you were using "awake()" and not "Awake()" inside CardDatabase)

    To explain the error itself its likely complaining about the code
    CardDatabase.cardList[displayId]
    the error is simply stating that the value between the '[ ]' is not valid it is either too large or too small. if the list is empty at the time you call it it will always be invalid. this is why in the code in my previous post I was first checking the value of displayId
    Code (CSharp):
    1.         if(displayId<0)return;
    2.         if(CardDatabase.cardList.Count < displayId)return;
    before I would actually use it inside a '[ ]' for that list if the value was invalid the code would simply not run, but at least it would not throw exceptions.

    While TextMeshPro is better on all accounts. I believe the Text component is still fully supported even in the newest versions. You did not have to change from Text to TextMeshPro, but at the same time the code is still very similar.

    However it is important to point out if you changed the datatype of the Text fields to TextMeshPro it WILL have broken the references you hooked up for that class in the inspector since the datatype are different in unity it likely also explains the null reference error you are getting on line 40 which would be a DIFFERENT NullReferenceException than the one pointed out in the video.

    Check your inspector and see that everything is still hooked up before you press play..

    I see my mistake then, no worries
     
    Last edited: Jun 18, 2023