Menu
CoddyTech

Data Assets

Part of the Game Architecture in Unity section of Coddy's Unity journey. Lesson 19 of 50.

A farm game grows carrots and pumpkins. A carrot grows for 30 seconds and sells for 5 coins, a pumpkin grows for 90 seconds and sells for 40. Those numbers belong to the crop, not to one plant: as Inspector fields on a Plant script, every carrot in every scene holds its own copy of 30 and 5, and a change means finding all of them. A ScriptableObject keeps data like this in an asset, a file in the project that any number of objects can point at. Its class derives from ScriptableObject instead of MonoBehaviour:

using UnityEngine;

[CreateAssetMenu(fileName = "NewPlant", menuName = "Farm/Plant Data")]
public class PlantData : ScriptableObject
{
    public string plantName;
    public float growTime;
    public int sellPrice;
}

[CreateAssetMenu] puts the class in the Project window's Create menu. Right-click in the Project window, choose Create > Farm > Plant Data, and Unity makes an asset named NewPlant; rename it Carrot, select it, and type Carrot, 30 and 5 into its fields in the Inspector. A Pumpkin asset is made the same way. The class goes in a file named after it, PlantData.cs, as a MonoBehaviour does.

The behaviour stays in a MonoBehaviour with a field of the asset's type. Drag the Carrot asset onto that field, and the script reads the numbers through it:

public class Plant : MonoBehaviour
{
    public PlantData data;
    private float age;

    void Update()
    {
        age += Time.deltaTime;
        if (age >= data.growTime)
        {
            Debug.Log(data.plantName + " is ready, worth " + data.sellPrice);
            enabled = false;
        }
    }
}

A ScriptableObject is on no GameObject and in no scene. It has no Transform, and Unity never calls its Update or Start: it holds data, and the Plant holds the behaviour. When 200 carrots point at the one Carrot asset, setting its growTime to 25 changes all 200. In code, an instance is made with ScriptableObject.CreateInstance<PlantData>(), never with new.

challenge icon

Challenge

Medium

The Hero walks the arena with the arrows. Its name, speed and color are fields of the Hero script, and every new hero would copy them again. Move them into an asset:

  • In HeroData.cs, write HeroData, a ScriptableObject with the public fields heroName (a string), moveSpeed (a float) and color (a Color). Give it [CreateAssetMenu] with the menu name Heroes/Hero Data.
  • In Hero.cs, replace the three fields with one public field data of type HeroData, and use the asset's values where the script used its own.

The project has a Knight asset made with that menu (Knight, speed 3, red), and the Inspector puts it in the Hero's data field. Press Play and walk the Knight around, then Check.

Try it yourself

using UnityEngine;

// HeroData: the hero's name, speed and color, as a ScriptableObject
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Game Architecture in Unity