| Type | Class |
|---|---|
| Namespace | UnityEngine |
| Inherits | Object |
| Lives in | The Project window, as an .asset file |
ScriptableObject
A ScriptableObject is a script that stores data as an asset file instead of living on a GameObject. Use it for things like weapon stats, item definitions, enemy types and game settings that many objects share.
A MonoBehaviour is a worker standing in the scene doing a job. A ScriptableObject is a recipe card in a filing cabinet. It doesn't do anything by itself, but any number of workers can read the same card. Change "Sword damage: 10" to 15 on the card, and every sword in the game uses 15. You don't have to visit each sword one by one.
Attributes
| Attribute | Description |
|---|---|
[CreateAssetMenu(fileName = "...", menuName = "...")] | Put above the class. Adds an entry to the Project window's Create menu so you can make new asset files of this type. |
Static Methods
| Method | Returns | Description |
|---|---|---|
ScriptableObject.CreateInstance<T>() | T | Creates one in memory from code (not saved as a file). Use instead of new. |
Messages
| Message | When it's called |
|---|---|
Awake() | When the instance is created (for assets: when first loaded). |
OnEnable() | When the object is loaded. In the Editor, this also happens after every script recompile and when entering Play Mode. |
OnDisable() | When it goes out of scope or before a recompile. |
OnValidate() | Editor only: a value was changed in the Inspector. |
ScriptableObjects do not get Update, Start, collisions or coroutines. They aren't in a scene.
Code Samples
1. Define the data
using UnityEngine;
[CreateAssetMenu(fileName = "NewWeapon", menuName = "Game/Weapon Data")]
public class WeaponData : ScriptableObject
{
public string weaponName = "Sword";
public int damage = 10;
public float attackCooldown = 0.5f;
public Sprite icon;
}
2. Create assets
In the Project window: right-click > Create > Game > Weapon Data. Make a few ("Sword", "Axe", "Dagger") and fill in their values in the Inspector.
3. Use it from a MonoBehaviour
using UnityEngine;
public class Weapon : MonoBehaviour
{
[SerializeField] private WeaponData data; // drag an asset in here
private float nextAttackTime;
public void TryAttack(Health target)
{
if (Time.time < nextAttackTime) return;
target.TakeDamage(data.damage);
nextAttackTime = Time.time + data.attackCooldown;
}
}
For more patterns (event channels, shared variables, runtime lists), see the ScriptableObjects in a Game tutorial.
What happens at runtime
- When a scene loads and a component references a ScriptableObject asset, Unity loads that asset once into memory.
- Every component that references the same asset gets the same object. 100 enemies with the same
EnemyDatashare one copy, which saves memory compared to 100 copies of the same numbers. - In the Editor: if your code changes a field during Play Mode, the change is saved to the asset file and stays after you stop playing.
- In a build: changes last only until the game closes. They are never saved to disk.
JsonUtility).Common Mistakes
- Changing shared data at runtime by accident.
data.damage += 5for a power-up changes it for every weapon using that asset (and permanently in the Editor). Copy the value into a normal field first, orInstantiate(data)to get a private copy. - Using
new WeaponData(). UseScriptableObject.CreateInstance<WeaponData>(). - File/class name mismatch. Just like MonoBehaviours,
WeaponDatamust be inWeaponData.cs.
See also
This page is a simplified, AI-assisted interpretation. For the complete and authoritative reference, see the official Unity documentation.