Hey all.
So I’ve been bangin’ my head against this for some time. Watched countless tutorials but none actually seems to explain this sufficiently well.
I’m trying to patch together an inventory system with a few important characteristics. It also lacks a number of common characteristics.
NOTE: I’m not necessarily looking for a complete solution but a solid idea for architecture.
This is the function I’m looking for.
- Possible to easily expand with more items (I’m thinking scriptable objects).
- Possible to instantiate a populated inventory on a procedurally generated object. The specific items will be random (from a non-random list) with a random float amount (randomized in specific ranges).
- Possible to on given command take “amount” of “item” from inventory1 to inventory2.
Going forward I want to be able to craft, save/load and access data from a GUI. For now the ability to debug amounts and se what’s going on in the inspector is fine.
My suggestion in broad strokes:
- A scriptable object “Item” holding recourceSpecific data.
- A class “itemInstance” that holds the item and amount.
- An “inventory” class containing a List/Dictionary/Hashtable.
Any thoughts on a general structure (or specific scripts) would be greatly appreciated. The specific coding in its self I think I can handle.
Below is my feeble attempt. The Inventory-class contains short notes but like I said: What should the architecture look like?
using UnityEngine;
[CreateAssetMenu(fileName = "New Item", menuName = "Inventory/New Item")]
public class Item : ScriptableObject
{
public int itemID;
public string itemName;
public float itemWeight;
public Sprite itemSprite;
[TextArea]
public string itemDescription;
}
[System.Serializable]
public class ItemInstance
{
// Reference to scriptable object "template".
public Item item;
// Object-specific data.
public float amount;
public ItemInstance(Item item, float amount)
{
this.item = item;
this.amount = amount;
}
}
And here’s the big one (that doesn’t work).
using System.Collections.Generic;
using UnityEngine;
public class Inventory : MonoBehaviour
{
//Initiating my inventoryList. For some reason it shows up in the inspector with 0 capacity.
public List<ItemInstance> inventory = new List<ItemInstance>(10);
public void AddAmount(Item _item, float _amount)
{
for (int i = 0; i < inventory.Count; i++) //Generates a null exception. Why?
{
if (inventory[i].item.itemID == _item.itemID) //My code never gets here.
{
inventory[i].amount += _amount;
break;
}
}
InsertItem(_item, _amount); //All tries to "AddAmount" goes directly to "InsertItem".
}
public float RemoveAmount(Item _item, float _amount)
{
for (int i = 0; i < inventory.Count; i++)
{
if (inventory[i].item.itemID == _item.itemID)
{
if (inventory[i].amount > _amount)
{
inventory[i].amount -= _amount;
return _amount;
}
else if (inventory[i].amount <= _amount) //Take more than available.
{
_amount = inventory[i].amount;
inventory[i].amount = 0f; //Reduce inventorySlot.amount to zero.
inventory.RemoveAt(i); //Remove the item from the inventorySlot.
return _amount; //Return whatever amount was available.
}
}
}
return 0f;
}
public void InsertItem(Item _item, float _amount)
{
for (int i = 0; i < inventory.Count; i++) //Again the for-loop gives null exception.
{
if(inventory[i] == null)
{
inventory.Insert(i, new ItemInstance(_item, _amount));
}
}
}
}