Unity How to use ScriptableObjects for handling Game State – Tutorial

Unity How to use ScriptableObjects for handling Game State – Tutorial


What’s up game developers? CouchFerret
here! Welcome back to yet another video of making games in Unity. If this is your
first time here and you wanna learn how to design draw and develop games in
Unity start now by subscribing and hit the bell so you won’t miss anything.
Today we’re gonna talk about ScriptableObjects and how to use them to handle
game state. But because this use case is a bit unconventional, first we’ll talk
about the common use case of ScriptableObjects. What’s up guys it’s me, FutureFerret! I just like to mention that Code Monkey, Roman Papush, and I created awesome
mods for the FPS Microgame. If you haven’t heard about
Unity’s Microgames then definitely check it out they are like example
projects but on steroids and you can learn a lot from them. The link is in the
description, back to the present! Okay, what’s a ScriptableObject? A ScriptableObject is a data container but unlike MonoBehaviors you cannot directly
attach ScriptableObjects to GameObjects. Instead, ScriptableObjects are
stored as assets in your project just like images textures or meshes. One of
the main use cases of ScriptableObjects is to store data like item stats or
properties that won’t change while playing the game. There’s a pretty good video on
this use case by Brackeys where he’s using ScriptableObjects to store
Hearthstone card stats. Check it out the link is in the description! But today,
we’ll use ScriptableObjects a bit differently. We’ll use them for decoupling
our code even further by separating the game’s state data from the MonoBehaviors.
State data is the data that changes while we play the game for example current
health, current score, or positions of the players. However, we won’t be saving this
data to load it back later, we’ll just use it during runtime. Anyway, if we
separate the game state from the MonoBehaviours we’ll be able to access things
like current score without accessing another GameObject. This is great
because we won’t be relying on certain GameObjects in the scene. Instead
the game state will live in the project as an asset and we’ll be able to access
it just like we would access an image asset. And because the Inspector window
understands ScriptableObjects we’ll see the ScriptableObjects’ variables in the
Inspector window just like we see the MonoBehaviors’ variables. Today I’ll be
demonstrating this whole concept with a simple example.
Okay, let’s finally jump into Unity! First, I’m gonna create the game state
ScriptableObject. In the Scripts folder I’m gonna create a new folder called
States, in it let’s create a new script called GameState and let’s open it up
in the script editor. First thing first, let’s remove these functions. ScriptableObjects don’t have Start() or Update() functions anyway. Let me zoom in a little.
That’s much better. Okay, now we need to change the superclass from MonoBehavior
to ScriptableObject. This is how we say it in code that we want to create a
custom ScriptableObject now, instead of a MonoBehavior. Okay, to make this
ScriptableObject contain any data we have to declare variables in it. So let’s
declare a public float gameTime variable. Okay, what we have created so
far here is a template for GameStates and not an actual instance. Of course in
our game we’ll have only one GameState instance because more than one doesn’t
make any sense. But we still need to create an instance
out of this because this script just defines how a GameState instance should look. There’s a handy attribute that creates a new menu item in the create
menu. And with it we could easily create our GameState instance that we
desperately need. To define the new menu item we have to use the [CreateAssetMenu] attribute above our GameState class’s definition. fileName defines the
new instance’s name, and the menuName defines the new item’s
name. Let’s save the script and see if I our new
menu item is in the create menu. Cool, it’s here so let’s click it and create
the instance itself. If we select the GameState ScriptableObject we can see
its gameTime variable. Let’s create a separate folder for ScriptableObjects just to be a bit more organized. And let’s drag and drop it into this new
folder. Okay, now we’ll change the gameTime’s value from the GameLogic script so
let’s open it up. To be able to reference the GameState ScriptableObject we need
to create a variable for its reference. And also we have to drag and drop the
GameState itself into this new variable’s field. And that’s it. No GameObject.Find() or GetComponent() function calls. Now, let’s go back to the
script editor and assign a starting value for the gameTime variable. I’m
gonna do this in the Start() function gameState.gameTime and I’m gonna set it to 90 seconds. Now, let’s define the Update() function so we can decrease the
gameTime’s value in every frame. gameState.gameTime -=time.deltaTime this will decrease the gameTime’s value with the elapsed time since the
last frame. If we run the game now we should see in the Inspector how the gameTime’s value changes over time. So let’s hit play and select the GameState
ScriptableObject. It works. Now it’s time to display it on the screen. For that
let’s hit right click on the Hierarchy window and go to UI/Canvas. And let’s
name it UI. On it, we have to create a new
MonoBehaviour by hitting the Add Component button and
let’s name it UIBehavior. Let’s move this new script into the Scripts folder
and let’s open it up. I’m gonna remove the Start() function but let’s keep the
Update(). In the Update() function we’ll update text GameObject to display the
current game time. So let’s go back to Unity and create the text GameObject
first. Right clicking on the UI GameObject, let’s go to UI/Text – TextMeshPro
to create a new text game object we haven’t used TextMeshPro in this
project yet, so Unity brings up an importer window.
So let’s hit import TextMeshPro essentials and Unity will import
everything we’ll need. And now, we can close this window. I’m gonna name this text
object as GameTimeText and to find it in the Scene view we need to select the
object and hit F while the cursor is in the Scene window. This will zoom in a bit and
we’ll position the Scene view on the GameTimeText object. So let’s zoom out a
bit so we can see the whole UI and let’s anchor this text to the top center and
move it up a bit. Also I’m gonna center the text in it as well. Now, we need a
reference to this Text GameObject in the UIBehavior script, so let’s jump
back into the script editor. First, we need to use the TextMeshPro namespace,
then we have to declare a new variable for the GameTimeText. I’m gonna declare
it as public TextMeshProUGUI and name it gameTimeText. And also let’s
create a new variable for the GameState as well. Let’s save the script and let’s go
back to Unity. Let’s select the UI GameObject and let’s fill the gameTimeText
variable with the GameTimeText GameObject and also fill the GameState
variable as well. Cool, now we have everything we need to change the
GameTimeText from script. So in the code editor and in the Update() function
let’s assign a new value to the gameTimeText text parameter and for the right
side let’s type gameState.gameTime and ToString(). The ToString() function gives
back the float’s string representation. Let’s try it out!
Well, it works but it’s kinda ugly. I’m gonna prettify it to make it look like a
digital clock. And I’m gonna use TimeSpan for this. TimeSpans come from C#
and they represent time intervals. But to be able to use them first we need to use
the System namespace. I can convert the gameTime float into a TimeSpan with the
TimeSpan.FromSeconds() function and then let’s save this into a timeSpan
variable. The good thing about Time Spans is that you can format them in any way
you want. I’m gonna change the gameTimeText’s text value to timeSpan.ToString() and in the parenthesis I can define the
formatting itself. So I’m gonna put “m’:’ss” and that’s it. Let’s save and it try it out. Co-Coo-Cool!
So today we used a ScriptableObject to store data about our game’s
state and then we displayed it in a decoupled way. That’s it for today folks.
Don’t forget that you can get the project files and sprites on patreon.
Link is in the description. And huge thanks to all the awesome patreon
supporters! Thank you guys! You guys are amazing!
Next time we’ll create our own pixel art font so we don’t have to use this
default ugly one. Sounds fun, right? So stay tuned, be sure to subscribe, and say hello to us on Discord! See you next time!

19 thoughts on “Unity How to use ScriptableObjects for handling Game State – Tutorial

  1. Lol I was today on your channel and wondered β€œwhy do I get not notifications from him, did I close them?” And saw that you had no new videos. And now you uploaded a new one πŸ˜‚

  2. I learned about scriptable objects a while ago but did not know that you could use them like this. I love it.
    Thank you. πŸ™‚

  3. Cute tiny example, but not really scalable. I’ve inherited a medium size project that’s using this architecture to store literally all state. It’s horrible. Better to just use static variables if you need them to be global.

  4. You are an absolute legend. Thank you so much for everything that you do, the effort you put into these videos, the quality is amazing, the kind and extremely helpful way you immerse yourself in the community as well and offer so much help to so many people. Thank you!

  5. Thanks CouchFerret super helpful stuff. I learned so much from the video, I'm very new to Unity so this tutorial series is great!

Leave a Reply

Your email address will not be published. Required fields are marked *