Adding item into player inventory. Log #18 (Unity, C#)
01.06.2018

    In previous log I was only destroying game object of the item after clicking on it. In this log I will add the item into character inventory. Player character is going to have its own inventory holder inheriting from class Inventory. Class Inventory implements all general behaviour for inventory like adding items or removing them, also mothods for adding whole stack or whole another inventory (like everything from a chest). All items are going to be stored in generic list. Character's inventory holder will only implement singelton pattern for player inventory.

    Physical models in scene are only graphic representation of the items. Items itself need to have its own holder to keep informations about current item, like if the item is equipped, if it's weapon and the characteristics of item (ScriptableObject of the item). Therefore I create class ItemHolder without any inheritance, containing (ScriptableObject) Item item data or mentioned informations as bool isEquipped, et cetera. This class will represent all items in game. I separate this class intentionally from ScriptableObjects, because I dont want this additional info in my ScriptableObjects and also informations in this class will change dynamically at runtime.

 

using UnityEngine;

[System.Serializable]
public class ItemHolder
{
    public Item itemData { get; private set; }

    public ItemHolder(Item itemData)
    {
        this.itemData = itemData;
    }
}

 

    Main functions of class Inventory are AddItem(ItemHolder), RemoveItem(ItemHolder) and other methods like AddAll(List<ItemHolder>) and RemoveAll(List<ItemHolder>). These methods simply manage the list of items.

 

using System.Collections.Generic;
using UnityEngine;

public class Inventory : MonoBehaviour
{
    protected List<ItemHolder> itemList;

    public void AddItem(ItemHolder item)
    {
        itemList.Add(item);
    }

    public void AddAll(List<ItemHolder> items)
    {
        foreach (ItemHolder _itemHolder in items)
        {
            AddItem(_itemHolder);
        }
    }

    public void RemoveAllItems()
    {
        itemList.Clear();
    }

    public void RemoveAll(List<ItemHolder> items)
    {
        foreach (ItemHolder _itemHolder in itemList)
        {
            foreach (ItemHolder _itemInList in items)
                if (_itemInList.itemData == _itemHolder.itemData)
                {
                    RemoveItem(_itemHolder);
                }
        }
    }

    public void RemoveItem(ItemHolder item)
    {
        itemList.Remove(item);
    }

    public List<ItemHolder> GetItemList()
    {
        return itemList;
    }
}

 

    For mentioned inventory holder I create PlayerInventoryHolder script, inheriting from Inventory class and make singelton of it, then I init item list in Awake() of PlayerInventoryHolder from Inventory class.

 

using System.Collections.Generic;

public class PlayerInventoryHolder : Inventory
{
    public static PlayerInventoryHolder Instance { get; private set; }

    void Awake()
    {
        //Singelton
        if (Instance == null)
            Instance = this;
        else if (Instance != this)
            Destroy(gameObject);
        DontDestroyOnLoad(gameObject);

        itemList = new List<ItemHolder>();
    }
}

 

    Every physical item in scene holds the data about item in variable ItemHolder item in component ItemInteraction, after adding item into inventory, the ItemHolder item pass on to list in the inventory. Thus all informations about item are kept unchanged and I can simply pass this ItemHolder (againt to ItemInteraction component) when instantianting new object, for example, when dropping the item from inventory. Now because all items implement method Interact() I will simply define clicking action in this method. In this case it is adding the item into inventory.

 

using UnityEngine;

public class ItemInteraction : Interactable
{
    [Header("Item Interactable")]
    public Item itemData;

    public ItemHolder itemHolder { get; private set; }

    protected new void Awake()
    {
        base.Awake();
        itemHolder = new ItemHolder(itemData);
    }

    public void SetItemHolder(ItemHolder itemHolder)
    {
        this.itemHolder = itemHolder;
    }

    protected override void Interact()
    {
        PlayerInventoryHolder.Instance.AddItem(itemHolder);
        Destroy(gameObject);
    }
}

 

   I drag component PlayerInventoryHolder on the object Player in scene. Adding item into inventory is now finsihed and in next log I will show this item in the inventory list.