Scriptable Objects 1 — Introduction
If you’ve ever found yourself creating dozens of similar MonoBehaviour scripts just to hold data, or struggled with managing game configurations across multiple scenes, ScriptableObjects are about to become your new best friend.
ScriptableObjects are Unity’s way of creating data containers that exist outside of GameObjects. Think of them as pure data holders that can be saved as assets in your project and shared across multiple scenes and objects.
Unlike MonoBehaviours, which need to be attached to GameObjects, ScriptableObjects exist independently. This makes them perfect for storing configuration data, item definitions, enemy stats, and much more.
Here’s the key difference: MonoBehaviours are for behavior and logic, while ScriptableObjects are for data and configuration.
Basic ScriptableObject Implementation
Let’s create our first ScriptableObject. I’ll start with a simple weapon data container:
using UnityEngine;
// The CreateAssetMenu attribute allows us to create instances
// of this ScriptableObject directly from the Unity Editor
[CreateAssetMenu(fileName = "New Weapon", menuName = "Game Data/Weapon")]
public class WeaponData : ScriptableObject
{
[Header("Basic Properties")]
public string weaponName;
public Sprite weaponIcon;
public float damage;
public float fireRate;
public int magazineSize;
[Header("Audio")]
public AudioClip fireSound;
public AudioClip reloadSound;
[Header("Effects")]
public GameObject muzzleFlash;
public GameObject impactEffect;
// Method to calculate DPS for balancing purposes
public float CalculateDPS()
{
return damage * fireRate;
}
// Validation method that runs in the editor
private void OnValidate()
{
// Ensure damage is never negative
damage = Mathf.Max(0f, damage);
fireRate = Mathf.Max(0.1f, fireRate);
magazineSize = Mathf.Max(1, magazineSize);
}
}Notice the CreateAssetMenu attribute — this adds a menu item to create new instances. The OnValidate method ensures our data stays within valid ranges, and I’ve included a utility method to calculate DPS for game balancing.
Get Code_With_K’s stories in your inbox
Join Medium for free to get updates from this writer.
Now you can find the scriptable object in the file menu
Usage With Monobehaviours
Now lets demonstrate how to use the object scriptable object with monobehaviours
using System;
using UnityEngine;
public class WeaponController : MonoBehaviour
{
[Header("Weapon Configuation")] [SerializeField]
private WeaponData weaponData;
[Header("Runtime Components")]
[SerializeField] private AudioSource audioSource;
[SerializeField] private Transform muzzlePoint;
private float lastFireTime;
private int currentAmmo;
private void Start()
{
InitializeWeapon();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
Fire();
}
if (Input.GetKeyDown(KeyCode.R))
{
Reload();
}
}
private void InitializeWeapon()
{
if (weaponData == null)
{
Debug.LogError("Weapon data is not assigned");
return;
}
currentAmmo = weaponData.magazineSize;
if (audioSource == null)
{
audioSource = GetComponent<AudioSource>();
}
}
private void Fire()
{
lastFireTime = Time.time;
currentAmmo--;
if (weaponData.fireSound != null && audioSource != null)
{
audioSource.PlayOneShot(weaponData.fireSound);
}
if (weaponData.muzzleFlash != null && muzzlePoint != null)
{
GameObject flash = Instantiate(weaponData.muzzleFlash, muzzlePoint.position, muzzlePoint.rotation);
Destroy(flash, 0.1f);
}
Debug.Log($"Fired, our current ammo is {currentAmmo} ammo, weaopn name {weaponData.name}");
}
private void Reload()
{
currentAmmo = weaponData.magazineSize;
if (weaponData.reloadSound != null && audioSource != null)
{
audioSource.PlayOneShot(weaponData.reloadSound);
}
}
public string WeaponName => weaponData.weaponName;
public int CurrentAmmo => currentAmmo;
public int MaxAmmo => weaponData.magazineSize;
public Sprite weaponIcon => weaponData.weaponIcon;
}Now attach this script to any gameobject in the scene , i have attached it to the main camera
Also assign the weapon data scriptable object in the weapon data field on the WeaponController component attached to the camera.
Testing
Now if you run the game and press ‘A’ key you should see a debug message for firing and ‘R’ key will show you a debug message for reloading.
Conclusion
This was a very basic and brief introduction to scriptable objects, in the next part we will dig deep into scriptable objects and how we can leverage them to create complex systems for our games.
If you prefer a video tutorial you can watch it here https://youtu.be/yR-poIkdflU
If you have read till here don’t forget to share , your support means a lot :D










