Scriptable Objects in Unity
In our Zoo app, we’re going to have information cards describing a variety of animals. While it would be OK to individually fill out the information and create a panel manually for each, what if the app grows and suddenly we’ve got hundreds of animals or even thousands of information pages we'd like to display?
Scriptable Objects to the rescue!
Instead of making each information card individually, we’ll be making a template and use scriptable objects to fill it in. Scriptable Objects are merely data containers that we can map to a template, we can make each one of those elements a variable that will be populated by the scriptable object. This is a UI-driven model where the template is the UI and the scriptable object data is the model.
Creating the template:
Let’s take a look at our card:
So we have a background, a title, some information, some more information at the bottom, a logo, an image, and a button to exit. The background was easy enough and fortunately was the correct size so it was just a matter of checking ‘set native size’. Next was the title, I found a free font called Multicolore that was similar to the design.
For the rest of the text, I just reproduced the title and placed them in their proper areas:
The logo and photo were just two UI/Images and the exit button is a UI/Button with the red x icon replaced for the source image.
Here’s the panel item list. I labeled items that would not be replaced as static, and the rest are labeled as descriptively as I could.
Creating the Card View
We’ll create a new script called CardView and attach it to the card panel. After that, some public Text and Image variable holders for each element will be created, and then we’ll drag those elements into the proper holder:
Scriptable Objects:
It’s now time to create the actual Scriptable Object. We’ll create a ScriptableObjects directory in our assets and create a new script called CardModel.
Normally, a script would inherit from Monobehaviour which would allow the script to be attached to an object, but since we’re going to be using this script in a data containing capacity, we’ll inherit from a ScriptableObject class instead.
Next, we’ll create a set of rules for our data container that defines what a card will need in order to function. In a way, it’s very reminiscent of an interface and its contract. Where it deviates from the interface, we’ll need to create a way for a user to create a new scriptable object from this template. We’ll do that through an attribute that allows us to create them from the editor. To create an attribute, use square brackets. This attribute will be called CreateAssetMenu
the intellisense hints tell us we’ll need a file name, a menu name, and the order or position of the menu item. We can ignore this last item.
This will make sense in a moment, but we’ll use “NewCard” for the file name and the menuName “Cards”.
Now, in order to create a new scriptable object, we can right click the scriptable objects folder and in the dropdown, we’ll see a new option “Cards”!
Next, I created all the info cards according to the artboard and filled each one out with the appropriate info.
Displaying the ScriptableObject
After all of the cards have been filled, it’s time to connect them to each button. In the CardView script attached to the Card Panel, I created an array called Cards and dragged all of the ScriptableObjects into it.
I also made a function called ShowCard that would take in a number which would be associated with each element, 0 being africa, 1 being bearden, etc.
Each button will invoke the showcard function, passing the id parameter to it, which then will display the appropriate data. For example, The Big Cat button will call ShowCard and pass 2 as the id number, which will call element 2 of said card array, which is, of course, the big cat scriptable object. The next OnClick event will activate the panel.
So let’s see it in action!
Everything works perfectly! Before I go, the exit button is just using the OnClick boolean SetActive but with the checkmark un-ticked so it closes the panel.