The Power of Scriptable Objects as Middle-Men

samyam
10 Feb 202217:40

Summary

TLDRThis video explores the use of Scriptable Objects in Unity for event-based messaging, a technique that decouples code and reduces dependencies between components. The speaker illustrates how traditional health management in games can be improved by using Scriptable Objects, which act as middlemen for communication between scripts. They demonstrate how this approach simplifies game architecture, enhances flexibility, and facilitates easier testing and debugging. The video references Ryan Hipple's talk on game architecture with Scriptable Objects and highlights the benefits of using Unity Events for managing game data across scenes, ultimately leading to a more scalable and maintainable project.

Takeaways

  • ๐Ÿ“ฆ Scriptable Objects are data containers that persist outside the scene and maintain their values across scene reloads unless programmed otherwise, making them ideal for storing game data like health and enemy attack stats.
  • ๐Ÿ”— Scriptable Objects can be used for event-based messaging, acting as intermediaries between different scripts or components to decouple code and reduce dependencies, leading to easier testing, debugging, and flexibility in game design.
  • ๐Ÿ‘จโ€๐Ÿซ The video recommends watching a previous video for an introduction to Scriptable Objects and their benefits, and also suggests a Unity Austin 2017 talk by Ryan Hipple for in-depth insights on using Scriptable Objects for game architecture.
  • ๐ŸŽฎ The video discusses the use of Scriptable Objects in managing player health, demonstrating how they can be used to avoid direct dependencies between the player and UI elements like health sliders.
  • ๐Ÿ’ก The concept of the 'single responsibility principle' is highlighted, emphasizing that each module, class, or function should handle only one part of the program's functionality to minimize dependencies.
  • ๐Ÿ”„ The issues with using Singletons for managing health are discussed, including the potential for creating global dependencies and difficulties in testing due to static instances.
  • ๐Ÿ”— The video introduces the idea of using Scriptable Objects to maintain health data across different scenes without relying on Singletons or PlayerPrefs, promoting a more scalable and manageable approach.
  • ๐Ÿ› ๏ธ The implementation of a Scriptable Object for health management is outlined, detailing how it can be used to send events and communicate changes to subscribed scripts, such as a UI manager.
  • ๐ŸŽฏ The benefits of using Scriptable Objects over MonoBehaviour for event communication are pointed out, noting that Scriptable Objects do not require instantiation in the scene and thus are more memory efficient.
  • ๐Ÿงฉ The video touches on the concept of dependency injection, drawing parallels with Scriptable Objects in terms of decoupling code, but notes that Scriptable Objects are more designer-friendly due to their visual nature in the Unity Inspector.
  • ๐ŸŽ The video concludes with a call to action for viewers to support the content creator and the sponsor, Mental Checkpoint, and thanks the patrons for their support, highlighting the importance of community engagement.

Q & A

  • What are scriptable objects in Unity and why are they useful for storing data?

    -Scriptable objects in Unity are data containers that exist outside the scene and maintain their state even when the scene reloads. They are useful for storing data such as health, enemy attack values, etc., because they provide a persistent way to manage game data without being tied to specific scene instances.

  • Can you explain the concept of event-based messaging with scriptable objects?

    -Event-based messaging with scriptable objects involves using these objects as intermediaries or middlemen between different scripts or components. This approach helps decouple the code, reducing dependencies and making the game architecture more flexible, easier to test, and simpler to debug.

  • What is the single responsibility principle in programming and how does it relate to game architecture?

    -The single responsibility principle states that every module, class, or function in a program should have responsibility over a single part of the program's functionality and should encapsulate that part. This principle helps prevent unnecessary dependencies between different parts of a program, making it easier to manage, test, and maintain, which is particularly important in game architecture.

  • Why is using a slider directly in the player's script an issue in terms of game design?

    -Using a slider directly in the player's script creates a dependency between the player and the UI component, which goes against the single responsibility principle. This makes the code less flexible and harder to test, as changes in one part of the game might require changes in seemingly unrelated scripts.

  • What are some common alternatives to scriptable objects for managing health or similar data across scenes?

    -Some alternatives include using PlayerPrefs to save and load values, using a singleton pattern with a 'Do Not Destroy On Load' component to persist data across scenes, or using additive scenes to maintain a separate scene that holds the data manager.

  • Why are singletons generally frowned upon in the game development community?

    -Singletons are often discouraged because they create global instances that can be accessed by any part of the program, leading to increased dependencies. This makes testing difficult, as it's hard to track what's referencing what, and can lead to issues like null references if the singleton is not available for some reason.

  • How can scriptable objects help in maintaining health data across different scenes without resetting?

    -Scriptable objects can store health data independently of the scene, allowing the data to persist even when scenes are reloaded. By using a scriptable object, the health value is not tied to a specific scene or game object, ensuring that the player's health remains consistent across different levels.

  • What is the difference between using a scriptable object and a MonoBehaviour for event-based communication?

    -A MonoBehaviour would require instantiation of a GameObject with a Transform component to act as a middleman, whereas a scriptable object does not need the extra memory of the Transform component and does not exist in the scene. Scriptable objects are also more designer-friendly, as they can be easily managed and adjusted in the Unity Inspector without writing additional code.

  • How does the Unity Event system relate to scriptable objects for event-based programming?

    -The Unity Event system can be used in conjunction with scriptable objects to create a powerful event-based programming model. Scriptable objects can hold events that other scripts can subscribe to, allowing for a decoupled and flexible way to handle game events and changes in data.

  • What is the benefit of using scriptable objects over dependency injection for game design?

    -While dependency injection also helps in decoupling code, it typically requires a framework and can be less intuitive for designers who may need to look into the code to understand or modify behavior. Scriptable objects offer a more visual approach, allowing designers to easily add and adjust attributes directly in the Unity Inspector.

Outlines

00:00

๐Ÿ“š Introduction to Scriptable Objects and Event-Based Messaging

This paragraph introduces the concept of scriptable objects as data containers that persist outside the scene and maintain their values across scene reloads unless programmed otherwise. It highlights their utility for storing game data like health and enemy attack stats. The speaker recommends a previous video for a deeper understanding of scriptable objects and discusses their use in event-based messaging, where they act as intermediaries between scripts to decouple code and enhance flexibility, ease of testing, and debugging. The talk from Unite Austin 2017 by Ryan Hipple on game architecture with scriptable objects is also recommended. The paragraph concludes with a mention of the sponsor, Mental Checkpoint, a YouTuber known for game design tips and the game 'Move or Die'.

05:01

๐ŸŽฎ Managing Player Health with Scriptable Objects

The second paragraph delves into the typical management of player health in games, using a player controller and a UI slider as examples. It outlines the process of setting health to maximum on awake, decreasing health with a trigger, and updating the UI slider accordingly. The paragraph then critiques this approach for creating dependencies between the player and the UI slider, which can complicate testing and scalability. It introduces the single responsibility principle, advocating for reducing dependencies to simplify testing and maintenance. The discussion leads into how scriptable objects can be used to manage health across different scenes without resetting, contrasting with the limitations of singletons and the complexities they introduce.

10:02

๐Ÿ”„ Persistence of Health Data Across Scenes

This paragraph explores solutions for maintaining health data across different game scenes. It mentions the use of player preferences and the 'Don't Destroy On Load' method to persist values, but also points out their limitations, such as the messiness of player prefs and the complications of singletons. The paragraph then introduces the concept of additive scenes, where multiple scenes can run simultaneously, as a potential solution for persisting data like health. However, it acknowledges that the issue of interdependencies between managers, like health and UI managers, still needs to be resolved.

15:04

๐Ÿ“ก Using Scriptable Objects for Event-Based Communication

The fourth paragraph presents scriptable objects as a solution for the issues discussed earlier. It describes how a scriptable object can hold player health data and be used to communicate health changes between scripts, such as triggering health decrease and updating the UI. The speaker explains the implementation of a 'Health Manager Scriptable Object' that maintains health data, triggers events when health changes, and allows other scripts to subscribe to these events. This approach eliminates the need for singletons, reduces dependencies, and simplifies the game architecture. The benefits of using scriptable objects over MonoBehaviours and the concept of dependency injection are also briefly discussed, highlighting the ease of use for designers and the visual friendliness of scriptable objects.

Mindmap

Keywords

๐Ÿ’กScriptable Objects

Scriptable Objects in Unity are data containers that exist outside the scene and maintain their state even when the scene reloads. They are pivotal for storing game-related data such as health or enemy attack values. In the video, Scriptable Objects are highlighted for their ability to facilitate event-based messaging, acting as intermediaries between different scripts to decouple code and reduce dependencies, which simplifies testing, debugging, and makes the game architecture more flexible.

๐Ÿ’กEvent-based Messaging

Event-based Messaging is a programming paradigm where a 'middleman' or a messenger facilitates communication between different parts of a program without them being directly dependent on each other. In the context of the video, Scriptable Objects serve as this 'middleman', allowing different scripts or components to communicate changes, such as health updates, without needing direct references to each other, which enhances modularity and maintainability.

๐Ÿ’กDecoupling

Decoupling in software design refers to creating a system where components have minimal or no dependencies on each other. This concept is crucial in the video as it discusses how using Scriptable Objects can help decouple game scripts, making the game easier to manage, test, and modify. Decoupling is exemplified through the transition from a direct slider reference in a player's health script to an event-based approach using Scriptable Objects.

๐Ÿ’กSingle Responsibility Principle

The Single Responsibility Principle is a software design principle that states that a class or module should have only one reason to change, meaning it should only have responsibility over a single part of the functionality. In the video, this principle is mentioned to argue against the player script having multiple responsibilities, such as managing health and UI elements, and instead suggests using managers or Scriptable Objects to adhere to this principle.

๐Ÿ’กSingleton

A Singleton is a design pattern that restricts the instantiation of a class to one single object, providing a global point of access to it. The video discusses the use of Singletons in game development, particularly for manager classes like a health manager, but also points out the downsides, such as creating hidden dependencies and making testing difficult.

๐Ÿ’กDon't Destroy On Load

In Unity, 'Don't Destroy On Load' is a method that can be used to keep a GameObject active across different scenes. The video mentions this as a technique to maintain the state of a Singleton health manager when scenes are reloaded, thus preserving the player's health across levels.

๐Ÿ’กAdditive Scenes

Additive Scenes in Unity are scenes that are loaded on top of the current scene without replacing it, allowing for multiple scenes to run simultaneously. The script discusses using additive scenes as a method to maintain game state, such as health, by keeping a persistent scene with a health manager while other game scenes are loaded and unloaded.

๐Ÿ’กUI Manager

A UI Manager in the context of the video is a Singleton class responsible for managing the user interface elements, such as a health slider. It is used to illustrate how a decoupled system can communicate state changes, like updating the slider when the player's health changes, without direct references to the UI elements themselves.

๐Ÿ’กDependency Injection

Dependency Injection is a technique where an object's dependencies are provided to it, rather than the object constructing or requesting its own dependencies. The video touches on this concept in the context of Scriptable Objects, where the objects (like a health manager) receive the data they need (like health value) from the Scriptable Objects, promoting a more modular and testable code structure.

๐Ÿ’กUnity Events

Unity Events are a part of Unity's event system that allows for the creation of events that can be listened to and triggered by various components in a Unity project. In the video, Unity Events are used in conjunction with Scriptable Objects to create a flexible event-driven architecture, where changes like health updates can be communicated to any subscribed listener, such as a UI Manager.

Highlights

Scriptable objects are data containers that persist outside the scene and maintain their values across scene reloads unless programmed otherwise.

Scriptable objects are beneficial for storing data like health, enemy attack, etc., and can also be used for event-based messaging.

Event-based messaging with scriptable objects acts as a middleman between scripts or components, helping to decouple code and reduce dependencies.

Decoupling code makes it easier to test, debug, and architect a game to be flexible and easy to change for both coders and designers.

The video references a Unity Austin 2017 talk by Ryan Hipple on game architecture with scriptable objects for in-depth insights.

Mental Checkpoint, a game design YouTuber, is highlighted for their experience and valuable game design tips.

The single responsibility principle is discussed, emphasizing that each module, class, or function should handle only one part of the program's functionality.

Using a health manager as a singleton can help manage dependencies but is generally discouraged due to potential issues with testing and global access.

Singletons can create dependencies and make it difficult to track references, leading to potential null reference errors.

Player prefs and DontDestroyOnLoad are alternative methods to persist data across scenes but have limitations and can be messy.

Additive scenes can be used to keep certain objects persistent while reloading others, but still involve dependencies.

Scriptable objects can be used to communicate between scripts, avoiding singletons and reducing complexity.

Unity events are a powerful tool for event-based programming, as demonstrated with the health manager scriptable object.

Decoupling code with scriptable objects makes it easier for both developers and designers to work with and modify game elements.

Scriptable objects are more designer-friendly compared to dependency injection, allowing for easy adjustments in the inspector.

The video concludes with a demonstration of how scriptable objects maintain health values across scene reloads and play sessions.

Transcripts

play00:00

scriptable objects are data containers

play00:02

which live outside the scene and are

play00:04

also persistent meaning that their

play00:06

values do not change when the scene

play00:08

reloads unless you programmed that

play00:10

functionality so they're a great way of

play00:11

storing data you may need such as the

play00:13

health enemy attack etc however there is

play00:16

another use for them and if you're

play00:17

interested in learning more about

play00:19

scriptable objects i'd recommend my

play00:20

previous video before watching this one

play00:23

which explains scriptable objects what

play00:25

they are and how to use them and their

play00:26

benefits but there's also another use

play00:28

case for scriptable objects and that's

play00:31

called event-based messaging and it's

play00:33

where the scriptable object kind of acts

play00:34

as a middleman between two different

play00:36

scripts or components so we can decouple

play00:39

the code which basically means to

play00:41

separate or to remove dependency onto

play00:43

components and when you remove

play00:45

dependency it makes your life easier

play00:46

makes it easier to test more flexible

play00:48

and easier to debug but it is a great

play00:50

way to architect your game to be

play00:52

flexible and easy to change for both the

play00:54

coders and designers and what i'm going

play00:56

to show you is based on a unite austin

play00:59

2017 talk which is actually pretty well

play01:01

known it's called game architecture with

play01:03

scriptable objects and it's given by

play01:05

ryan hipple a principal engineer at

play01:07

shell games so i definitely recommend

play01:09

checking out this video because they go

play01:11

more in depth into scriptable objects

play01:13

and how to architect your entire project

play01:15

to use scriptable objects and on the

play01:17

topic of game design this video is

play01:20

sponsored by mental checkpoint if you

play01:22

haven't heard of mental checkpoint

play01:23

they're an amazing youtuber who actually

play01:25

made the game move or die which is an

play01:27

awesome game on steam if you haven't

play01:29

played it already and their channel is

play01:30

full of super useful and secret tips on

play01:33

game designs that i have not heard in

play01:35

many of the other videos that i watch

play01:36

and this is largely due to their

play01:38

experience in the field the editing and

play01:40

pacing of the videos are also amazing so

play01:42

if you're interested in learning about

play01:43

game design i definitely recommend you

play01:45

check out mental checkpoint

play01:47

alright so i'm going to show you how to

play01:49

use scriptable objects for event based

play01:52

messaging now what does that entail so

play01:55

first let's see how we would usually

play01:57

manage our player health so let's say we

play01:59

have a player controller which you can

play02:00

ignore all of this but the important

play02:02

thing is let's say we have a health here

play02:05

of a hundred and then on awake we set

play02:07

the health to the max health and then we

play02:09

have a function here called decrease

play02:12

health which decreases the health and

play02:14

you'll see that we have a reference to

play02:16

the slider here which the slider is just

play02:18

a ui slider on the scene and we set the

play02:21

value of the slider whenever we decrease

play02:23

the health so you'll see that right here

play02:25

we need a reference to the slider and of

play02:27

course we need to import the unity

play02:28

engine ui namespace to use this slider

play02:32

so what happens here is that when the

play02:34

player enters this red box it loses

play02:36

health and when the player enters this

play02:38

green box the level reloads so if we

play02:40

enter this red box you'll see that the

play02:42

help decreases by 10 which is just a

play02:44

simple script here health decrease

play02:46

trigger that we attach to this box and

play02:48

we have this on trigger enter function

play02:50

if the other tag is called player then

play02:53

we get a reference to the player

play02:54

controller and we decrease the health

play02:56

seems simple enough right and make sure

play02:59

to add a rigid body disable using

play03:01

gravity and also marking the object as

play03:04

static if it's not moving as well as

play03:05

enabling its trigger on the box collider

play03:08

so this is simple enough we walk into

play03:09

the green box and the level reloads and

play03:12

we have our health back however there

play03:14

are multiple issues with this first of

play03:16

all now the player has to have a

play03:19

reference to the slider so now the

play03:21

player is dependent on the slider so

play03:23

what happens if we have a level where we

play03:25

don't want the slider but we still want

play03:27

to decrease the health well in that case

play03:29

you'd have to change the script around

play03:31

so that you don't accidentally have any

play03:32

null reference values or you might be

play03:34

accessing this slider when you don't

play03:36

actually have one in the scene with game

play03:38

architecture you want to try to reduce

play03:40

dependencies between things that don't

play03:42

need them does the player really need to

play03:44

depend on a slider no the player should

play03:48

only be in charge of what it needs to do

play03:50

and in the coding world this is called

play03:52

the single responsibility principle it

play03:55

states that every module class or

play03:56

function in a program should have

play03:58

responsibility over a single part of

play04:01

that program's functionality and it

play04:03

should encapsulate that part this is to

play04:04

prevent dependencies between different

play04:06

things that might not need them because

play04:08

if you have dependencies it makes it

play04:10

harder to test because now if i wanted

play04:12

to put my player in a different scene to

play04:15

test just the movement

play04:17

now i'd need to import the slider over

play04:20

or else i wouldn't be able to test this

play04:22

accurately and this is just a simple

play04:23

example what happens if the player

play04:25

starts depending on a bunch of other

play04:26

stuff on the audio what if the player

play04:29

depends on the enemies themselves then

play04:31

to test this we need to import all of

play04:33

those variables into a new scene just to

play04:35

test if the player mechanics are working

play04:38

and that is not scalable so this

play04:41

bad another issue is that what if we

play04:43

want to keep the health over different

play04:45

scenes what if we don't want it to reset

play04:47

well since we're reloading the scene

play04:49

somehow you'd need to pass the value

play04:51

over to the new scene and i'm actually

play04:52

going to explain this in the following

play04:54

examples all right so let's see the

play04:56

example number two so what a lot of

play04:58

people do is that they have a health

play05:00

manager now instead of the player having

play05:03

a direct reference to the ui you have a

play05:05

manager as the middleman speaking

play05:08

between the two parties which helps with

play05:10

the single responsibility principle

play05:12

since this health manager is only

play05:14

managing health and now the player

play05:15

doesn't need to worry about the slider

play05:18

so what's common practice is to make a

play05:20

singleton of managers and a single 10

play05:23

just means a single instance of this on

play05:25

a scene similar to a static class so you

play05:28

can only have one health manager in the

play05:30

scene but that means that it's just

play05:32

really easy to access for example if we

play05:34

go to this singleton class you'll see

play05:36

that we can access the singleton just by

play05:38

typing in the class name and dot

play05:41

instance and it'll return an instance of

play05:43

health manager all we're doing is

play05:45

putting the decrease health function

play05:46

here and in the awake function we're

play05:48

just setting the health back to the

play05:50

maximum health so this is refreshed when

play05:53

the new scene loads and now for the

play05:55

health trigger instead of accessing the

play05:56

player directly you can do health

play06:00

manager.instance.decreasehealth so now

play06:01

the trigger does not depend on the

play06:03

player it just depends on a manager that

play06:05

we can assume that will be in our scene

play06:07

at all times alright so if we click play

play06:09

here you'll see that

play06:11

the health decreases we reload the level

play06:13

and it refreshes the slider and the

play06:16

health so there's some issues with this

play06:19

the main one being the singleton class

play06:21

is generally frowned upon in the gamedev

play06:24

community and in general because of

play06:26

multiple reasons with singletons you

play06:28

have a global instance meaning that

play06:30

anyone can access it it also means that

play06:33

when someone accesses the singleton you

play06:35

create a dependency to this singleton

play06:38

and we're back at the issue with

play06:39

dependencies where now if something

play06:41

depends on the singleton and the

play06:43

singleton is not available for some

play06:46

reason many reasons can happen then you

play06:48

have a null reference and tracking that

play06:50

down and fixing it is just quite a

play06:52

hassle with singletons since this is a

play06:55

static instance it makes it hard to test

play06:57

because it's hard to track exactly

play06:59

what's referencing what so in general

play07:01

singletons have the issue where if

play07:03

you're not careful you can end up having

play07:05

a bunch of dependencies so you're

play07:06

singletons with your scripts and it can

play07:08

make it harder to test now if you're

play07:09

making a small project this isn't much

play07:12

of a problem however as you scale your

play07:14

project upwards and create a bigger

play07:15

project with different teams that's

play07:17

where the issue begins and another issue

play07:20

is that the health resets when we reload

play07:22

the scene and we don't want it to reset

play07:24

we want to keep the health the same

play07:26

throughout the different scenes like

play07:27

most games do now first let's tackle the

play07:30

issue of having the data persist along

play07:32

different scenes so usually if you

play07:34

follow this line of thinking and not use

play07:36

scriptable objects there's some ways to

play07:38

do that first you can use player prefs

play07:40

to save your values and then load it

play07:43

again when the scene reloads however i

play07:45

tried doing this and it was just kind of

play07:46

a mess especially when you start the

play07:48

game over again because the previous

play07:50

player prefs value is saved and you have

play07:53

to reset it and using player prefs isn't

play07:55

totally scalable if you have a ton of

play07:58

values another method is for your

play08:00

singleton your health manager is to use

play08:02

don't destroy on load so in this case

play08:05

i've changed the singleton to be

play08:07

singleton persistent which if you go to

play08:10

the main difference is that in the awake

play08:11

function we have the stone destroy

play08:13

unload which when loading a new scene

play08:15

does not destroy the game object it

play08:17

keeps it and with the singleton

play08:19

persistent value this makes sure that

play08:20

there's only one instance of the health

play08:22

manager on the scene even when the scene

play08:25

is reloaded so this is one way to make

play08:27

your values persist over multiple scenes

play08:29

by using a singleton and do not destroy

play08:32

unload and then the main difference here

play08:34

is that instead of accessing the slider

play08:36

directly we create a ui manager instance

play08:38

which is another singleton and we call

play08:41

that to change the slider value with the

play08:43

ui manager all it does is has this

play08:45

function called change slider value and

play08:47

that's what we call here from the health

play08:49

manager prefs so for example we press

play08:52

play and we reset the level you'll see

play08:54

that now we have the scene here which is

play08:56

the previous game objects and the don't

play08:58

destroy unload which is the health

play08:59

manager so since this was not destroyed

play09:02

the reason why we made a ui manager is

play09:04

so that the ui manager would have a

play09:06

reference to the slider and so that the

play09:08

health manager can access the slider

play09:10

since the ui manager is a singleton if

play09:13

you put the slider directly on the

play09:14

health manager once the levels were

play09:16

loaded it would lose access to the

play09:18

slider since the slider would be

play09:20

destroyed and a new slider is created

play09:23

when the level is reloaded so now you

play09:24

see this is getting a little bit

play09:26

complicated we're making managers we're

play09:28

making singletons you see how this can

play09:30

get messy really quickly additionally

play09:32

the health manager is assuming that the

play09:33

ui manager exists and that the ui

play09:36

manager has a reference to the slider so

play09:38

if the ui manager does not exist there's

play09:40

a null reference or if the ui manager

play09:42

doesn't have a reference to the slider

play09:44

that's another null reference and so

play09:46

following this line of thinking there's

play09:47

actually another way to have the value

play09:50

persist over multiple scenes apart from

play09:52

player preps and it's using additive

play09:55

scenes usually in unity you have one

play09:57

scene active the main scene and what you

play09:59

can do is you can actually have multiple

play10:01

scenes running at the same time and

play10:03

those are called additive scenes because

play10:05

they're added to the main scene and

play10:07

similar to the do not destroy that lives

play10:09

in its own bubble you can actually click

play10:12

in the hierarchy here to add a new scene

play10:15

you can delete the lights that the scene

play10:17

has and you can actually add a game

play10:20

object in that new scene and you can add

play10:22

your health manager in that scene what

play10:24

you can do is you can load in a new

play10:27

active scene this is the active scene

play10:29

where all your game objects are and

play10:31

where your light

play10:32

settings are which is important the

play10:34

directional lights and so you can keep

play10:36

this health manager scene running and

play10:38

instead just reload this main active

play10:40

scene now i'm not going to go over the

play10:42

implementation for that but just know

play10:44

that that's a possibility but the issue

play10:46

still remains where we're using

play10:47

singletons and the health manager

play10:49

depends on the ui manager and vice versa

play10:51

so what is the solution we can fix all

play10:53

of our problems really easily using

play10:55

scriptable objects as a way to

play10:57

communicate between scripts similar to

play11:00

sending events so what we can do is have

play11:03

a scriptable object with the health of

play11:05

the player and then whenever our player

play11:07

enters the red box which decreases our

play11:10

health that trigger will talk to the

play11:12

scriptable object which will then tell

play11:14

the scriptable object to decrease the

play11:16

health and the scriptable object will

play11:17

then send out an event which the ui

play11:20

manager will subscribe to and the ui

play11:22

manager will listen to that event when

play11:24

the health has decreased and when it has

play11:26

it will change the value of the slider

play11:29

so let's go over the implementations

play11:31

pretty simple we have this health

play11:32

manager scriptable object here it

play11:34

extends scriptable object so all we have

play11:37

here is an integer for our health which

play11:40

is our data and then we have max health

play11:42

which is the maximum amount of health

play11:43

our player can have so in the on enable

play11:46

of this script which is called also when

play11:48

this scriptable object is loaded in this

play11:51

case when we press play and the level is

play11:53

loaded this is called we set the health

play11:55

equal to max health so kind of like when

play11:57

the game starts we just set it to the

play11:59

max health and then what we're doing

play12:01

here is that we have an event a unity

play12:03

event called health change event and

play12:05

here we're just instantiating that event

play12:08

if it equals no and so what we're going

play12:10

to do here is when we decrease the

play12:11

health of our player we decrease the

play12:14

health as usual but now we invoke or we

play12:17

just call this event and we pass in the

play12:20

health so to make that easier to

play12:22

understand we have our trigger here so

play12:23

when the player enters our on trigger

play12:25

enter we call the health manager which

play12:28

in this case is just our scriptable

play12:31

object so we just have a reference to

play12:33

our scriptable object here and we call

play12:35

decrease health and so this will call

play12:37

this function and then any script that

play12:38

has subscribed to this event

play12:41

will get notified of this new health

play12:44

value and unity events are super

play12:46

powerful i definitely recommend using

play12:48

event based programming that's what the

play12:50

input system uses actually and side note

play12:52

the input system actually uses

play12:54

scriptable objects for most of its stuff

play12:56

such as the assets the input actions

play12:59

which i thought was pretty interesting

play13:00

besides the point here we invoke this

play13:03

event meaning we call it and then the ui

play13:05

manager what it does is that in the

play13:07

enable function we use our reference to

play13:10

the same scriptable object health

play13:12

manager scriptable object we do dot

play13:15

health change event and we add a

play13:17

listener in this case we add the change

play13:19

slider value function that we made here

play13:22

which just changes the value of the

play13:23

slider to the new amount and on disable

play13:26

we unsubscribe from this event so we

play13:28

remove the listener so this script is

play13:30

listening to the scriptable object and

play13:32

the trigger is telling the scriptable

play13:34

object what value is changing so the

play13:36

scriptable object now acts as the middle

play13:39

man and not only is it scene independent

play13:42

so we can avoid any problems with

play13:45

reloading scenes and the health will get

play13:47

passed on from scene to scene but we

play13:50

also now are not using any single tins

play13:53

and now these two scripts only depend on

play13:56

this one scriptable object and so we've

play13:58

dramatically decreased the complexity of

play14:01

having a bunch of scripts everywhere

play14:03

reference each other all we need to do

play14:05

is drag our scriptable object which you

play14:07

can right click create scriptable object

play14:10

health manager you can call it whatever

play14:12

you want and you can just drag in your

play14:14

health manager scriptable object into

play14:16

your field and when you press play and

play14:18

you reload the scene you'll see that the

play14:19

value still stays the same because it's

play14:21

still reading it from this scriptable

play14:24

object you see that now the health is at

play14:25

90. you see that when we keep going here

play14:27

the health decreases and when we reload

play14:29

the scene the health is the same since

play14:32

it is reading this value from the

play14:33

scriptable object and when we unclick

play14:36

play and click play again you'll see

play14:38

that the value is reset and that is

play14:40

because of this on enable function that

play14:42

is called when the scene is played

play14:44

health equals max health so we've

play14:46

decoupled our code we've made our lives

play14:48

easier and we've also made the lives of

play14:51

the designers of our games easier and so

play14:53

a few other things i wanted to mention

play14:55

are the differences between using a

play14:57

scriptable object and a monobehaviour so

play14:59

with the monobehaviour it's c

play15:01

independent this is nuts independent

play15:03

however you could do something similar

play15:05

with a monobehaviour if you wanted to

play15:07

however since the monobehaviour is in

play15:09

the scene you have to instantiate a game

play15:12

object and that game object has to have

play15:14

a transform component just to act as a

play15:17

middleman whereas the scriptable object

play15:19

does not need that extra memory of the

play15:21

transform component and it does not

play15:23

exist in the scene which is nice and

play15:26

there's also something called dependency

play15:27

injection which dependency injection is

play15:30

when you inject a script with the

play15:32

dependency that it needs so instead of

play15:35

it needing to go and fetch that

play15:36

dependency itself it just waits to

play15:38

receive it and then it can use it for

play15:40

whatever it wants now this is kind of

play15:42

similar to what we're doing with

play15:43

scriptable objects but you'll need a

play15:45

whole framework for dependency injection

play15:48

and it's good because it decouples code

play15:50

and removes hard-coded references

play15:52

decoupling just means separating so it

play15:55

is kind of similar to scriptable objects

play15:56

in a way but scriptable objects are more

play15:58

designer friendly because you can easily

play16:01

drag and drop stuff in the inspector

play16:02

without much code with dependency

play16:04

injection the designers will have to

play16:05

look into the code to see what's going

play16:07

wrong to see how to change values with

play16:09

scriptable objects they can easily add

play16:11

in their own attributes it's visually

play16:13

friendly and it's good for building

play16:15

tools and holding data overall so i hope

play16:18

you enjoyed the video if you did make

play16:19

sure to like subscribe and sign up for

play16:21

notifications by clicking the bell icon

play16:24

and thank you once again to the sponsor

play16:26

of this video mental checkpoint i'd also

play16:28

really like to thank all of my patrons

play16:30

for the support their support makes

play16:31

these kind of videos possible and so i

play16:33

really appreciate it if you're

play16:34

interested the link is in the

play16:35

description i offer source code early

play16:37

access to videos sneak peeks exclusive

play16:39

discord chats and more and with that i'd

play16:42

like to thank my new patrons in the

play16:43

supporter tier we have

play16:45

thank you so much in the enthusiastic

play16:47

tier we have flamed keith andre mirko

play16:52

ever the journeyman nicholas jesse you

play16:55

3000 banu popa

play16:58

sebastian

play16:59

stephen

play17:00

bernard

play17:01

paul knew

play17:05

thank you so very much for your support

play17:07

and in the dedicated tier we have brett

play17:10

thank you so much for all of your

play17:11

support it is really really appreciated

play17:13

if you're interested again the link is

play17:14

in the description and if you haven't

play17:16

joined our discord yet the link is in

play17:17

the description you can chat post memes

play17:19

or ask for help so thank you again for

play17:21

watching and i'll see you next time

play17:27

[Music]

play17:32

[Music]

play17:39

you

Rate This
โ˜…
โ˜…
โ˜…
โ˜…
โ˜…

5.0 / 5 (0 votes)

Related Tags
Scriptable ObjectsUnity Game DevelopmentEvent MessagingGame ArchitectureSingleton PatternDecoupling CodeScene PersistenceDependency InjectionUI ManagementDesign Principles