Crafting System

No worries man, take your time :slight_smile:

You and me both… one reason I’m not an instructor yet.

You make ONE COURSE, ONE COURSE AND I’M FLAT OUT BUYING IT. NO QUESTIONS ASKED!

1 Like

hey @bixarrio any updates about how to get the UI set up? :slight_smile:

Here is the breakdown:

We have the game object that holds the whole crafting UI

On here we have only the CraftingUI script

Inside we have the button in the top-right corner that will just set the above object inactive.


We also have another game object that holds the background image

Under the crafting window, we have the title, the recipe list and the item details


The recipe list is not a straight forward game object, but a ScrollView of which I removed the horizontal scrolling

I added a vertical layout group, and content size fitter to the content game object (I believe Sam discusses these in the course);

It also holds the RecipeListUI script

The item details panel has the name of the resulting item, as well as its icon and description. At the bottom is the ingredients list and the craft button. The ingedients list here is similar to the recipe list except that it’s horizontal instead of vertical


There is also an image that covers the whole button. It has been set to ‘filled’, etc

The crafting button and the image are buttons that are bound to the CraftingItemUI


The Recipe prefab (that is instantiated into the recipe list) is straight forward.

The same goes for the Ingredient prefab


I hope all this makes sense. Lemme know if I missed something, or if it’s ubnclear

So, my subconscious alerted me to 2 issues (so far) with the code I presented. This is, of course, aside from the parts where I’m not doing any null checks, etc.

  1. If you set up a recipe that has the same ingredient in 2 entries - for example this
    image
    the player will be able to craft the item even if they only have 1 hat. This is because the system checks each ingredient individually and will find the same hat twice and conclude that the ingredients are good. A solution may be to either validate the recipe at design time and highlight the issue, or to combine those two entries into one before presenting the ingredients to the crafting system

  2. With the the way the crafting is currently set up, if the craft duration is sufficiently long there is some potential for duplication. One way is to start the crafting and then switching to an item that you cannot craft. The item details will be loaded, but the coroutine continues to run. The code is actually quite bad in that coroutine. When it is complete, it will attempt to remove the new recipes ingredients (which it may not be able to because it was never there to begin with) and then add the result of the original recipe to the inventory. This will leave the ingredients of the original recipe and add the result. I have updated CraftingItemUI above to fix this issue. It will use the recipe that was passed to the coroutine, but it will also cancel the coroutine if the item changes.

Meanwhile I’m here trying to figure out if that’s an Image UI, a Panel UI or what type of item that is, to create from the Unity 2D Toolkit…

@bixarrio not exactly sure where I went wrong, but I keep getting this NRE whenever I click on my Crafting Table:

MissingReferenceException: The object of type 'RecipeItemUI' has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
RPG.Crafting.UI.RecipeListUI.Setup (RPG.Crafting.CraftingRecipe[] recipes) (at Assets/Project Backup/Scripts/Crafting/UI/RecipeListUI.cs:27)
RPG.Crafting.UI.CraftingUI.OnCrafting (RPG.Crafting.CraftingRecipe[] recipes) (at Assets/Project Backup/Scripts/Crafting/UI/CraftingUI.cs:25)
RPG.Crafting.CraftingTable.HandleRaycast (RPG.Control.PlayerController callingController) (at Assets/Project Backup/Scripts/Crafting/CraftingTable.cs:78)
RPG.Control.PlayerController.InteractWithComponent () (at Assets/Project Backup/Scripts/Control/PlayerController.cs:150)
RPG.Control.PlayerController.Update () (at Assets/Project Backup/Scripts/Control/PlayerController.cs:79)

Apart from that, for some reason my own UI (when it opens the first time before running the NRE), is kind of… transparent…? Like this:

Oh, and I also get this yellow error whenever I first run my game (if it helps in anyway):

The referenced script on this Behaviour (Game Object '<null>') is missing!
UnityEngine.Resources:LoadAll<RPG.Crafting.CraftingRecipe> (string)
RPG.Crafting.CraftingTable:Start () (at Assets/Project Backup/Scripts/Crafting/CraftingTable.cs:24)

Please help, anyone :slight_smile: (I tried following the instructions as close as possible, but sometimes there’s a ‘RecipeUI’ that comes out of nowhere, or ‘IngredientUI’ for instance… basically stuff that shows up out of nowhere in the tutorials makes it hard to follow sometimes)

Edit: Re-checked the entire tutorial… still got the same issues

and this is my Crafting UI Hierarchy, if that helps:

I got this error initially. You have to make sure that you unsubscribe the events. When the save system loads the save, it reloads the scene. If the events are not unsubscribed, it fires off to an item that was on the previous instance of the scene and now no longer exists

No idea what this is. I do set the text of the Recipe Item in the list to 50% transparency if the recipe cannot be crafted. Perhaps you got the wrong reference

Don’t know what this is either. Looks like maybe something is persisting this object, but the scripts have been destroyed.

It wasn’t really a tutorial. I just shared the code and what I did. I will try to do better next time.

I made a fork of the RPG github repository and created the crafting system on the code base of the course (and accidentally made a pull request to the course repo🤦‍♂️).

You can find my fork with all the code and UI here:

The code is a little different from the above post, but the system is the same.

I checked my code again and all my subscribed events were eventually unsubscribed to. I’ll cross check, but there’s a good chance that the error originates elsewhere

Edit: I updated my code with your github code, it just got worse… Ahh, I’ll spend the night on this I guess

Edit 2: Reversed the changes. The UI Opens as expected. I added “Recipes” in the CraftingTable.Start() setup, that loads all the resources for that to work, so now the function looks like this (this is what eliminates the NRE):

private void Start()
        {
            _allRecipes = Resources.LoadAll<Recipe>("Recipe");
        }

but no visible recipes yet (even though I do have recipes created in Unity, and I cross-checked my UI setup and code in every possible way…), so now my crafting screen in-game, when I click on the Crafting table, looks like this (I deactivated the Raycast Recipe check to get this to work, for now):

Please help me out :slight_smile:

Could you possibly share your project (without the library folder)? Then I can look because I have no idea what’s happening.

The purpose of the repo fork was more to get you an in-game version of the UI.

Alright I sent it to you in a message. Kindly have a look in 10-15 minutes, when it’s done uploading

Edit: @bixarrio upload is done. You can check your messages now :slight_smile:

This happens because you referenced the Recipe prefab in the hierarchy instead of the prefab from the projects folder


The one in the hierarchy is just there so I could see what it will look like. It’s getting destroyed as soon as the new list is getting populated. You could even delete that one

This is because you set the alpha value of the background image to 100 (out of a possible 255)

I didn’t get this error

@bixarrio OK so… yup, apparently setting the Recipe PREFAB did make a significant difference, and the same went for the ingredients list. Problem now is, whilst it detects the Recipes, the button on the recipe is not working. This is the Argument Exception I get instead:

ArgumentException: Object of type 'UnityEngine.Object' cannot be converted to type 'RPG.Crafting.Recipe'.
System.RuntimeType.CheckValue (System.Object value, System.Reflection.Binder binder, System.Globalization.CultureInfo culture, System.Reflection.BindingFlags invokeAttr) (at <88e4733ac7bc4ae1b496735e6b83bbd3>:0)
System.Reflection.RuntimeMethodInfo.ConvertValues (System.Reflection.Binder binder, System.Object[] args, System.Reflection.ParameterInfo[] pinfo, System.Globalization.CultureInfo culture, System.Reflection.BindingFlags invokeAttr) (at <88e4733ac7bc4ae1b496735e6b83bbd3>:0)
System.Reflection.RuntimeConstructorInfo.DoInvoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <88e4733ac7bc4ae1b496735e6b83bbd3>:0)
System.Reflection.RuntimeConstructorInfo.Invoke (System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <88e4733ac7bc4ae1b496735e6b83bbd3>:0)
System.Reflection.ConstructorInfo.Invoke (System.Object[] parameters) (at <88e4733ac7bc4ae1b496735e6b83bbd3>:0)
UnityEngine.Events.PersistentCall.GetObjectCall (UnityEngine.Object target, System.Reflection.MethodInfo method, UnityEngine.Events.ArgumentCache arguments) (at <ba783288ca164d3099898a8819fcec1c>:0)
UnityEngine.Events.PersistentCall.GetRuntimeCall (UnityEngine.Events.UnityEventBase theEvent) (at <ba783288ca164d3099898a8819fcec1c>:0)
UnityEngine.Events.PersistentCallGroup.Initialize (UnityEngine.Events.InvokableCallList invokableList, UnityEngine.Events.UnityEventBase unityEventBase) (at <ba783288ca164d3099898a8819fcec1c>:0)
UnityEngine.Events.UnityEventBase.RebuildPersistentCallsIfNeeded () (at <ba783288ca164d3099898a8819fcec1c>:0)
UnityEngine.Events.UnityEventBase.PrepareInvoke () (at <ba783288ca164d3099898a8819fcec1c>:0)
UnityEngine.Events.UnityEvent.Invoke () (at <ba783288ca164d3099898a8819fcec1c>:0)
UnityEngine.UI.Button.Press () (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:70)
UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/UI/Core/Button.cs:114)
UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:57)
UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction`1[T1] functor) (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/ExecuteEvents.cs:272)
UnityEngine.EventSystems.EventSystem:Update() (at Library/PackageCache/com.unity.ugui@1.0.0/Runtime/EventSystem/EventSystem.cs:514)

We might want to play around with my version of the project a bit… it’s probs gonna be full of weird surprises down the line with the new crafting system :sweat_smile: (I apologize in advance if it’ll take a lot of your time, but I really want this to work)

Edit: This was a fake recipe, a dummy one, hence why it probs didn’t work… The crafting UI now is visible, but is both ugly :stuck_out_tongue_winking_eye: and empty (It’s not loading the Recipes for some other reason. Like… no recipes at all)

Edit 2: Nope, the recipe that ain’t working returns when we keep the following CraftingTable.Start() function content as follows (the tuned one):

private void Start()
        {

            // original line: 
            _allRecipes = Resources.LoadAll<Recipe>("Recipes");
           // tuned line (which results in the errors above and below):
            _allRecipes = Resources.LoadAll<Recipe>("");
        }

(i.e: I deleted “Recipes” from the line), and this one projects the error above again

And it also results in this weird error:

The referenced script on this Behaviour (Game Object '<null>') is missing!
UnityEngine.Resources:LoadAll<RPG.Crafting.Recipe> (string)
RPG.Crafting.CraftingTable:Start () (at Assets/Project Backup/Scripts/Crafting/CraftingTable.cs:16)

I don’t get any of the errors you mention here. I changed none of your code, just fixed the references to the prefabs I mentioned above. Crafting worked fine. There’s a bug where the crafting progress is active when the UI loads that I fixed in the repo.

You should really look at how the UI in the repo was set up.

@bixarrio Can we have a rundown of what you changed to the UI that fixed it? I did some changes too, got it to partially work, but not fully yet (and tbh I’m not sure how to import someone else’s work into mine from git yet, or how to deal with github tbh :sweat_smile:)

Because there’s something I had to set up to get the recipe to show up, which is place the recipe into the recipe prefab, under the event that was over there, as you can see in the screenshot below (circled in blue):

Can this be done automatically through code, or do I have to create multiple recipe prefabs and do that manually? Because if it’s manual, how do we keep setting Recipes up to inject them into the Recipe “Content”? As you can see below, it’s currently limited to just one (or at least that’s my case):

Apart from that, the Crafting button works, but the selection for the recipes-to-craft (the left hand side of the UI, which contains the recipes we can craft), and the green bar that fills up for the duration of the crafting does not work. It’s… static for now (I just want to clean these bugs up tbh)

And neither is my Ingredients’ list Scroll view working properly tbh, where it’s not displaying the proper image… (I think I’ll refer to the git, but I need to know how people do this. Edit: The project on git has issues, so I just let it be for now)

When the CraftingUI opens, I hide the progress image.

It is being done through code. If you used the code from the previous post, the buttons are being set up in the Setup function

public void Setup(Recipe recipe)
{
    _recipe = recipe;
    UpdateUI();
    _button.onClick.AddListener(OnSelect); // <-- here
}

but this code is outdated. The code from the repo does not add the listener in code - it adds it in the inspector - but it does the same thing. And there’s no need to give it a recipe. OnSelect does not take in the recipe

What issues are you having? The repo works fine for me (except that everything is moving at 900mph and the only question here I could find about it has no answers). The code and UI in the repo is what you should be looking at.

I did just that, I hid it manually in the hierarchy, but now it’s not visible at all… (which makes sense btw)

So I’ll use the new code from the Repo now, got it

Ahh… they’re… a lot, I didn’t even bother to look at all of them honestly :sweat_smile:

I have rearranged all the code and stuff in the repo and made a package that you should just be able to import. There is a readme (in the repo as well as the package) with a few instructions that will need to be followed to make it work.

Find the package here

2 Likes

Privacy & Terms