Inventory problem (444991)

every time i call a function in my inventory script, i get the error

form the code

public void RemoveItem (string _name, float _weight) {
		foreach (Item value in inventory) {
			if (value.name == _name) {
				inventory.Remove(value);
				gameObject.GetComponent<MoveInfo>().SpeedMulti += _weight / 100;
				Instantiate(Resources.Load(_name, typeof(Transform)), transform.position + new Vector3(1, 0, 0), transform.rotation);
			}
		}
	}

what does this mean?

You are modifying the inventory while you are enumerating it. This is generally a no-no.

The loop:

foreach (Item value in inventory)

is enumerating inventory. the line

inventory.Remove(value);

is modifying it.

You should first find the item, break the loop, and then remove it:

		Item invitem = null;
		foreach (Item value in inventory)
		{
			if (value.name == _name)
			{
				invitem = value;
				break;
			}
		}
		if (invitem != null)
		{
			inventory.Remove (value);
			gameObject.GetComponent<MoveInfo> ().SpeedMulti += _weight / 100;
			Instantiate (Resources.Load (_name, typeof(Transform)), transform.position + new Vector3 (1, 0, 0), transform.rotation);
		}

Using a foreach loop, you can’t modify the collection your iterating through. Since that’s what the inventory.Remove statement is attempting to do, you receive the exception. Use a for loop instead.

ug, now i get the same error from this

foreach (Item value in inventory) {
	if (GUI.Button(new Rect(10, 43, 100, 50), value.name + " Type: " + value.type)) {
		RemoveItem(value.name, value.weight);
	}
}

To repeat what I said before - using a foreach loop, you can’t modify the collection your iterating over. So, use a different loop style or somehow record the items you want to remove while within the loop and then remove them when you get out of the loop (as suggested by Jaimi).

I’m not sure what the RemoveItem function is doing, but I would venture to say that it is doing the same thing you were doing in the first post. Just moving the inventory.Remove statement to a separate function will, unfortunately, not get around the issue. I use an approach to this problem where a separate list of removed items is created during the first loop. Then, after the first loop is complete, loop through the items that need to be removed and remove them from the first list. This way, you are never looping through the same list you are removing from.

List<Item> toRemove = new List<Item>();
// loop through original list
// add any items that had the button clicked to the toRemove list
foreach (Item value in inventory) {
	if (GUI.Button(new Rect(10, 43, 100, 50), value.name + " Type: " + value.type)) {
		toRemove.Add(value);
	}
}

// loop through the toRemove list and
// remove them from the inventory list
foreach (Item removedValue in toRemove) {
	inventory.Remove(removedValue);
	gameObject.GetComponent<MoveInfo>().SpeedMulti += _weight / 100;
	Instantiate(Resources.Load(removedValue.name, typeof(Transform)), 
		transform.position + new Vector3(1, 0, 0), transform.rotation);
}
// clear the toRemove list
toRemove.Clear();

well, the stuff in OnGUI goes hand in hand with the Remove function