Unity: ScriptableObjects Basics

3 minute read

ScriptableObjects: what are they good for?

After some experimenting we have found ScriptableObjects to be best used as data containers that are easy to create and customize in code with a very streamlined creation process in the editor.

Example: Upgrades

Imagine you need a way to create different kinds of upgrades for the player in your game. I am not going to address all the logic you’ll need to actually apply and use the upgrades, just how to come up with a quick way to store values for the upgrade information itself. As an example let’s say you want to create an upgrade that boosts the player’s max health. We want to know the following about this upgrade:

  • Name of the upgrade (for purposes of showing it in any menus in the game)
  • Description of the upgrade (ditto)
  • Required player level for the upgrade
  • Health boost amount

You could of course go about doing this by creating a HealthBoostUpgradeInfo MonoBehaviour that has public fields for required information, sticking it on a game object, making a prefab out of it, then referencing the prefab in the editor and interacting with it using GetComponent<>() in other classes in your game, but what if you need to make more HealthBoostUpgradeInfo prefabs with different values in the fields? You’ll either have to repeat the creation process in the scene and make a new prefab for each one, or duplicate existing prefabs, change the names and make sure you have changed every single field on the new prefab. If you end up with other MonoBehaviours in your game that need to reference the info on the various upgrades, you’ll be doing a lot of dragging and dropping from the folders to the inspector, which can become troublesome as your project grows.

ScriptableObjects are much more suitable to this task. They offer the following benefits:

  • As easy to code as a MonoBehaviour.
  • No need to be attached to a GameObject.
  • Custom editor code allows them to be created very quickly using menus.
  • The selection process in the inspector is automatically aware of them.

Here is the way we would code such a ScriptableObject for one of our own games. We prefer to use the [SerializeField] attribute with private fields instead of just public fields on our classes that can be serialized in the editor. This is better coding practice as it allows us to control what our other code can access and how it can access it. In this example there is no reason for other code to change the fields on this class, but other code will need to read the fields. We also like to use the [Tooltip] attribute when applicable in order to clarify things in the editor. The => (hash rocket) on the properties is a C# 6 feature that streamlines writing a getter for a property. If you don’t have .NET assembly 4.0 enabled in your project settings -> player settings, it won’t work:

using UnityEngine;

[CreateAssetMenu(menuName = "SparrowhawkLabs/Health Boost Upgrade")]
public class HealthBoostUpgrade : ScriptableObject
    [Tooltip("Name of this upgrade.")]
    private string _name;

    [Tooltip("Description of this upgrade.")]
    private string _description;

    [Tooltip("Minimum player level required to apply this upgrade.")]
    private int _requiredPlayerLevel;

    [Tooltip("Amount of the health boost for this upgrade.")]
    private int _healthBoostAmount;

    public string Name => _name;
    public string Description => _description;
    public int RequiredPlayerLevel => _requiredPlayerLevel;
    public int HealthBoostAmount => _healthBoostAmount;

This results in the ability to create HealthBoostUpgrades very quickly as discrete asset files to be referenced later, right in the editor!

Alt Text

You can then set all the fields in the inspector like you would with a normal MonoBehaviour.

Alt Text

No need to drag and drop from the prefab folder to the reference field in the inspector. The editor knows they exist! The UpgradeList script in the image below contains a list of 3 HealthBoostUpgrades that can be set very quickly, like you would a Sprite or Material or AudioClip.

Alt Text

Follow-up post

I’ve got a follow-up post that will show you how you can use inheritance with your ScriptableObjects to streamline your code: Unity: ScriptableObjects and Inheritance