- Home /
Struggling with part of my crafting-algorithm and don't know what my mistake is
Hey =)
I'm searching for a tutorial or some help for a rather simple crafting system. I've laid the groundwork, but I can't seem to wrap my head around the execution.
I have a gameobject called "Sword". Sword needs 2x Wood and 3x Ironbar to be crafted. Now, if I click on Sword, I want a function to check if I have enough crafting materials in my inventory. (<-- this is not implemented yet) If there are enough items, remove their respective amounts and add Sword instead. (<-- I'm stuck at the "remove"-part) If there aren't, Sword's Button-component shouldn't be clickable. (<--I'll cross this bridge once above problem is fixed)
The thing I struggle most with is the "check if I have and remove"-part (last line of the code) :( I've spent almost all of today and yesterday on this single function and it feels like I can't see the forest for the trees. I made several scripts, but this is the one which works for the most part. When I search for crafting-system-tutorials, I seem to find every kind of system except this one. So, maybe I'm just bad at google? Or miss the vocabulary to tell google exactly what I am searching for? Maybe somebody here might be able to point me in a good direction =)?
If you think that pointing out my mistakes is simpler than conjuring up a link, you are very welcome to have a look at my code. Be warned, though: I'm still a bit of a beginner and my code might not be pretty.
My items are built like this (this is an excerpt):
[CreateAssetMenu]
public class Item : ScriptableObject
{
public Sprite sprite;
[Header("Worth")]
public int currentWorth;
[Header("Crafting")]
public bool craftable;
public Item[] craftmaterial;
public int[] craftmaterial_Menge;
[Header("Where do I find this")]
public int currentlyIn_Shop;
public int currentlyIn_Inventory;
}
In the case of Sword, the craftingmaterial is wood and iron bar, craftingmaterial_Menge (needed craftingmaterial) is 2 and 3. This should mean that I need 2 wood and 3 iron bars.
And here is my crafting-script.
public class Crafting : MonoBehaviour {
[SerializeField] private Inventar[] inventar; //My inventory counts four slots.
[SerializeField] private Item[] items; //right now, I have six items. Five are craftingmaterials, one is the craftable sword.
[SerializeField] private CraftingSlot[] craftingslot; //Right now, there is only one entry in this list, since I only have one craftable.
private Item item; //the item I want to craft
private int neededmaterials; //this should take how many different materials I need to craft the craftable.
public void Herstellung (CraftingSlot craftingslot) // function gets the craftingslot via click on the Sword (button component)
{
item = craftingslot.item; //the item I want to craft
int neededmaterials = item.craftmaterial.Length; //how many different materials I need
for (int i = 0; i < neededmaterials; i++) //for every material, I want to hand infos to the next function
{
Debug.Log("Needed different types of materials: " + neededmaterials); //Here, I get the correct amount of different materials shown in the console =)! (2 in the case of sword)
ItemsAusInventarNehmen(item.craftmaterial[i], i, item.craftmaterial_Menge[i]); //This might be a problem. I want to hand the crafting material , the current counter, as well as how many I need of the crafting material to the next function, so it will be used for each needed material.
}
}
public void ItemsAusInventarNehmen(Item tmpItem, int y, int tmpAnzahl) // "TakeItemsOutOfInventory"
{
Item craftingmaterial = tmpItem.craftmaterial[y]; // the craftingmaterial in place y of the array (this works)
Debug.Log("Craftingmaterial " + y + " " + craftingmaterial); // yep, it shows wood and iron bar in the console.
craftingmaterial.currentlyIn_Inventory -= tmpAnzahl; // This is the major head-scratcher. It should take 2 wood and 3 iron bars, but whatever I do, only the wood gets taken out of my inventory correctly. Why o_O?
}
}
One more problem is, that it always thinks that I have every needed material in the needed quantity available, as long as I have at least 1 wood in my inventory. I have a rough hunch about how the "don't to anything as long as you don't have all the required items"-functions might look like, but I think, I might be able to figure that out once I understand why this script only checks for wood, only takes wood, and completely ignores my iron bars :/
Help would be very much appreciated, I feel terribly stuck :/
Answer by Chik3r · Mar 20, 2018 at 11:20 PM
Part 1 of your problem(removing items):
Instead of setting the amount of crafting material in inventory by using craftingmaterial.currentlyIn_Inventory -= tmpAnzahl;
, use item.craftingmaterial[y].currentlyIn_Inventory -= tmpAnzahl;
. Because with craftingmaterial.currentlyIn_Inventory -= tmpAnzahl;
you're just setting the value to the local var of the function, instead with item.craftingmaterial[y].currentlyIn_Inventory -= tmpAnzahl;
you're setting it to the var of the script.
Part 2 of your problem (checking if you have enough items):
Create a function called HasEnoughItems that returns a bool ( bool HasEnoughItems () {}
) and that takes a int called "NeededAmount" ( int NeededAmount
) and a int called "CurrentAmount" ( int CurrentAmount
), and then check if "CurrentAmount" is greater than or equal to "NeededAmount" return true and else return false. How it should look like:
bool HasEnoughItems(int neededAmount, int currentAmount)
{
if(currentAmount >= neededAmount) return true;
else return false;
}
Then in the "Herstellung" function, before doing the "for" loop do another "for" loop that checks if you have enough items:
void Herstellung(...)
{
...
for(int i = 0; i < neededmaterials; i++)
{
if(!HasEnoughItems(item.craftmaterial_Menge[i], item.craftmaterial[i].currentlyIn_Inventory))
{
return; //Exit from the funtion(Herstellung)
}
}
...
}
Part 3(making the button interactive only if you have enough items):
In some part of your code (maybe update) put this:
public Button button;
...
...
for(int i =0; i < neededMaterials; i++)
{
if(!HasEnoughItems(item.craftmaterial_Merge[i], item.craftmaterial[i].currentlyIn_Inventory))
{
button.interactable = true;
}
else button.interactable = false;
...
...
Wow, thank you so, so much, chiker! That is a huge help :) It's 1am right now and I just shut down my computer, but I will try your solutions first thing in the morning. The suggestions for the extra functions look great, too - it would have taken quite a while for me to come up with boolean variables by myself :) Thank you very much for your time and effort and for explaining your codes =)
Your answer
Follow this Question
Related Questions
The imported type 'Inventory' is defined multiple times :<<<< 0 Answers
Simple Crafting and Inventory System 0 Answers
Crafting system NOT like minecraft 1 Answer
Inventory List Crafting HELP 0 Answers
List<> and Crafting null reference. 1 Answer