Notifications
Article
Unity Tips: Scriptable Objects
Published 15 days ago
16
0
If you are new to Unity or have not yet come to know Scriptable Objects, you are in the right place!

What is a Scriptable Object?

First let’s look at the definition Unity gives us
Scriptable Objects are amazing data containers. They don’t need to be attached to a GameObject in a scene. They can be saved as assets in our project. — Unity
The definition that Unity gives us is quite clear, but I’m sure there can be doubts.
First of all, we must understand that SOs are used to store information. They are very useful to save configurations for your application / game as well as for the editor, yes! you can also use them for your editor tools! : D
Tip: The reason why it can be used both in the editor and in your applications is because it is incorporated under the UnityEngine library.

How do you create a Scriptable Object?

In this example we will create an SO where we can save the information we want and then use it in the editor and in our game.

First let’s start by creating a class that inherits from ScriptableObject.
using UnityEngine; public class ScriptableApplicationSettings : ScriptableObject { }
All right! Now what you have to do is create the famous .asset that is generated based on this class. To do this there are two ways:

CreateAssetMenu

using UnityEngine; [CreateAssetMenu(fileName = "ApplicationSettings", menuName = "ApplicationSettings/Create")] public class ScriptableApplicationSettings : ScriptableObject { }
fileName: The name of the file with which Unity will save. In this case it will be ApplicationsSettings.asset
menuName: This will be the submenu within the Assets tool.
If we click on it we will create our .asset file in the root of our project with the name that we have indicated but if you want you can rename it later.
Tip: The file will be created inside the folder that we have selected.

AssetDatabase.CreateAsset

The other way is to create it manually through an editor script, which allows us to modify the instance that we want to save previously and also choose the folder where to save it.
Tip: The folder must already exist or Unity will throw us an error.
Tip: Since we are creating an Editor script, we must place it inside a folder called Editor
using UnityEditor; using UnityEngine; public class ApplicationSettingsMenuItem { private const string FileDirectoryPath = "Resources/ApplicationSettings/"; private const string File = "ApplicationSettings.asset"; [MenuItem("Application Settings/Create")] public static void CreateApplicationSettingsFile() { // Creates an Instance of ScriptableApplicationSettings var applicationSettings = Editor.CreateInstance<ScriptableApplicationSettings>(); // Creates the folder path System.IO.Directory.CreateDirectory(System.IO.Path.Combine(Application.dataPath, FileDirectoryPath)); // Creates the file in the folder path AssetDatabase.CreateAsset(applicationSettings, "Assets/" + FileDirectoryPath + File); } }
After Unity compiles the code, a Menu will be enabled in the toolbar.
Pressing Create will create the .asset file inside the folder we assigned.

Decorating our Scriptable Object

Perfect! Now that we know what they are and how to create them we can start to store information on them.
All you have to do is start placing objects that can be serialized.
Serialization is the process of translating data structures or object state into a format that can be stored (for example, in a file or memory buffer) — Wikipedia
using System.Collections.Generic; using UnityEngine; [CreateAssetMenu(fileName = "ApplicationSettings", menuName = "ApplicationSettings/Create")] public class ScriptableApplicationSettings : ScriptableObject { public string MyString; public int MyInt; public float MyFloat; public List<int> MyList; public MyStruct MyStruct; public GameObject MyGameObject; public MyCustomClass MyCustomClass; } [System.Serializable] public struct MyStruct { public string key; public string value; } [System.Serializable] public class MyCustomClass { public string SomeValue; public GameObject SomeGameObject; }
This are some object examples we can use in SOs. And now we can see our ApplicationSettings in the Inspector revealing object names and values. Try playing with objects and setting them values.
So, let’s stop here and make a summary of what we did.
  • We have created a class that inherits from ScriptableObject called ScriptableApplicationSettings.
  • We have created an .asset file of type ScriptableApplicationSettings.
  • We have added serializable fields in our ScriptableApplicationSettings class.
  • We could see it in the Inspector.
All the values that we place in our .asset will be saved directly to disk.
Tip: When we save the project with File > Save Project Unity will save all the changes. If we do not, it is likely that we will lose the data when we close Unity without saving.
This is how our .asset file looks if we open it.

How to load Scriptable Objects?

Using Resources.Load

First I will create a class that inherits MonoBehaviour and place it in a GameObject in the scene.
using UnityEngine; public class ScriptableObjectDemo : MonoBehaviour { private const string ApplicationSettingsPath = "ApplicationSettings/ApplicationSettings"; void Start () { var applicationSettings = Resources.Load<ScriptableApplicationSettings>(ApplicationSettingsPath); Debug.Log(applicationSettings.MyString); Debug.Log(applicationSettings.MyInt); Debug.Log(applicationSettings.MyFloat); Debug.Log(applicationSettings.MyGameObject); Debug.Log(applicationSettings.MyList); Debug.Log(applicationSettings.MyStruct); Debug.Log(applicationSettings.MyCustomClass); } }

Using public variable in Inspector

We also create a class that inherits MonoBehaviour and we publish a variable of type ScriptableApplicationSettings and assign it to a GameObject in the scene.
Then we drag our file to the value of the published variable that we see in the Inspector.

Using AssetDatabase

Unlike Resource.Load, AssetDatabase is used to manage files within the editor. You can not place code in your application that uses this class since Unity will not let you build your app.
I will add a Load method to the script created above.
using UnityEditor; using UnityEngine; public class ApplicationSettingsMenuItem { private const string FileDirectoryPath = "Resources/ApplicationSettings/"; private const string File = "ApplicationSettings.asset"; [MenuItem("Application Settings/Create")] public static void CreateApplicationSettingsFile() { // Creates an Instance of ScriptableApplicationSettings var applicationSettings = Editor.CreateInstance<ScriptableApplicationSettings>(); // Creates the folder path System.IO.Directory.CreateDirectory(System.IO.Path.Combine(Application.dataPath, FileDirectoryPath)); // Creates the file in the folder path AssetDatabase.CreateAsset(applicationSettings, "Assets/" + FileDirectoryPath + File); } [MenuItem("Application Settings/Load")] public static void LoadApplicationSettingsFile() { var applicationSettings = AssetDatabase.LoadAssetAtPath<ScriptableApplicationSettings>("Assets/ApplicationSettings.asset"); Debug.Log(applicationSettings.MyString); Debug.Log(applicationSettings.MyInt); Debug.Log(applicationSettings.MyFloat); Debug.Log(applicationSettings.MyGameObject); Debug.Log(applicationSettings.MyList); Debug.Log(applicationSettings.MyStruct); Debug.Log(applicationSettings.MyCustomClass); } }
A new MenuItem will be enabled called Load and when we press on it it will load our .asset showing in the console their properties.

Customize our Scriptable Objects

We can use the CustomEditor attribute to customize and give flexibility to our SOs. We can also nest SOs so we use one ScriptableObject to show others.
I will not go into detail in this post about CustomEditor but I will leave a sample of what can be done.

Are Scriptable Objects and MonoBehaviours the same?

Short answer No. They can be similar in a visual way but they have significant differences between them.
If you have time I recommend you to see this Unite conference video explaining in details the differences.

Summary

Scriptable Objects are the perfect objects to store information, such as application settings or levels configuration or a character values. That’s why every time you see that something is configurable, think of them.

Martin Gonzalez
Software Engineer at Etermax - Programmer
3
Comments