Crafting System help!

Hi,

I am currently working on a crafting system using scriptable objects for items and I am trying to compare two lists to see if the items I have in the crafting slots are equal to any of the recipes in another list.

At the moment in the CheckForRecipe() method (i’m not that great with coding) but im assuming it is checkng both lists to see if ANY of the items are the same? But I want to compare and see if ALL the items in ItemList are the same.

Hope this makes sense and TIA!

I am not very good with explaining myself so hopefully the diagram below will help lol.

Crafting Manager script:

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;

namespace Deano
{
    public class CraftingManager : MonoBehaviour
    {
        [SerializeField] PlayerInventory playerInventory;

        public List<Item> itemList;
        public Recipe[] recipes;
        public CraftingSlot resultSlot;

        public CraftingSlot[] craftingSlots;

        void Update()
        {
            CheckForSlotItem();
            CheckForRecipe();
        }

        void CheckForSlotItem()
        {
            foreach (CraftingSlot slot in craftingSlots)
            {
                //If a crafting slot has a child i.e... has an item in the slot
                if (slot.transform.childCount > 0)
                {
                    //Set the slots item to the item in the slot
                    slot.item = slot.gameObject.transform.GetChild(0).GetComponent<InventoryItem>().Item;
                    slot.itemInSlot = true;
                }
                else
                {
                    itemList.Remove(slot.item);
                    slot.itemAddedToList = false;
                    slot.itemInSlot = false;
                    slot.item = null;
                    
                }

                if (slot.itemInSlot == true)
                {
                    if (slot.itemAddedToList == false)
                    {
                        itemList.Add(slot.item);
                        slot.itemAddedToList = true;
                    }
                }
                else
                {
                    slot.itemInSlot = false;
                    slot.itemAddedToList = false;
                    itemList.Remove(slot.item);
                }
            }
        }

        void CheckForRecipe()
        {
            resultSlot.item = null;

            Debug.Log("Checking for recipe");

            for (int i = 0; i < recipes.Length; i++)
            {
                Debug.Log("Looping through recipes");

                if (itemList.Any(x => recipes[i].materials.Any(y => y == x)))
                {
                    Debug.Log("Can craft item");
                }
                else
                {
                    Debug.Log("Cannot craft item");
                }
            }
        }
    }
}

Recipe SO script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Deano
{
    [CreateAssetMenu(fileName = "Recipe", menuName = "ScriptableObjects/Crafting Recipe")]
    public class Recipe : ScriptableObject
    {
        public List<Item> materials;
        public Item craftedItem;
        public int craftedAmount;
    }
}

You and a gazilion of other developers who already published their read-to-use systems both on the store and for free on GitHub. It may take a little time to scan the candidates but unless you have fun implementing such a system, it’s effectively reinventing the wheel (aka waste of your time). :wink:

It helps if you name things properly. There aren’t any coordinates here so x and y are inappropriate names for “material” (x) and “recipeMaterial” (y) if I’m not mistaken.

The Any() method will return if any one of the conditions is true. So your loop checks if you have any material in itemList where the currently enumerated recipe also contains that same material. Since you loop over all recipes this makes even less sense. In other words: this check isn’t doing what you want.

If you find LINQ confusing, use the good old fashioned way of using conditionals. I often prefer this for complex logic because LINQ keeps failing my brain’s expectations for some reason.

1 Like

As above, don’t use LINQ for this kind of stuff. Think through and write out the logic yourself. In this case it’s pretty straight-forward: you loop through the recipes, and for each list of input items you check if your current ingredients matches that list. Both collections should have the same number of items, and the same items in the same order. You just need another loop to do the latter.

I mean how else are you going to learn? Using an off-the shelf solution isn’t going to teach them much.

1 Like