background top icon
background center wave icon
background filled rhombus icon
background two lines icon
background stroke rhombus icon

Download "How to do MORE with the Observer Pattern"

input logo icon
Video tags
|

Video tags

unity tutorial
unity arcade game
unity game tutorial
unity
game development
game dev
game development unity
programming
c#
software development
learn to code
learn programming
unity tutorials
unity devlog
indiedev
gamedev
unity3d
unity observer pattern
unity generic observer
Subtitles
|

Subtitles

subtitles menu arrow
  • ruRussian
Download
00:00:00
to be honest I wasn't going to make a
00:00:02
video about The Observer pattern it
00:00:04
feels played out on YouTube dozens of
00:00:07
beginner videos about the same two
00:00:08
things updating UI and the new input
00:00:11
system so today we'll quickly look at
00:00:13
the basics but the bulk of this video is
00:00:15
going to be about building a generic
00:00:17
Observer so that you can observe
00:00:19
property and field changes in play mode
00:00:22
and then we're going to take it even
00:00:23
further so that you can observe values
00:00:25
in edit mode and start building more
00:00:27
complex tools using the unity tools
00:00:30
class as always don't forget to hit the
00:00:32
like button when you learn something new
00:00:34
today let's get into
00:00:39
it let's review a basic use of the
00:00:42
Observer pattern a delegate type is a
00:00:44
bit like an interface it specifies the
00:00:47
signature of a method all delegates are
00:00:49
multicast in C which means it can hold
00:00:52
references to more than one function and
00:00:54
when it's invoked it calls each of the
00:00:56
methods it references in turn one after
00:00:58
the other the next line declares an
00:01:00
event named on any collected using the
00:01:02
previously defined notify delegate type
00:01:05
the event keyword in C essentially adds
00:01:08
safety features by restricting how the
00:01:09
delegate can be used for example it can
00:01:12
only be invoked from within the class or
00:01:13
struct where it's declared and external
00:01:16
code can subscribe or unsubscribe for an
00:01:18
event using the plus equals or minus
00:01:20
equal operators but cannot directly
00:01:22
manipulate the list of subscribed
00:01:24
delegates programmers still use
00:01:26
delegates over shorthand action or Funk
00:01:28
when they want to make code more
00:01:29
understand able or self-documenting but
00:01:32
in most cases people just use Funk when
00:01:34
they want to return value and action
00:01:35
when they do
00:01:36
not so for this simple example when the
00:01:39
player bumps into a collectible it's
00:01:41
going to fire off the trigger the
00:01:43
trigger will invoke our action any
00:01:46
subscribers to the action will receive
00:01:48
the points for this collectible and then
00:01:50
we'll just disable the game object to
00:01:52
make this work let's just make another
00:01:54
class called score manager it'll have a
00:01:56
text field it'll keep track of our
00:01:58
current score and and we're going to
00:02:00
have it subscrib to our static event on
00:02:03
our collectible class and we'll just
00:02:05
have an add score method whenever the
00:02:08
event is fired we're going to increase
00:02:10
the score and update our text let's make
00:02:13
sure that we unsubscribe for the event
00:02:14
too I'm just going to move the
00:02:16
subscription down into on enable because
00:02:18
I prefer it that way and I'm going to
00:02:21
move the updating of the text into its
00:02:23
own method because I also want to call
00:02:25
it on awake just so we make sure that
00:02:26
the score text is going to be zero right
00:02:28
at the start going to change these into
00:02:30
expression body methods so it's a little
00:02:32
bit
00:02:33
shorter now back in unity I've already
00:02:35
put the scripts onto the various game
00:02:36
objects you can see here on this
00:02:38
collectible I'm just going to change it
00:02:39
to 50 points on this one but I'll leave
00:02:41
the other box just at 10 and I've
00:02:44
already put the script onto my HUD with
00:02:46
the score text so just hit play and
00:02:49
you'll see how it works everything will
00:02:51
hook up and subscribe to the events
00:02:53
right from the start you can see the
00:02:54
score is zero if I come over here and
00:02:56
grab this box suddenly we have 50 points
00:02:59
and
00:03:00
if we come over here to the other box it
00:03:02
should go up by another 10 points there
00:03:04
we go 60 points so that's as far as
00:03:06
we're going to go with the simple
00:03:08
Observer I'm just going to come out of
00:03:10
play mode again here and I think what
00:03:12
I'm going to do is actually just disable
00:03:13
these two boxes because we're not going
00:03:16
to work with Collectibles anymore for
00:03:18
the rest of this video what I want to
00:03:19
talk about is using a generic Observer
00:03:21
of type T we'll store our type t as a
00:03:25
private field value but we can expose it
00:03:27
to the editor so we can set it and then
00:03:28
we're going to associate this with unity
00:03:31
events let's expose t as a public
00:03:33
property but we're going to have a
00:03:35
special method set whenever we set the
00:03:37
value we're going to notify observers
00:03:39
that it's potentially been changed
00:03:41
before we get to that let's set up a
00:03:43
Constructor for this the Constructor
00:03:44
needs to accept our value T and could
00:03:46
potentially take in a first Unity action
00:03:49
let's default it to null so we don't
00:03:51
have to specify it if we don't want to
00:03:53
we'll set the value if the call back
00:03:55
wasn't null We'll add that as a listener
00:03:57
to our Unity event and let's make sure
00:03:59
that we initialize our Unity event
00:04:01
whenever the Constructor fires in our
00:04:03
set method let's say if the value coming
00:04:06
into the set method is the same as the
00:04:08
value we already have let's bail out now
00:04:11
I want to keep invoke as a separate
00:04:12
method because we might want to call it
00:04:14
at other times and it can handle some
00:04:15
other things for us such as debugging
00:04:17
let's put a debug statement here that'll
00:04:19
actually tell us how many events are we
00:04:21
actually going to invoke here and then
00:04:23
let's actually invoke them by passing in
00:04:24
the value let's add some methods so that
00:04:27
we can add and remove listeners I'll
00:04:28
look co-pilot Phil in some of this but
00:04:30
basically let's do some defensive null
00:04:32
checking if everything's good let's add
00:04:34
The Listener exactly the same thing for
00:04:36
removing a listener let's also make a
00:04:39
method so we can remove all listeners
00:04:42
and finally just for the sake of
00:04:43
completeness let's have a dispose method
00:04:46
so that we actually remove all listeners
00:04:49
and we just reset some values
00:04:51
here come back up to the top and
00:04:53
actually make these set and invoke
00:04:55
methods public so that I can call them
00:04:57
from whichever class is declaring an
00:04:59
observable T let's come over to our
00:05:01
empty hero class here and I'm going to
00:05:03
declare a public Observer of type int
00:05:05
that'll be for our health and we'll just
00:05:07
start it with
00:05:09
100 now in the start method I'm going to
00:05:12
invoke that so any Unity events that are
00:05:15
defined in the editor will fire off
00:05:17
let's add an update method so that I can
00:05:19
test this out so whenever I press the
00:05:22
one key I want my health to go up by 10
00:05:25
let's do a bit of cleanup here we
00:05:27
actually don't need a serialized field
00:05:28
here since this is public
00:05:31
one more thing I've got a health display
00:05:33
script already written it just has a
00:05:34
reference to the text of my health and
00:05:37
it has a public method that we can use
00:05:39
to change that message let's recompile
00:05:41
and go back to Unity so over here in the
00:05:44
inspector you can now see I have this
00:05:45
observable health value and it has room
00:05:48
for some Unity events so we can drag in
00:05:51
our health display reference here and
00:05:53
call its public method which accepts an
00:05:56
integer so I'll just come over here to
00:05:58
my health display and I'm going to drag
00:05:59
that in and then I can select its method
00:06:02
it's a little bit off screen but it's
00:06:04
there at the top because it matches the
00:06:06
signature that's really it let's press
00:06:09
play and try it
00:06:10
out so in play mode here you can see it
00:06:14
right away it invoked the event so it
00:06:16
set it to 100 now I pressed one it went
00:06:18
up to 110 let's press it again and so on
00:06:21
it'll just keep going up by tens every
00:06:23
time I press the button so at this point
00:06:25
you might be thinking great how's this
00:06:27
going to help me out first of all when
00:06:28
you have Behavior associated with a
00:06:30
value start thinking about using an
00:06:32
object to encapsulate it you'll end up
00:06:34
with something much more powerful and
00:06:35
easier to debug than using just the
00:06:37
basic constructs of the language but
00:06:39
beyond that I want to introduce you to
00:06:41
the unity events tools class which is
00:06:43
going to allow us to start adding Unity
00:06:45
events programmatically in edit
00:06:47
mode up at the top of my class I'm going
00:06:49
to add system reflection and using Unity
00:06:52
editor. events now down in our public
00:06:55
method add listener we can add the unity
00:06:58
editor directive and do some special
00:07:00
stuff when we're in edit mode so all
00:07:02
we're going to do here is just use one
00:07:04
of those methods from the unity event
00:07:06
tools class to add a listener during
00:07:08
edit mode and we can do the same thing
00:07:10
in the public method remove
00:07:13
listener now we're going to have to do
00:07:15
something a little bit special when we
00:07:17
want to remove all listeners because
00:07:18
there is no real method to do that so
00:07:20
what we'll do is use some
00:07:23
reflection first let's get the field
00:07:25
info of a private field in the unity
00:07:27
event Base Class which is named n
00:07:29
persistent calls the field info object
00:07:32
has a method named get value that
00:07:33
retrieves the value of the field from an
00:07:35
object in this case the onv value
00:07:37
changed event object we can then use
00:07:39
reflection again to get the method name
00:07:42
clear we can then evoke the clear method
00:07:44
on the value now this effectively will
00:07:46
clear out the persistent calls list of
00:07:48
the unity event for interest sake let's
00:07:50
go and have a look at the unity event
00:07:52
Base Class which all Unity events
00:07:54
inherit from the easiest way to do that
00:07:57
I find is just to declare a variable of
00:07:59
that type and then command click into it
00:08:02
it'll decompile in rer here and here we
00:08:05
go so you can see right here at the top
00:08:08
we've got our M persistent calls it's
00:08:10
private persistent call group type so
00:08:14
let's click into there and see if we
00:08:15
can't find this clear
00:08:18
method and just a little bit down here
00:08:21
you can see here is the clear method so
00:08:24
it's not doing anything magical but the
00:08:26
only way to get at it because up in the
00:08:28
unity Base Class it's marked as private
00:08:31
we need to use reflection okay let's
00:08:33
come out of here I'm just going to
00:08:34
remove that declaration that I made and
00:08:37
clean up a little bit and what we can do
00:08:39
now is think about how we can use this
00:08:42
in an editor tool now I've already
00:08:44
started a class here it doesn't do
00:08:45
anything special it's just overriding
00:08:48
the on inspector guey and calling the
00:08:50
Base Class you can see riters even
00:08:51
graded out because it does nothing so
00:08:53
just a few rules before we start adding
00:08:55
persistent events the referencing type
00:08:58
must be Unity engine object object the
00:08:59
method that we call has to be public no
00:09:01
Anonymous or lambdas and the parameter
00:09:04
type has to match now the reason for
00:09:06
that is that everything that we put into
00:09:08
the unity event has to be
00:09:10
serializable so in our tool here let's
00:09:13
get a reference to our hero which is the
00:09:14
target of this inspector and let's start
00:09:17
adding some buttons we can have a button
00:09:18
to increase health one to decrease
00:09:20
health and then what I want to do is
00:09:22
have two more buttons that will add or
00:09:24
remove a debugger now I've made a tiny
00:09:27
debugger Singleton which inherits from
00:09:29
Unity object and has a method that will
00:09:31
match the signature that we can use just
00:09:33
for this example so we can have a button
00:09:35
that will add that method and one that
00:09:36
will remove it let's just take a quick
00:09:38
look at the debugger it's super simple
00:09:40
it's just inheriting from a boilerplate
00:09:42
Singleton and has a method that matches
00:09:44
the type of unity event we
00:09:48
want okay so back here in unity I'm
00:09:50
going to click add debugger and watch
00:09:52
what happens we serialize one of these
00:09:54
methods right into our Unity events that
00:09:57
also automatically added a single for me
00:10:00
now if I jump into play mode right away
00:10:02
we see that our start method invoked the
00:10:04
two listeners and we see the debug
00:10:06
message as well as showing the correct
00:10:08
Health amount now I can start moving the
00:10:10
health up and down no problem but what
00:10:13
happens if I remove the
00:10:14
debugger and then come out of play mode
00:10:17
well guess what that we already
00:10:19
serialized that onto the object so there
00:10:21
it is no problem that thing is going to
00:10:24
persist hence the name
00:10:26
persistent um what else can we try here
00:10:29
well how about if we just clear this up
00:10:31
again and I remove the debugger what's
00:10:34
going to happen let's go into play mode
00:10:36
and see what happens if I were to add a
00:10:38
debugger now if I click the button you
00:10:41
see it will add the debugger here but
00:10:44
it's not going to serialize it because
00:10:45
we did it in play mode so we come out of
00:10:47
play mode and it's gone so these editor
00:10:49
methods work just like dragging and
00:10:51
dropping so for example right now we
00:10:54
could just add another Unity event here
00:10:56
and technically we could just drag in
00:10:58
this s Singleton and reference the
00:11:00
method on it oops I missed there drag it
00:11:02
again and now we can just grab the debug
00:11:05
or debug method again and you'll see it
00:11:08
serialized it just as if we had done it
00:11:10
programmatically and that's the expected
00:11:16
Behavior just one more feature I want to
00:11:18
add to this today and that is the
00:11:20
implicit operator instead of having to
00:11:22
call health. Value every time you want
00:11:24
to get the value out of this public
00:11:26
property we can just use an implicit
00:11:28
operat to just convert whatever our
00:11:31
value T is right out into that type
00:11:34
automatically so that's just a shorthand
00:11:36
way of saying that when we request our
00:11:38
health property we don't have to tack on
00:11:41
the dot value it's just going to
00:11:43
implicitly convert our property into the
00:11:45
value integer that we want now as an
00:11:48
example of that let's just come back to
00:11:49
the hero class and add a bit of code to
00:11:51
our start method so we could say in
00:11:54
example one we'll get health dot value
00:11:56
so we'll grab the property but in
00:11:58
example example two will just get health
00:12:01
and you can see already in the code hint
00:12:03
here it's casting it as an integer but
00:12:05
let's see what happens when we debug
00:12:07
this out does it is example one equal to
00:12:10
example two and what if we just debug
00:12:13
the health object what is that going to
00:12:15
say let's recompile and hit
00:12:18
play so we can see that example one was
00:12:21
equal to example two but when we just
00:12:24
debug the object itself it's actually
00:12:26
telling us that it's an observer of the
00:12:29
system integer 32 type I will say one
00:12:32
thing about implicit operator and that
00:12:34
is it does have some overhead so don't
00:12:37
go throwing it everywhere but once in a
00:12:39
while it's very useful I was thinking a
00:12:42
cool editor tool that uses this might be
00:12:44
to observe a challenge rating on an
00:12:45
enemy in the editor and as your game
00:12:47
designers increase the challenge rating
00:12:50
your listeners can configure the enemy
00:12:52
with different strategies or gear the
00:12:54
only limitation really is your
00:12:56
imagination I think that'll have to be a
00:12:58
topic for a future video however if you
00:13:01
want to learn more about Advanced game
00:13:03
events check out the event Bus video and
00:13:05
I'll see you
00:13:07
there

Description:

Unity C# Architecture: Learn how to observe variables using a streamlined generic Observer class aided by the UnityEventTools class. This video covers play and edit modes, focusing on the serialization and persistence of UnityEvents programmatically in the Editor. 🔔 Subscribe for more Unity Tutorials https://www.youtube.com/@git-amend ▬ Contents of this video ▬▬▬▬▬▬▬▬▬▬ 0:00 C# Observer/Delegate Basics 3:00 Generic Observer 6:25 Unity Event Tools Generic Observer Source Code: https://gist.github.com/adammyhre/353195d4870e8fd0cc0028659e66f208 Resources Unity Event Tools Documentation https://docs.unity3d.com/2023.2/Documentation/ScriptReference/Events.UnityEventTools.html Creating Observable Variables with Delegates in Unity Using C# https://copyprogramming.com/howto/unity-c-creating-observable-variables-with-delegates Unity C# Creating Observable Variables with Delegates https://stackoverflow.com/questions/70445037/unity-c-sharp-creating-observable-variables-with-delegates Value Observer (FREE tool from Infinity Code) https://assetstore.unity.com/packages/tools/utilities/value-observer-266922?aid=1101lw3sv C# Implicit and Explicit Operators: A Comprehensive Guide https://medium.com/@gustavorestani/c-implicit-and-explicit-operators-a-comprehensive-guide-5e6972cc8671 Assets Shown In This Video (Affiliate Links) Dmitriy Dryzhak Models and Animations: https://assetstore.unity.com/publishers/10181?aid=1101lw3sv Odin: https://assetstore.unity.com/publishers/3727?aid=1101lw3sv Dungeon Mason Tiny Hero Duo: (FREE): https://assetstore.unity.com/packages/3d/characters/humanoids/rpg-tiny-hero-duo-pbr-polyart-225148?aid=1101lw3sv Chromisu: Handpainted Forest MEGA Pack https://assetstore.unity.com/packages/3d/vegetation/handpainted-forest-mega-pack-248421?aid=1101lw3sv SineVFX: Better Crystals https://assetstore.unity.com/packages/vfx/shaders/better-crystals-235002?aid=1101lw3sv VFX Trees: https://assetstore.unity.com/packages/vfx/particles/environment/stylized-vfx-trees-gpu-based-effect-238647?aid=1101lw3sv Kronnect Volumetric Fog & Mist 2: https://assetstore.unity.com/packages/vfx/shaders/fullscreen-camera-effects/volumetric-fog-mist-2-162694?aid=1101lw3sv Kronnect Cloud Shadows: https://assetstore.unity.com/packages/vfx/shaders/cloud-shadows-fx-267702?aid=1101lw3sv Kronnect Beautify: https://assetstore.unity.com/packages/vfx/shaders/fullscreen-camera-effects/beautify-3-advanced-post-processing-233073?aid=1101lw3sv Kyeoms Hyper Casual FX 2: https://assetstore.unity.com/packages/vfx/particles/hyper-casual-fx-pack-vol-2-245262?aid=1101lw3sv MalberS Animations: Forest Golems: https://assetstore.unity.com/packages/3d/characters/creatures/poly-art-forest-golems-164389?aid=1101lw3sv REXARD SpellBook Icons Megapack: https://assetstore.unity.com/packages/2d/gui/icons/spellbook-megapack-109615?aid=1101lw3sv ARCEY Vampire Skill Icons: https://assetstore.unity.com/packages/2d/gui/icons/vampire-skill-icons-250993?aid=1101lw3sv *Follow me!* https://linktr.ee/gitamend

Preparing download options

popular icon
Popular
hd icon
HD video
audio icon
Only sound
total icon
All
* — If the video is playing in a new tab, go to it, then right-click on the video and select "Save video as..."
** — Link intended for online playback in specialized players

Questions about downloading video

mobile menu iconHow can I download "How to do MORE with the Observer Pattern" video?mobile menu icon

  • http://unidownloader.com/ website is the best way to download a video or a separate audio track if you want to do without installing programs and extensions.

  • The UDL Helper extension is a convenient button that is seamlessly integrated into YouTube, Instagram and OK.ru sites for fast content download.

  • UDL Client program (for Windows) is the most powerful solution that supports more than 900 websites, social networks and video hosting sites, as well as any video quality that is available in the source.

  • UDL Lite is a really convenient way to access a website from your mobile device. With its help, you can easily download videos directly to your smartphone.

mobile menu iconWhich format of "How to do MORE with the Observer Pattern" video should I choose?mobile menu icon

  • The best quality formats are FullHD (1080p), 2K (1440p), 4K (2160p) and 8K (4320p). The higher the resolution of your screen, the higher the video quality should be. However, there are other factors to consider: download speed, amount of free space, and device performance during playback.

mobile menu iconWhy does my computer freeze when loading a "How to do MORE with the Observer Pattern" video?mobile menu icon

  • The browser/computer should not freeze completely! If this happens, please report it with a link to the video. Sometimes videos cannot be downloaded directly in a suitable format, so we have added the ability to convert the file to the desired format. In some cases, this process may actively use computer resources.

mobile menu iconHow can I download "How to do MORE with the Observer Pattern" video to my phone?mobile menu icon

  • You can download a video to your smartphone using the website or the PWA application UDL Lite. It is also possible to send a download link via QR code using the UDL Helper extension.

mobile menu iconHow can I download an audio track (music) to MP3 "How to do MORE with the Observer Pattern"?mobile menu icon

  • The most convenient way is to use the UDL Client program, which supports converting video to MP3 format. In some cases, MP3 can also be downloaded through the UDL Helper extension.

mobile menu iconHow can I save a frame from a video "How to do MORE with the Observer Pattern"?mobile menu icon

  • This feature is available in the UDL Helper extension. Make sure that "Show the video snapshot button" is checked in the settings. A camera icon should appear in the lower right corner of the player to the left of the "Settings" icon. When you click on it, the current frame from the video will be saved to your computer in JPEG format.

mobile menu iconWhat's the price of all this stuff?mobile menu icon

  • It costs nothing. Our services are absolutely free for all users. There are no PRO subscriptions, no restrictions on the number or maximum length of downloaded videos.