How can i make special usage function?

Hello, I am making an inventory system in unity. now when I use an item from this inventory system, where should I give it to the character and can I make a special usage function for each item?

A typical way is to use ScriptableObjects (SOs). That’s a special parent class somewhat like Monobehavior in Unity. Those scripts are not dragged onto gameobjects but instead can be instantiated as an asset. Sorta like a prefab.
That instance then can simply be dragged into a serialized field of that type on other SOs or Monobehavior.
This allows defining item types independently of scenes.

Now further inheritance works with those. So you’d have for example class InventoryItem: ScriptableObject and then e.g. class Potion: InventoryItem.
The parent class can be abstract and have an Use() method.
Use() is then implemented in your final class (of cpurse with arguments like the Player since the SOs cannot access things from the scene on their own except via “dirty” singletons).

SOs can also have serialized variables by the way (e.g. [SerializeField] int potion_strength).

Your players inventory is then a List<InventoryItem>.

This approach works well for reasonably small games.
For a full on RPG you may want to apply the principle of “Composition over Inheritance” but if that’s entirely new to you, best to keep the scope of the game small :slight_smile:

Yes, I am currently working with ScriptableObjects and I already know it. I give the item prefab to the character’s hand, but since the game I will make will be a Survival game, there will be more items and each item will have its own usage functions. For example, when the gun is in the character’s hand, when you press R, it will remove the magazine or something, but if there is a magazine in the character’s hand, it will start filling it.

Actually, I could put ItemController inside each item prefab and run the function inside that ItemController, but I think inheriting and creating ItemController for each Item type separately will complicate the game. Isn’t there a different way?

Is ItemController the class inheriting from SO? Then that name is rather suboptimal. It is an Item after all, not its controller.

As I said you can use inheritance. E.g. have Reloadable that inherits from InventoryItem and Shotgun inherits from Reloadable. Or also have Gun inbetween.

If that does lead to issues where you’d like to inherit from two different classes (which is not possible in C#) then you have indeed run into what I mention in the last paragraph and you may need to employ Composition.
The idea there is to split up functionalities like Reload into a totally different SO and allow your Item to have a list of those features.

This allows to “compose” the final item out of components, just like you compose a gameobject out of multiple Monobehaviors.

But make sure you actually need this because on the short run, this makes everything a bit more complex. I wouldn’t do that just for a handful of features.

Just experiment with it. Fail fast, fail often :wink:

First of all, this Item system is important for my game because I need to add more items for example: Weapons, Melee weapons, Resources (like Wood), Things for building, Medical items. That’s why this inventory system is so important and I can’t keep it short.

ItemController is not something inherited from SO, it’s a MonoBehavior
Class. Inside ItemController there is a function called OnUse, let’s say, I created something called MedicalItemController and inherited it from ItemController. I override the OnUse function, so I wrote that I increase the health of the character by the value of the ItemSO Can insertion. So far so good and it probably works exactly as I want it to. But now if I create something called a WeaponItemController, if I enter 3 different functions into it, for example 1st Function: Fire (Depends on Left Click) 2nd Function: Change Magazine (connected to R key) 3.Function: Aim (Right Click) let’s say I connected one function to OnUse. How will I do the others? I wonder if I should put an Update() function inside each ItemController and make it listen to each input one by one? Let’s say I solved that, I have to create ItemControllers for each ItemType one by one and I place the ItemControllers in the prefabs, so things will get very complicated after a while.

Actually I can think of some solutions but every idea I come up with is too complicated and I never use those ideas because I will add other items in the future. The ItemController I mentioned above is one of those ideas but I feel like I can get rid of the complexity.

Your OnUse function should not be in the controller class! It shall be in the Item (SO) class.
That way the functionality is tied to the item and not to the controller.

When the player’s ItemController checks for the R key, it uses the instance of InventoryItem to first check whether it is of type “Reloadable” and only then it executes the OnUseR() function of the Reloadable SO instance.

I’d agree with @DragonCoder that ScriptableObjects are normally the way to go. If you want to use composition as mentioned then SerializeReference is quite useful. For example I might have a property like this:

[SerializeReference]
public List<IItemAction> actions;

So I could trigger a sequence of actions like playing sounds, spawning particles, playing animations, healing etc.

Inheriting from a base type will also allow you to filter records e.g. ResourceItem : InventoryItem should only show resource items when assigning them to a recipe. One other nice thing about scriptables is that you don’t need visual monobehaviours e.g. a RPG might let you use a potion during combat or out of combat from the menu (don’t play particle effects or animations, just heal).

One issue I have had in the past with this method is that it doesn’t really work well with complex actions. So I my graph needs branches and starts turning into a behavior tree e.g. targeting, conditional triggers, different target missed actions etc. I’m currently looking at trying the new Unity behaviour graph. I’m thinking about assigning the graph to my inventory scriptable and triggering that on consume. This also lets me reuse logic with sub graphs. One downside is that the blackboard uses string keys so it could be easy to make a bug.

1 Like