Error in Inventory Script
Heya, So I'm trying to build an inventory system in C#, And so far its mostly working, Its just whenever I have only One object and remove it from the Inventory I get the error ArgumentOutOfRangeException: Argument is out of range. Parameter name: index
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
public class Inventory : MonoBehaviour{
public List<BaseItem> inventory = new List<BaseItem>();
//Reference Data
// Ui display Objects
bool _Isactive;
public GameObject InventoryMenu;
public GameObject ItemButton;
public GameObject InventoryDisplay;
public Text ItemNameDisplay;
public Text ItemDescDisplay;
//Equipment Slots
public BaseItem HeadSlot;
public BaseItem ChestSlot;
public BaseItem LegSlot;
public BaseItem BootSlot;
public BaseItem WeaponSlot;
// Base Item used For item Transference
void Start () { }
void Update () {
if (Input.GetKeyDown (KeyCode.Tab)) {
_Isactive =! _Isactive;
if (_Isactive == true) {
InventoryMenu.SetActive (true);
PopulateList ();
}
if (_Isactive == false) {
ClearDisplayList ();
InventoryMenu.SetActive (false);
}
}
}
public void PopulateList(){
for (int i = 0; i < inventory.Count; i++) {
int Index = i;
GameObject button = (GameObject)Instantiate (ItemButton);
button.GetComponentInChildren<Text> ().text = "" + inventory [i].itemName;
button.GetComponent<Item_descDisplay> ().Item_Name = "" + inventory [i].itemName;
button.GetComponent<Item_descDisplay> ().Item_Desc = "" + inventory [i].itemDesc;
button.transform.SetParent (InventoryDisplay.transform,false);
button.GetComponent<Button> ().onClick.AddListener (delegate {
ActivateItem (Index);
});
}
}
public void ActivateItem(int I){
if (inventory [I].ItemType == BaseItem.itemType.Head) {
if (HeadSlot.itemName == "") {
HeadSlot = inventory [I];
print ("" + I);
inventory.RemoveAt (I);
rebuildList ();
}
if (HeadSlot.itemName != "") {
inventory.Add (HeadSlot);
HeadSlot = inventory [I];
inventory.RemoveAt (I);
rebuildList ();
}
}
if (inventory [I].ItemType == BaseItem.itemType.Chest) {
if (ChestSlot.itemName == "") {
ChestSlot = inventory [I];
inventory.RemoveAt (I);
rebuildList ();
}
if (ChestSlot.itemName != "") {
inventory.Add (ChestSlot);
ChestSlot = inventory [I];
inventory.RemoveAt (I);
rebuildList ();
}
}
if (inventory [I].ItemType == BaseItem.itemType.Legs) {
if (LegSlot.itemName == "") {
LegSlot = inventory [I];
inventory.RemoveAt (I);
rebuildList ();
}
if (LegSlot.itemName != "") {
inventory.Add (LegSlot);
LegSlot = inventory [I];
inventory.RemoveAt (I);
rebuildList ();
}
}
if (inventory [I].ItemType == BaseItem.itemType.Weapon) {
if (WeaponSlot.itemName == "") {
WeaponSlot = inventory [I];
inventory.RemoveAt (I);
rebuildList ();
}
if (WeaponSlot.itemName != "") {
inventory.Add (WeaponSlot);
WeaponSlot = inventory [I];
inventory.RemoveAt (I);
rebuildList ();
}
}
if (inventory [I].ItemType == BaseItem.itemType.Boots) {
if (BootSlot.itemName == "") {
BootSlot = inventory [I];
inventory.RemoveAt (I);
rebuildList ();
}
if (BootSlot.itemName != "") {
inventory.Add (BootSlot);
BootSlot = inventory [I];
inventory.RemoveAt (I);
rebuildList ();
}
}
}
void rebuildList(){
foreach (Transform children in InventoryDisplay.transform) {Destroy (children.gameObject);}
PopulateList ();
}
void ClearDisplayList(){
foreach(Transform children in InventoryDisplay.transform)
{
Destroy(children.gameObject);
}
}
}
It also seems that if I have multiple objects in the list it will select the next object( and example would be when I click a button set to the object at index 0 and it effects the object set to index 1)
I searched through The Code But I cant seem to find the problem, Ive spent about 2-3 days trying to fix it But Its beyond me.
you're iterating thru inventory, but when you call ActivateItem(), it's potentially removing items in the list so the overall loop count will be lower, producing the error.
one workaround is to iterate in reverse - that way the reducing count won't affect you.
I tried reverse iteration, sadly the problem still persists, I do however like the way the list is organized now.
Answer by TBruce · May 07, 2016 at 01:18 AM
Here is one thing that I see that does not look good
public void PopulateList()
{
for (int i = 0; i < inventory.Count; i++)
{
button.GetComponent<Button> ().onClick.AddListener (delegate { ActivateItem (Index); });
}
}
public void ActivateItem(int I)
{
inventory.RemoveAt (I);
rebuildList ();
}
void rebuildList()
{
foreach (Transform children in InventoryDisplay.transform)
{
Destroy (children.gameObject);
}
PopulateList ();
}
Inside PopulateList() ActivateItem() is called in a loop.
And inside ActivateItem() items are removed then the list is rebuilt by calling rebuildList().
Inside rebuildList() all children are destroyed then PopulateList() is called causing a circular loop.
Your answer
Follow this Question
Related Questions
error CS0201 1 Answer
Nav Mesh Problem with SetDestination 1 Answer
Delete item in inventory 0 Answers
Getting certain values from an item in a list 0 Answers
InvalidCastException: Cannot cast from source type to destination type. 1 Answer