How can I check if there are all the items in a list AND the correct quantity using this system?

I have a script:

using System.Collections;
using System.Collections.Generic;
using UnityEditor.Experimental.GraphView;
using UnityEngine;

public class CraftingMenu : MonoBehaviour
{
    public List<Slot> slots = new List<Slot>();
    public List<Item> items = new List<Item>();
    public Transform craftableSpawn;
    public Inventory inventory;
    private List<Item> recipe;
    // Start is called before the first frame update
    void Start()
    {
        foreach (Slot slot in slots) //For each slot, initialize that slot
        {
            slot.initializeSlot();
        }
        for (int i = 0; i < items.Count; i++) //Sets all the items in the slots at start
        {
            slots[i].setItem(items[i]);
        }
    }

    // Update is called once per frame
    void Update()
    {
        for (int i = 0; i < slots.Count; i++) //For all slots, check if they are being hovered over and if the player clicks on it
        {
            if (Input.GetMouseButtonDown(0) && slots[i].hovered == true)
            {
                CheckItems(slots[i].getItem());//Checks to see if item is craftable               
                break;
            }
        }
    }

    public void CheckItems(Item item)//Check if all items are in the inventory
    {
        int amountNeeded = item.recipe.Count;
        for (int i = 0; i < item.recipe.Count; i++)
        {
            foreach (Slot slot in inventory.inventorySlots)
            {
                if (slot.heldItem != null)
                {
                    if (slot.heldItem.name == item.recipe[i].name)
                    {
                        amountNeeded -= 1;
                    }
                }
            }
        }
        if (amountNeeded <= 0)
        {
            CraftItem(item);
        }
        else
        {
            Debug.Log("Not enough items to craft this Recipe!");
        }
    }

    public void CraftItem(Item item)//Crafts the item
    {       
        int amountNeeded = item.recipe.Count;
        for (int i = 0; i < item.recipe.Count; i++)
        {
            foreach (Slot slot in inventory.inventorySlots)
            {
                if(slot.heldItem != null)
                {
                    if (slot.heldItem.name == item.recipe[i].name && slot.heldItem.currentQuant != 0)
                    {
                        amountNeeded -= 1;
                        slot.heldItem.currentQuant -= 1;
                        if(slot.heldItem.currentQuant == 0)
                        {
                            slot.heldItem = null;
                            slot.setItem(slot.heldItem);
                            slot.updateData();
                        }
                    }
                }               
            }           
        }
        if (amountNeeded <= 0)
        {
            Debug.Log("Item crafted!");
            Item craftable = Instantiate(item, craftableSpawn.position, Quaternion.identity);
            inventory.addItemToInventory(craftable);
            amountNeeded = item.recipe.Count;
        }
        else
        {
            Debug.Log("Something went wrong in the 'CraftItem' function in the 'CraftingMenu' script!");
        }

    }   
}

So in this script, the players items in their inventory are checked first (“CheckItems()”) in order to determine if they have the items needed to craft the item. It then sends this off to the “CraftItem()” function. This works, but as of right now, the script only verifies if they have the same items with the same name in their inventory, NOT the quantity as well. I’m not sure how to compare those things because the recipe stores each item individually so if a recipe for a bow takes 3 sticks and a vine, instead of it being 3 sticks and a vine, it’s a stick, a stick, a stick, and a vine. How can I count all the sticks in item.recipe and store it as a value? Am I going about this the wrong way?

You probably just want to aggregate the items you need from a recipe first before checking if you have enough in your inventory.

So if a recipe requires stick, stick, stick and vine, run through the crafting recipe and tally all the items needed, perhaps storing it in a Dictionary<Item, int>. So the aforementioned becomes Stick x 3, Vine x 1. Then it’s easier to check if there’s enough items in the players inventory.

Side note, comparing items by name is pretty flaky. If the items are scriptable objects then you can just compare them directly (== operator). Otherwise I’d implement an explicit comparison method, which is usually best done by implement IEquatable<T>.

1 Like