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