Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
1
00:00:04,290 --> 00:00:11,520
So let's take a look now at the notorious singleton pattern or anti pattern, depending on who you ask.
2
00:00:11,550 --> 00:00:18,600
So the idea of the singleton pattern is that you have some sort of object that you only wants to exist
3
00:00:18,600 --> 00:00:26,280
once you only ever wanted to load up once, such as an audio player, an ambient audio player.
4
00:00:26,460 --> 00:00:29,550
You might want this to work across scenes.
5
00:00:29,940 --> 00:00:34,470
So you want there to be one and you want to be able to crossfade audio.
6
00:00:34,470 --> 00:00:38,300
There's only one speaker system in your computer, so it makes sense.
7
00:00:38,330 --> 00:00:45,270
There's only one audio kind of central audio player and that is responsible for cross fighting between
8
00:00:45,270 --> 00:00:47,010
all the different audio in your game.
9
00:00:47,280 --> 00:00:54,660
So if you were to make that decision, then you might decide that if we go and find our Singleton's
10
00:00:54,660 --> 00:01:01,800
code here under patterns and we look at the simple audio player, you might decide that you want the
11
00:01:01,800 --> 00:01:06,780
class to be responsible for making sure that there is only ever one instance here.
12
00:01:07,110 --> 00:01:14,000
And here's how it's usually done in language like C-sharp or even Java, or sometimes C++, too.
13
00:01:14,430 --> 00:01:21,720
The idea is that you create a static instance of the class itself within the class, so you have something
14
00:01:21,720 --> 00:01:27,120
like the ambient audio player class, which has its Crossfade new music method, for example.
15
00:01:27,480 --> 00:01:29,550
That's basically what we want it to be able to do.
16
00:01:30,060 --> 00:01:36,540
But in order to make sure that we only ever get one of these instantiated, we add a private static
17
00:01:36,540 --> 00:01:38,100
member that points to itself.
18
00:01:38,250 --> 00:01:40,620
So this is typically the instance started off as no.
19
00:01:40,740 --> 00:01:45,510
You then have a public static getter to get hold of the instance.
20
00:01:45,520 --> 00:01:53,160
So in another class, you would be able to use it simply by typing something like ambient audio player
21
00:01:53,160 --> 00:01:55,020
dot jet instance.
22
00:01:55,740 --> 00:01:59,790
And you can see that simply goes ahead and would get the instance.
23
00:01:59,790 --> 00:02:01,020
Now, what does that do?
24
00:02:01,050 --> 00:02:04,760
Well, first of all, it checks whether we've already created an instance before.
25
00:02:04,770 --> 00:02:07,290
If we've already created instance, we just go ahead and return that one.
26
00:02:07,740 --> 00:02:11,460
And if we haven't created instance, it goes ahead and creates the instance.
27
00:02:12,000 --> 00:02:18,030
And now, just to make sure that nobody else is going to create a second instance of the ambient audio
28
00:02:18,030 --> 00:02:25,710
player anywhere in your code, you then make the default constructor private.
29
00:02:25,740 --> 00:02:30,780
So that means that no one else outside of this class can go and construct this class.
30
00:02:31,410 --> 00:02:37,200
So taken together, this allows us to instantiate a single instance of the class, make sure nobody
31
00:02:37,200 --> 00:02:42,870
else does it and give us away from anywhere in our code base to access this instance.
32
00:02:43,230 --> 00:02:46,260
Now stop me if you have spotted an issue.
33
00:02:46,920 --> 00:02:49,170
Well, it's basically global state.
34
00:02:49,170 --> 00:02:52,950
So why is it any better than using global state?
35
00:02:53,070 --> 00:02:54,480
Said Statics, a global state.
36
00:02:54,480 --> 00:02:56,460
We've got this static instance of that variable.
37
00:02:56,760 --> 00:02:58,740
We've got a way of accessing it from anywhere.
38
00:02:58,770 --> 00:02:59,910
Isn't it just global state?
39
00:03:00,270 --> 00:03:02,370
Well, a few things make it better for a start.
40
00:03:02,400 --> 00:03:05,010
Singleton means that we don't pollute any namespaces.
41
00:03:05,010 --> 00:03:06,860
This isn't so much a problem with static.
42
00:03:06,870 --> 00:03:09,300
Statics already solve that problem.
43
00:03:09,300 --> 00:03:15,000
Statics don't pollute the namespace, but if you had other languages that you're using like C++, then
44
00:03:15,000 --> 00:03:19,320
you can pollute the global namespace there with global variables and singletons.
45
00:03:19,320 --> 00:03:25,700
Wouldn't it provides encapsulation so you don't have to access these static variables directly.
46
00:03:25,710 --> 00:03:31,020
You can do it through a public interface that manages the state of a class again.
47
00:03:31,560 --> 00:03:33,030
Statics can do the same thing.
48
00:03:33,030 --> 00:03:38,190
You can have private static and you can have public static accesses, and you would essentially get
49
00:03:38,190 --> 00:03:41,520
the same thing without having to create an instance of the class at all.
50
00:03:41,640 --> 00:03:47,970
However, the final point is sort of useful is that it allows us to have lazy initialization.
51
00:03:48,330 --> 00:03:55,230
So if you didn't want this object to be in initialized until we needed it, then it does allow us to
52
00:03:55,230 --> 00:03:56,100
do that.
53
00:03:56,100 --> 00:04:01,890
But basically, it's a not much better than global state, and this is why people see it as being a
54
00:04:01,890 --> 00:04:03,000
bit of an anti-party.
55
00:04:03,240 --> 00:04:06,570
So let's dig in a little bit more into why it's bad.
56
00:04:06,960 --> 00:04:09,000
So it's still a global state.
57
00:04:09,120 --> 00:04:15,960
It can be accessed from anywhere, so it can lead to that spaghetti code situation where you don't know
58
00:04:15,960 --> 00:04:18,510
who is dependent on this code.
59
00:04:18,810 --> 00:04:24,780
It's not immediately obvious we break the rule of three that you can only do one thing because suddenly
60
00:04:24,780 --> 00:04:32,100
this class is responsible for making sure it's instantiated only once, as well as its usual routine
61
00:04:32,400 --> 00:04:34,230
of just doing its job.
62
00:04:34,500 --> 00:04:42,480
But in unity, we often have recourse to want to do something like this because we ultimately can't
63
00:04:42,480 --> 00:04:46,220
write any code that has a larger scope than the scene.
64
00:04:46,230 --> 00:04:48,660
Everything has to reside in mono behaviors.
65
00:04:49,050 --> 00:04:53,580
So we often want those behaviors to travel between scenes with us.
66
00:04:53,730 --> 00:04:57,440
Now, how could we do this in a mono behavior?
67
00:04:57,460 --> 00:05:02,550
Because at the moment we've seen how we can do this just using pure C-sharp classes.
68
00:05:02,900 --> 00:05:06,350
If we want to do this with a minor behavior, this is going to be a challenge.
69
00:05:06,650 --> 00:05:12,560
So imagine that we had a class that looked very similar to the one that we had previously, except this
70
00:05:12,560 --> 00:05:14,180
time it's a mono behavior.
71
00:05:14,660 --> 00:05:20,090
And you can go and get the state of the code linked against this lecture to play around with this,
72
00:05:20,090 --> 00:05:20,750
if you like.
73
00:05:21,470 --> 00:05:27,530
And the first part of this I've already done for you, which is I've said that we on a week we mark
74
00:05:27,530 --> 00:05:30,260
this object as do not destroy on load.
75
00:05:30,500 --> 00:05:37,820
You may also need to do something else on a week in order to ensure that this mode of behavior is instantiated
76
00:05:37,820 --> 00:05:38,440
only once.
77
00:05:38,450 --> 00:05:45,500
Take your inspiration from the way we are using statics and that instance variable to see if you can
78
00:05:45,500 --> 00:05:47,510
achieve something similar with a mono behavior.
79
00:05:47,900 --> 00:05:54,350
And if we get more than one minor behavior in the scene at a time, you can destroy the one that we
80
00:05:54,350 --> 00:05:55,010
don't want.
81
00:05:56,210 --> 00:05:57,110
VIDEO And go.
82
00:06:00,390 --> 00:06:00,910
OK.
83
00:06:01,230 --> 00:06:03,720
Let's head back in to visual studio code.
84
00:06:03,840 --> 00:06:10,080
We're going to go to this ambient audio player behaviour, and what we're going to do here is we're
85
00:06:10,080 --> 00:06:18,720
going to essentially look at whether we are the chosen one when we enter a week and the way we're going
86
00:06:18,720 --> 00:06:22,170
to do that is by having a private static instance.
87
00:06:22,500 --> 00:06:29,790
So going to have a private variable of type ambient audio player behavior and it is going to be called
88
00:06:29,790 --> 00:06:33,810
the instance, and I've forgotten this needs to be static as well.
89
00:06:34,880 --> 00:06:37,880
Because we want it to be shared between all instances of the class.
90
00:06:38,630 --> 00:06:40,760
And it's going to be set to null by default.
91
00:06:41,150 --> 00:06:47,360
Now when we awake for the first time in the first scene, we load that instance is going to be null.
92
00:06:47,420 --> 00:06:58,100
So we'll say if the instance is null, we're going to want to set the instance equal to this and we're
93
00:06:58,100 --> 00:07:01,280
going to want to set don't destroy, unload as well.
94
00:07:02,330 --> 00:07:11,660
However, if this is not the case and so else, we have an instance already and we are not at that instance.
95
00:07:11,930 --> 00:07:14,660
So we need to make this not an else, but an else.
96
00:07:14,960 --> 00:07:16,820
If the instance?
97
00:07:18,040 --> 00:07:26,380
Is not equal to this, then we need to destroy ourselves and probably the game object that we're on.
98
00:07:26,680 --> 00:07:35,170
So we're going to call destroy game object like so so now the audio player will make sure that there
99
00:07:35,170 --> 00:07:40,480
is only one of it hanging around at a given time and we can test this out.
100
00:07:40,480 --> 00:07:42,370
In our scene example.
101
00:07:42,370 --> 00:07:48,550
We had this singleton example with the audio player behavior and we've got a reload, a script which
102
00:07:48,550 --> 00:07:50,740
will reload the scene when you hit Ah.
103
00:07:50,890 --> 00:07:57,670
So if we go ahead and hit play now, then you can see we've got a singleton example.
104
00:07:57,670 --> 00:08:04,810
Here is under the Don't Destroy and load section and we can go ahead and hit all and the scene reloads.
105
00:08:04,810 --> 00:08:09,070
But we don't get a new singleton example being created here.
106
00:08:09,340 --> 00:08:16,030
It will stick to that initial one, and we probably do get one created very briefly, but it gets destroyed
107
00:08:16,030 --> 00:08:16,960
on awake.
108
00:08:17,320 --> 00:08:21,970
So that's the singleton pattern, as it's usually used in a nutshell.
109
00:08:21,970 --> 00:08:28,570
As I say, try not to use it as much as possible because I do think it violates some of our best coding
110
00:08:28,570 --> 00:08:29,300
practices.
111
00:08:29,320 --> 00:08:31,150
Sometimes it's unavoidable.
112
00:08:31,330 --> 00:08:36,370
But if for those cases, I have got a solution that, in my opinion, is slightly neater and we're going
113
00:08:36,370 --> 00:08:38,350
to see that in the next lecture.
114
00:08:38,409 --> 00:08:38,980
I'll see that.
11936
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.