Get Your Personalized Game Dev Plan Tailored tips, tools, and next steps - just for you.

This page may contain affiliate links.

When to Use Scriptable Objects Instead of Prefabs in Unity

Posted by Gemma Ellison
./
August 6, 2025

Scriptable Objects vs. Prefabs: An Indie Dev’s Guide (and Confessions)

Okay, so I totally get it. You’re starting out in Unity, and everything looks like it should be a Prefab. Enemy? Prefab. Power-up? Prefab. That random piece of space junk floating by? Prefab! I mean, isn’t that what they’re for? Making copies?

Well, kind of. But thinking like that is how I ended up with five different Prefabs for “Space Rock,” each with slightly different stats that I had to manually update across all instances. It was a nightmare. Don’t be like me.

The Allure (and Trap) of the Prefab

Prefabs are great! Seriously. They are templates for GameObjects, allowing you to create multiple instances with shared properties. Change the Prefab, and all its instances update. Magic! Except when it’s not.

My initial thought was, “Every thing is an object, therefore, everything should be a Prefab.” Wrong! This led to Prefabs holding static data that shouldn’t be tied to a GameObject. Think character stats: health, damage, movement speed. If you bake these values into a Prefab, you’re making things way harder than they need to be.

Imagine you have a “BasicEnemy” Prefab with 10 health. Now you want to create a slightly tougher enemy. Do you duplicate the Prefab and change the health? Now you have two nearly identical Prefabs to maintain. What if you want a temporary health buff for all BasicEnemies? Uh oh.

Enter the Scriptable Object: Data’s Best Friend

Scriptable Objects (SOs) are data containers. They hold information independent of GameObjects. Think of them as blueprints for data, not for objects.

Here’s where I slapped myself: Instead of storing enemy stats on the “BasicEnemy” Prefab, I should have created a “EnemyStats” Scriptable Object. This SO holds the health, damage, etc. Then, the “BasicEnemy” Prefab simply references this SO.

Let’s refactor!

  1. Create a new C# script called EnemyStats.cs:

    using UnityEngine;
    
    [CreateAssetMenu(fileName = "EnemyStats", menuName = "ScriptableObjects/EnemyStats", order = 1)]
    public class EnemyStats : ScriptableObject
    {
        public int health = 10;
        public int damage = 2;
        public float moveSpeed = 3f;
    }
    
  2. In Unity, right-click in your Project window, go to Create -> ScriptableObjects -> EnemyStats. Name it "BasicEnemyStats". Tweak the values in the Inspector.

  3. Create a new script, Enemy.cs, to attach to your “BasicEnemy” Prefab:

    using UnityEngine;
    
    public class Enemy : MonoBehaviour
    {
        public EnemyStats stats;
    
        void Start()
        {
            Debug.Log("Health: " + stats.health);
        }
    }
    
  4. Attach Enemy.cs to your “BasicEnemy” Prefab. In the Inspector, drag your “BasicEnemyStats” SO to the stats field.

Now, your “BasicEnemy” Prefab uses the data from the Scriptable Object! Need a tougher enemy? Create a new EnemyStats SO with higher values and assign it to a new enemy Prefab (or even an instance of the existing one!). Want to buff all BasicEnemies? Change the one BasicEnemyStats SO. Boom!

Flexibility is Key (and Saves Sanity)

The real win here is flexibility. Scriptable Objects promote loose coupling. Your GameObjects don’t directly contain the data; they reference it. This makes your code easier to maintain, modify, and reuse.

I was initially resistant to SOs because they felt “too abstract.” But trust me, the slight upfront investment pays off big time down the road. Especially during prototyping.

Prototyping with Scriptable Objects: Build the Right Thing

This is where Scriptable Objects really shine. Before you even think about creating a bunch of Prefabs, use SOs to define your game’s data.

Want to experiment with different enemy wave configurations? Create a WaveConfig Scriptable Object that holds an array of EnemyStats SOs and spawn timings. Tweak the SO, and instantly see how different enemy compositions feel in-game. No Prefab juggling required!

This approach allows you to rapidly iterate on your game’s core mechanics before committing to specific visual representations. You’re building the right thing, then making it pretty.

Common Pitfalls (and How to Avoid Them)

  • Over-reliance on Prefabs: Just because something is an object doesn’t mean it needs a Prefab, especially if it’s primarily data.
  • Modifying SOs at runtime (without copying): SOs are persistent. Changes you make during play mode will persist when you stop playing, which is not always what you want. Duplicate the SO or create a temporary copy if you need to modify data at runtime.
  • Ignoring the benefits of SO inheritance: You can create SOs that inherit from other SOs, allowing you to create variations on existing data without duplicating everything.

Track Your Progress (or You’ll End Up Like Me)

Seriously, document your journey. I wish I had started a proper game dev journal from the beginning. Reflecting on my initial Prefab obsession, and how Scriptable Objects helped me escape it, is invaluable. A game development log helps you see patterns, identify mistakes, and celebrate wins. It keeps you focused and motivated.

Plus, when you hit a wall (and you will), looking back at your progress can remind you how far you’ve come. Don’t just blindly code; think about your process.

Speaking of thinking about your process, start your game dev journal today and track your progress like a pro! You’ll thank yourself later.

My Confession: I Still Mess Up Sometimes

Even now, after years of using Unity, I occasionally fall back into the “Prefab everything!” trap. It’s easy to do, especially when you’re under pressure. But now, I recognize the signs and quickly course-correct. Learn from my mistakes (and hopefully, my solutions!). Happy developing!