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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

[Solved] IndexOutOfRangeException: Index was outside the bounds of the array.

Discussion in 'Scripting' started by Kingleon99, Apr 23, 2019.

  1. Kingleon99

    Kingleon99

    Joined:
    Oct 11, 2018
    Posts:
    7
    HI first of all I want so say that I am completely new to Unity and cSharp

    I try to make an Inventory Manager that keeps track of the Items the player has pickt up and saves the ID of the item and when the player loadts a new scene it should add the items based on the ID and it works sofar that it keeps track of it without any proplems but when I load a new scene I get a IndexOutOfRangeException Error say if you need more information

    and bytheway i hope my english isn't to bad because i am not an native English speaker

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class InventoryManager : MonoBehaviour
    6. {
    7.     static InventoryManager instance;
    8.     private GameMenu GM;
    9.     public List<GameObject> Items = new List<GameObject>();
    10.     public List<int> ItemID = new List<int>();
    11.  
    12.     void Start()
    13.     {
    14.         //checks if another Inventory Manger exist and deletes itelf if
    15.         if (instance != null)
    16.         {
    17.             Destroy(gameObject);
    18.         }
    19.         else
    20.         {
    21.             instance = this;
    22.             DontDestroyOnLoad(gameObject);
    23.         }
    24.     }
    25.  
    26.     public void loadInventory()
    27.     {
    28.         for (int i = 0; i < ItemID.Count; i++)
    29.         {
    30.             for (int a = 0; a < Items.Count; a++)
    31.             {
    32.                 if (ItemID[i] == Items[a].GetComponent<Item>().ID)
    33.                 {
    34.                     GM = GameObject.Find("MenusUI").GetComponent<GameMenu>();
    35.                     GM.AddItem(Items[a], Items[a].GetComponent<Item>().ID, Items[a].GetComponent<Item>().type, Items[a].GetComponent<Item>().description, Items[a].GetComponent<Item>().icon);
    36.                 }
    37.             }
    38.         }
    39.     }
    40. }
     
  2. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,120
    Hmm. I might be missing something obvious, but that bit of code looks solid in terms of IndexOutOfRange goes. What exact line number does the exception reference?

    Also, just for sanity and readability, I would do something like this:

    Code (CSharp):
    1. var item = Items[a].GetComponent<Item>();
    Do this once so you don't need to keep calling GetComponent. This is also more efficient, especially if this code gets called a lot.
     
  3. Kingleon99

    Kingleon99

    Joined:
    Oct 11, 2018
    Posts:
    7
    IndexOutOfRangeException: Index was outside the bounds of the array.
    GameMenu.AddItem (UnityEngine.GameObject itemObject, System.Int32 itemID, System.String itemType, System.String itemDescription, UnityEngine.Sprite itemIcon) (at Assets/Scripts/Menus/GameMenu.cs:266)
    InventoryManager.loadInventory () (at Assets/Scripts/Saving Stuff/Saving Player/InventoryManager.cs:35)
    PlayerMovement.Awake () (at Assets/Scripts/PlayerMovment/PlayerMovement.cs:183)

    is the full error message

    and then i click on the error messege it opens my AddItem function

    Code (CSharp):
    1.     public void AddItem(GameObject itemObject, int itemID, string itemType, string itemDescription, Sprite itemIcon)
    2.     {
    3.         for (int i = 0; i < allSlots; i++)
    4.         {
    5.             if (slot[i].GetComponent<Slot>().empty)
    6.             {
    7.                 IM.ItemID.Add(itemID);
    8.                 itemObject.GetComponent<Item>().pickedUp = true;
    9.  
    10.                 slot[i].GetComponent<Slot>().item = itemObject;
    11.                 slot[i].GetComponent<Slot>().icon = itemIcon;
    12.                 slot[i].GetComponent<Slot>().type = itemType;
    13.                 slot[i].GetComponent<Slot>().ID = itemID;
    14.                 slot[i].GetComponent<Slot>().description = itemDescription;
    15.  
    16.                 itemObject.transform.parent = slot[i].transform;
    17.                 itemObject.SetActive(false);
    18.  
    19.                 slot[i].GetComponent<Slot>().UpdateSlot();
    20.                 slot[i].GetComponent<Slot>().empty = false;
    21.                 return;
    22.             }
    23.         }
    24.     }
     
  4. lowbl_dan

    lowbl_dan

    Joined:
    Jan 22, 2019
    Posts:
    34
    You might want to check if the contents of your slot array is not null, especially if you change scenes, if slot was predefined by gameObjects in the other scene and is not brought over, the contents of the array will be set to null.

    Also, like dgoyette mentioned, this would be better for readability and getcomponent will not be called multiple times.

    Code (csharp):
    1.  
    2.            Slot currentslot = slot[i].GetComponent<Slot>();
    3.            if(!currentslot)   Debug.logError("currentslot is null"); //or do a try catch
    4.  
    5.   if (currentslot .empty)
    6.   {
    7.                 IM.ItemID.Add(itemID);
    8.                itemObject.GetComponent<Item>().pickedUp = true;
    9.  
    10.  
    11.                 currentslot .item = itemObject;
    12.                 currentslot .icon = itemIcon;
    13.                 currentslot .type = itemType;
    14.                 currentslot .ID = itemID;
    15.                 currentslot .description = itemDescription;
    16.         }
    17.  
    18.  
    19.  
     
  5. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,120
    Note that the error message gives you a line number in your script:

    GameMenu.cs:266

    That means the exception is occurring on line 266. Unfortunately, you've only pasted the method itself, so the line numbers in Unity's code block aren't the actual line numbers in your script, so we can't tell which line it's occurring on. But you should look at line 266 in your script, and maybe even tell us which line in your post it's occurring.
     
  6. Kingleon99

    Kingleon99

    Joined:
    Oct 11, 2018
    Posts:
    7
    line 266 is the if statement
    Code (CSharp):
    1. if (slot[i].GetComponent<Slot>().empty)
     
  7. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,120
    Okay, that makes sense. Notice that your looping through from 0 to `allSlots', rather than looping through 0 to slot.Count. That's dangerous, since the value of allSlots could (and apparently has) gone out of sync with the number of items in your 'slot' collection. I'd recommend that with for loops like this, where you're going to index into an array, you base the looping on the number of items in the array. Or you can just do some additional checks within your loop, and `continue' if `i' represents an index too large for the array.
     
  8. Kingleon99

    Kingleon99

    Joined:
    Oct 11, 2018
    Posts:
    7
    i am sorry but i dont understand completely what you mean what do i need to change to fix it ?
     
  9. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,120
    Simplest fix:

    Change this:

    Code (CSharp):
    1. for (int i = 0; i < allSlots; i++)
    To this:
    Code (CSharp):
    1. for (int i = 0; i < slot.Count; i++)  // Or .Length, or .Count(), depending
     
  10. Kingleon99

    Kingleon99

    Joined:
    Oct 11, 2018
    Posts:
    7
    its working thanks