Help Understanding ScriptableObjects

I’m an aspiring indie game developer and I am starting to work on my first game. So far it’s been going quite well and I’m really getting the hang of it (quicker than I imagined).

With that said, I’m still pretty new to Unity and C# and one of the things I am working on implementing now is adding items to my game. What I believe I want is to use are ScriptableObjects - something that all of my items will derive from.

My Item class (that all items derive from) is:

using UnityEngine;

[CreateAssetMenu(fileName = "New Item", menuName = "Item")]
public class Item : ScriptableObject {

  new public string name = "New Item";
  public Sprite icon = null;
  public GameObject item = null;

  public virtual void UseItem() {
    Debug.Log("Using " + name);
  }

}

With this code written, I can right click and create new “Items” in Unity. For example, I’ve created a “Sword” asset.

I also setup a very simple “Inventory” script to hold the ScriptableObject that is equipped:

public class Inventory : MonoBehaviour {

  #region Singleton
  public static Inventory instance;
  void Awake() {
    if (instance != null) {
      Debug.LogWarning("More than one instance of inventory found.");
    }
    instance = this;
  }
  #endregion

  public Item selected = null;

}

I dragged my “Sword” asset into the Inventory and linked it. In my PlayerActions script, I use the item like so:

public class PlayerActions : MonoBehaviour {

  Item item = null;

  void Update() {
    if (Input.GetMouseButtonDown(0)) {
      item = Inventory.instance.selected;
      if (item != null) {
        item.UseItem();
      } else {
        // Do something else...
      }
    }
  }

}

Excellent, now when I click I am seeing the message: “Using Sword”. This is great, but I’d like to override the UseItem() function to do something a little more sword-like. I’ve written another script to handle this override:

public class Sword : Item {
  public override void UseItem() {
    base.UseItem();
    Debug.Log("Swinging Sword!");
  }
}

I don’t understand where do I put this new script for it to become effective in my game? I can’t attach this to a GameObject in my game because “the script needs to derive from MonoBehavior”. When I run my game, I’m still seeing the “Using Sword” message.

Could someone give me some pointers? Am I doing it completely wrong?

I think you are on the right way. Here are my suggestions:

  1. An item, on its own, does not make much sense (how do you use a “general” item?), and I don’t think you should give the possibility to have an item asset. You should remove CreateAssetMenu and make the class abstract.
  2. Because Sword inherits (indirectly) from ScriptableObject, and is a real item you can use, you should have the CreateAssetMenu attribute: [CreateAssetMenu(fileName = "New sword", menuName = "Create item/Create sword")]
  3. For every item inheriting from Item, you have to put the CreateAssetMenuAttribute, and implement the UseItem function.
  4. The UseItem function should have a parameter such as Player for example. Thanks to this, you could apply the effect of the item on the player (health potion, …) and you will call the function like this in your Player / PlayerActions script : item.UseItem( this );