- Home /
Why use a scriptable object instead of MonoBehaviour?
So for ages now I've been storing data that I want to share between objects in a separate class. I simply drop that script onto an empty GameObject and then create a prefab from that GameObject. Voila. I now drag that prefab onto every object I want to share the data with. Done.
Then I watch this video on the Learn section explaining that ScriptableObjects are great for data storage. First you create a script that lists the data you want to store, then you create a second script that creates an .asset file from your script, you then simply drag that script onto every object you want to share the data with. Done.
Now, to me, it sounds like we are doing exactly the same thing except I am using MonoBehaviour, dragging it onto an empty GameObject and then dragging the GameObject into the project's tab... while they suggest using ScriptableObject and creating a separate script to generate the resource via code instead of just dragging something out of the scene.
So this leads me to wonder: What's the difference? Why would I want to go through the hassle of creating an .asset when creating a .prefab results in exactly the same end result (just quicker and easier)?
If there is no difference then why does ScriptableObject even exist? What's it's purpose? According to that excruciatingly painful video to watch, ScriptableObject exists for this purpose. Is that all? Or what am i missing?
A $$anonymous$$onoBehaviour allows to store default data. If you want a Car with different values, you need two different $$anonymous$$onoBehaviour (DriveController and then two inheriting classes with overriding values), but maybe you just want the same DriveController with different values, this is where you use the ScriptableObject. You could also use two json files, same same but different.
There is also the associated memory allocation of the data. Each time you create an instance of the prefab you are creating a copy of the data, which now belongs to the gameobject your script is attached to. A scriptable object is passed by reference, so there is only ever one copy of the data, shared by every game object that references it. This might not have much of a performance impact in your game, but if you were storing a large amount of shared data, then it’d be preferable to use a scriptable object.
Source: http://docs.unity3d.com/$$anonymous$$anual/class-ScriptableObject.html
I get what you are trying to day but remember, once you have a reference to the prefab in yoir other prefabs, there is no reason to first instantiate the prefab for you to use it.
In the system I explained above I simply create the prefab then link it to my 3 or 4 gameobjects and use the stored values. If I want two cars with different values I would create 2 such prefabs and link the relevant one to where I want to use it. Exactly the same as with ScripableObject assets. I never instantiate the ScripableObjects or the prefabs so the required resources is a bit of a moot point.
Tanoshimi's answer sounds most correct at the moment and confirms what I was thinking: Both methids are equal so pick what you like best and go with it. The reason for this question was to find out if there was anything significant that I was overlooking.
Answer by DiegoSLTS · May 29, 2016 at 04:32 PM
I know the resources required to instantiate and maintin empty gameObjects is really small and that creating a script and a prefab is easy, but ScriptableObjects exists to allow you to store data in a clean way. The important thing here to me is that a ScriptableObject is, by definition, an asset that contains custom user data, while a prefab could contain anything.
If your team is big and you need a lot of data you'll have to come up with naming conventions or some folder structure that must be explained to other people so they know that some prefabs are objects in the game and some others are just data containers. If you use ScriptableObjects to store data you don't have to explain anything, there will be an asset that contains the data it should and nothing else.
ScriptableObjects are a good solution for storing level data, weapon data, and so on. Everything that you might store in a text file and then parse is a good candidate for a ScriptableObject, which also has other advantajes, like having the serialization and deserealization built-in and allowing references to project's assets.
Also, note that you don't need to have the ScriptableObject script and a second script to create the asset, there's an attribute you can add to the ScriptableObject so it shows up in the "Asset" menu: http://docs.unity3d.com/ScriptReference/CreateAssetMenuAttribute.html
So basically just do it because it is the right way to do it. I guess I can get behind that. That menu attribute is useful to know about. I have very little experience with using attributes but I think once I get the syntax down that could actually make ScriptableObjects easier to create prefabs... Cool. Thanks for the link.
If both methods are fine but one is more right than the other while also being easier to create then it just makes sense to use that one. That attribute also answers my question...it does have something the other does not: an easier, faster, proper way to create. Thanks
[CreateAsset$$anonymous$$enuAttribute (fileName="SpriteList.asset", menuName="Sprites List")]
public class SpritesList : ScriptableObject {
public Sprite[] icons;
}
That attribute makes generating data assets so incredibly easy! That was exactly what I wanted to know. Thanks a lot DiegoSLTS :D
Since this answer was posted, there was a very excellent talk about scriptable objects and why they are more useful than $$anonymous$$onobehaviour in different scenarios. Worth your time to learn:
Thanks for sharing this. I've been using Unity off and on for a while now, but never realized this. I've been creating custom editors this whole time, which is often massive overkill.
Answer by tanoshimi · May 29, 2016 at 10:24 AM
There's not much difference - if you've got a system that works for you, I would recommend sticking to it. ScriptableObjects don't derive from Monobehaviour. That means that they don't (and can't be) attached to objects in the scene hierarchy. Using your system, you're having to create an empty gameobject to attach the monobehaviour to, which contains an unnecessary transform component. You're deriving no benefit from it being instantiated in the scene, and it's costing you (a little bit of) resources to do so. But it's no real biggie.
Exactly what I want, yes. I have 3 completely different classes that each have to keep a reference to 30 Sprites so it can load the appropriate one when the time comes. When I have to add a new type of object to the game I first have to hunt for the various prefabs in the project hierarchy (Some in resources, others not, some in subfolders etc) so I can add the new sprite to each and then finding the corresponding class to use the sprite.
Ins$$anonymous$$d, I create a prefab that only lists the sprites, drag that into evey one of the orefabs that use those sprites and this way I just need to add the sprite once and all prefabs know about all sprites I use. I don't need to ever instantiate the prefab in the scene and thuss not being able to doesn't bother me. Being derived from $$anonymous$$onoBehaviour and thus being ABLE to, even though I don't do it, not sure if that really is any overhead or not but as I said above, I wanted to know if there is anything significant that would make one better than the other. It seems not, so far, unless you actually instantiate it.
I have already streamlined the process of creating this data file to a single function call created statically inside a kit that is always included in all my kits. As such I have now started doing it "the right way" but was wondering what was wrong with how I've been doing the exact same thing for the past 8 years. Just curious if it had some super cool feature I am yet to discover...