Often while making a game, you need a good way of storing data Say if you're making an RPG You need to make a whole bunch of items each with their own stats and properties Of course you could create an item prefab and then make copies of it with different values, but this is both prone to error and very inconvenient. So instead we use scriptable objects ♫ [Heavenly Choir] ♫ Scriptable objects are basically just data containers First, you create a template that defines what information each object should hold and then you create objects from that template. So in this video we'll learn how to use scriptable objects by looking at the example: creating cards for Hearthstone. Alright Let's go. So here's a simple scene with an empty card. If we have a look at it in the hierarchy, we can see that I have all of these different UI elements. I have a text object for the name, description, mana, attack and health As well as an image for an artwork And I've made sure to mask it out so it fits the card Let's now create a scriptable object that contains all of this information. To do that, we go to the project -> right click Create, C# script and let's call it "Card". Let's now click to open it Now we want to delete both our methods and this time we don't want to derive from MonoBehaviour Because this script is not gonna be sitting on another object It's more going to act as a template for all of the data that we want to store. To do that we want to derive from ScriptableObject. And now we're ready to define what values we want these objects to store And this is pretty simple: we want a string with the name of our cards, so we'll call this "name". We also want a string with the description of our card, we'll call that "description". Now we also wanna be able to define the artwork for our card So this is going to be some kind of image So we create a public sprite And we'll call it "artwork". And then finally we need the game-play stuff So we need a public int with the mana cost, a public int for the attack value and a public int for the health and here we have all information that each card will contain. Notice how we have a green line under the "name" That's because by default any object has a variable called "name". So we can either rename this to say "cardName" or we can just tell the object to use this definition of name from here on out To do that, we write "public new" string. And now every time we write "card.name", this is what it'll use So if we're now save this and go into unity Not much will happen here. You'll notice that I don't have any cards in the project. If I select this script it just shows the script here and for some reason we have a field for the artwork here, but none of the other stuff. Remember, this script is only the template for our cards. So how do we go ahead and create a card from this template? Well that's exactly what we need to define Unity makes this really easy with an attribute called "CreateAssetMenu". We need to always put this right above our class This will basically tell Unity to make it possible to create this object through the create asset menu Which means every time you right click in the project and go Create. So we're basically now adding a new object To this list. Now we need to define a few things here. Set default file name to something like 'New Card'. As well as the "menuName" to something like "Card" And if you have multiple cards you can create a submenu by going "Cards" and then "/" and then you can have all the specific cards in here But we only have one so we'll stick to Card. If we now save this and go to Unity (wait for the editor to compile here) and if we then right click go create, you can now see that there's indeed a card here If we press it, it's going to create an object. By default it says "New Card". Let's call this one "Edwin" Then at the top here we can set the name to "Edwin" We can create a description: "the baddest guy in town" Select some artwork I'm gonna open up here. I've already imported a sprite that we can use Set the Mana Cost, I'm gonna set that to 3, and attack value And the health value. So here we go. We've now created an object that is as simple as can be All it does: it stores information about a given card. And we can go ahead And create as many as these as we want. We can right click again. Go Create, "Card". This time we can create Tirion. His name is going to be "Tirion", his description is going to be: "His light shall burn you!" We can select some artwork. A Mana Cost, let's set that to 6, an attack value, and some health so now we've defined these two cards. But currently they're just sitting inside of the editor. We need some way of putting these cards Into the game. In other words we need to display them on the UI I've created here To do that we need another script. So let's select our card Add Component, and let's call this one "CardDisplay". Let's again select C# and hit create and add.
Let's open up Visual Studio. This time we want to delete our update method But let's leave our start method in here, because it's at the start of the game that we want to setup our card But in order to do this, we first need a reference to the scriptable object That we want to display. To do that, we'll simply create a "public" "Card". And we'll call it "card" with a non-capital "c". And it's actually that easy. Now inside of Unity we get this empty field where we can take any of our two scriptable objects. I'm gonna take Edwin here and drag him in. And now inside of our script we can access all of the data that we stored inside of this object So if we want it, we can just print out the name of the card By going "card.name". If we now save this and play the game, it's going to show "Edwin" in the console. So that's really cool. In fact we can also add symbol methods to our scriptable objects. We can go in here and create a public void called "Print" And this method will simply show some of the card information in the console. So we'll throw a Debug.Log And here we'll print the name of the card, followed by a description. So, a description on the card And then we can print, say, the mana cost, so we'll go The card costs and then the "manaCost". So if we save that and go into CardDisplay, we can simply call "call.Print();" And if we save this and hit play It's going to print: "Edwin, the baddest guy in town. The card costs 3." Awesome! But we can do better Instead of just showing this stuff in the console Let's show it on the UI To do that, instead of printing the card to the console, let's go and reference all of our UI elements To do that, we need to be using "UnityEngine.UI;" and now we can create a public Text This is going to be our "nameText" We'll also create a public Text "descriptionText" then we need a public Image this is going to be our artwork image And then a public Text manaText public Text attackText And you guessed it, a healthText. Then in Unity we'll setup these references So we'll put name into the nameText slot Then description, then the artwork image is under here, so there's an artwork image the manaText, the attackText and the healthText. And now in the start method, we can simply set nameText.text equals to "card.name;" and descriptionText.text = card.description; we can really just continue this way for the artwork image We need to make sure to access the sprite And set it equal to card.artwork. And for the manaText we'll go manaText.text equals card.manaCost. But we remember that manaCost is a number, it's an integer, so we need to convert this to a string. To do that, we simply call .toString(); And we do the same thing for the attack and health. ♫ [Music Break] ♫ And there we go! That should be all of the code that we need. If we now save this and try and play the game. We can see all of our UI elements get updated to show Edwin's information. And we can input any scriptable object here If you want to show Tirion instead, we simply drag in Tirion and hit play, and there we go! Our card is now Tirion. In fact, we can easily copy this card and place them side by side, let's make one of them Tirion and the other one Edwin. When we now play the game We can see our two cards. And right now we're just doing This in the start method. You can easily update this while the game is running. Because we're just swapping out simple information. And each of these scriptable objects are extremely small. You can see both Edwin and Tirion is only 1 Kb. So yea, scriptable objects are super cool. That's pretty much it for this video. If you enjoyed it, make sure to subscribe, so you don't miss the next one. I hope you guys had a Happy New Years, and I'm looking forward to an awesome 2018 With plenty of game dev goodness! On that, thanks for watching! And I will see you in the next video. Thanks to all of the awesome Patreon supporters who donated in December and a special thanks to: @Youdaman, Armin Noroozi, Yorai Omer, beffio, UnnecessaryRoughness, InfinityPBR, Cyborgmummy Cole Cabral, Dan Evans, John Beauregard, SupermanTheG8, James P, Jason Lotito, Derric Heemskerk, Fasal Marafie, Erasmus, Rob Fearn James Rodgers Alex Rakitsky, Manolis and Robert Bund
Scriptable objects are actually so good. If you are wanting to learn more you HAVE HAVE HAVE to watch these Unite talks on them
https://youtu.be/6vmRwLYWNRo https://youtu.be/raQ3iHhE_Kk?list=WL
Really great video. Scriptable objects had always confused me.