Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Prefabs vs Scriptable Object

Discussion in 'Editor & General Support' started by TheThunderBirds, Nov 15, 2016.

Thread Status:
Not open for further replies.
  1. TheThunderBirds

    TheThunderBirds

    Joined:
    Nov 15, 2016
    Posts:
    1
    I'm creating an online hack and slash game and I'm wondering how I should save the enemies. Currently I'm able to save them as prefabs and as scriptable objects. What are the pros and cons of both? Prefabs seem to be easier but less clear when you have a lot of them.
     
  2. Chella90

    Chella90

    Joined:
    Sep 11, 2014
    Posts:
    8
  3. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    576
    Imagine a scenario where you have a prefab "Enemy" that has a certain model and animations and ai.
    Now you want to create a variation of the same enemy with same everything, but different stats.
    You could have a prefab for each variation, sure. Now later you decide to rework how the prefab is structured, you want to change hierarchy, add scripts, colliders, many internal changes. That would mean that to maintain that enemy you would have to manually process each variation and manually make changes to hierarchy etc, this is very time consuming and error prone.
    Now instead of storing variations as prefabs you can have a single prefab for the enemy, and pull the variations from scriptable objects.
    Lets say scriptables only contain fields like - health, armor, speed...
    You instantiate your enemy, and you inject the scriptable object in it, and enemy uses the scriptable object fields as his own.
    So he goes like

    Awake() {
    myHealth = data.Health;
    agent.speed = data.Speed;
    ...
    }

    This way you have a single prefab that is easy to maintain and data that is agnostic of the type of object you want to inject it in.
     
  4. odan-travis

    odan-travis

    Joined:
    Apr 12, 2019
    Posts:
    10
    @pointcache Sorry for the bump, but isn't the point you're making kind of obsolete now with hierarchical prefabs? Because I could have a prefab for whatever contains the stats of the enemy, and wouldn't have to update it in the "higher level" prefab that constructs the rest of the enemy.

    When you made the post you were certainly right, since there was no way no inside prefabs to make reference to another prefab.

    I still prefer ScriptableObject, but the reason is different: ScriptableObjects just have less overhead. If you make a prefab containing a single gameobject that has a component with whatever data you would otherwise put onto a ScriptableObject, every prefab (and if you actually spawn instances of that prefab, every instance) has all the baggage of a gameobject attached to it, such as transforms, the various attributes that you see when you type "component.gameobject.[xyz]", and so forth. ScriptableObject presumably has none of that and is thus much more lightweight on memory.

    Assuming Unity has no magic way to optimize away that extra memory overhead, if you have a game where, let's say, you have thousands of different prefabs (or alternatively ScriptableObjects), say 1 for every monster, item, upgrade, buff and whatever else is in your game, you may come out with megabytes less memory used in the ScriptableObject case. That not only saves memory (a few megabytes is nothing today, even on smartphones), but it also doesn't pollute the CPU cache with data you don't need every time you just want to, say, iterate through a bunch of items to get their stats.
     
  5. pointcache

    pointcache

    Joined:
    Sep 22, 2012
    Posts:
    576
    I want to add that the process of instantiation of a gameobject means it has to be injected into scene graph and it has to be updated, then all overhead the unity callbacks, component registration.

    There are certain hierarchical scriptables i've seen, I don't know if they work or not, and im contemplating finally writing my own, but im very weary of it, given how crucial is data safety and all the edge cases with editor and changes propagation.

    https://assetstore.unity.com/packag...g/sohi-hierarchy-for-scriptable-objects-98195
    https://odininspector.com/community-tools/59D/nested-scriptable-object-attributes-(field-and-list)
     
    Chris_Martin likes this.
  6. Limnage

    Limnage

    Joined:
    Sep 12, 2013
    Posts:
    41
    Apologies for the bump, but this example shows why I stopped using ScriptableObjects.

    First, in the event that you want to restructure your game data (which happens all the time during development). All your existing SOs will break. Unity says use something like [FormerlySerializedAs], but this is an extremely cumbersome and unrealistic solution.

    Second, is the problem of code architecture. Let's expand this example of an SO for enemy data. Imagine that different enemies have different stats/resources. Some use mana, others use energy or rage or spirit or heat or blood whatever. Some have armor, others do not, etc. In the usual way Unity describes SOs, you'd have to put all of these in the God SO

    EnemySO {
    health
    mana
    energy
    rage
    spirit
    heat
    blood
    armor
    etc.
    }

    This is obviously bad code and data design. You should instead be using something like a composition-based approach where an enemy only has the stats it needs. So then you might do something like put List<IStat> in the SO, but at that point you're on your own. You'll have to find you own way to make the editor work and serialize nicely, and even doing something simple like ensuring that the Enemy doesn't have duplicate stats (e.g. two health stats) becomes non-trivial. Even in this various basic example, SOs don't provide the functionality necessary.
     
  7. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,917
    Why did you bump an old thread when I already proved you can do what you want simply by using
    SerializeReference
    in another thread?

    How about spending some time solving your problems rather than having a winge in old threads?

    Unity's not going to support what you want out of the box as it all depends on specific implementation details.
     
    zombiegorilla and Kurt-Dekker like this.
Thread Status:
Not open for further replies.