WEBVTT 1 00:00:05.607 --> 00:00:09.841 Game Advanced Beta Type Version 2 00:00:09.841 --> 00:00:12.059 GCC Academy 3 00:00:27.852 --> 00:00:28.802 Hello 4 00:00:28.802 --> 00:00:32.299 I am Lee Youngho, in charge of the shooting game development lecture 5 00:00:32.299 --> 00:00:36.099 In this chapter, we will learn the Beta Type version 6 00:00:36.099 --> 00:00:40.580 First, we will learn how to create a manager using the Singleton design pattern 7 00:00:40.580 --> 00:00:43.680 We will understand design patterns and learn how to create 8 00:00:43.680 --> 00:00:47.540 and use the Singleton pattern for score management 9 00:00:47.540 --> 00:00:51.860 Next, we will learn about memory management using objectPool 10 00:00:51.860 --> 00:00:54.210 We will implement objectPooling 11 00:00:54.210 --> 00:00:56.164 using array and list data structures 12 00:00:56.640 --> 00:01:00.293 Creating a Manager Using the Singleton Design Pattern 13 00:01:00.619 --> 00:01:03.769 Let's learn how to create a manager 14 00:01:03.769 --> 00:01:05.739 using the Singleton pattern 15 00:01:05.739 --> 00:01:09.019 The pattern you see here refers to a design pattern 16 00:01:09.019 --> 00:01:11.260 which is essentially a way of structuring or designing the system 17 00:01:11.260 --> 00:01:12.842 Singleton is like this 18 00:01:15.921 --> 00:01:18.059 Singleton literally means something singular 19 00:01:18.059 --> 00:01:19.779 When using these single instances 20 00:01:19.779 --> 00:01:23.220 C# provides grammatical elements in the pattern 21 00:01:23.220 --> 00:01:25.260 A key grammatical element used in the Singleton pattern 22 00:01:25.260 --> 00:01:28.580 is static 23 00:01:28.580 --> 00:01:30.820 Like this 24 00:01:30.820 --> 00:01:33.513 Let's draw a circle 25 00:01:33.513 --> 00:01:36.379 We call it a class or an instance 26 00:01:36.379 --> 00:01:38.820 Anyway, these are objects 27 00:01:38.820 --> 00:01:41.820 Right? these are objects 28 00:01:41.820 --> 00:01:43.139 Object A 29 00:01:43.139 --> 00:01:44.779 Object B 30 00:01:44.779 --> 00:01:47.699 Each of them has its own member variables 31 00:01:47.699 --> 00:01:52.459 properties and features like this 32 00:01:52.459 --> 00:01:55.019 properties and features are going to be here like this 33 00:01:55.019 --> 00:01:57.459 The variables inside this function 34 00:01:57.459 --> 00:02:00.739 are called local variables 35 00:02:00.739 --> 00:02:03.019 The variables that are inside the class but outside the functions are called member variables 36 00:02:03.019 --> 00:02:06.820 and from the class's perspective, they are considered global 37 00:02:06.820 --> 00:02:08.059 From its perspective, these are considered global 38 00:02:08.059 --> 00:02:11.179 Why? Because it can access them as well 39 00:02:11.179 --> 00:02:13.539 But this one, called member variables 40 00:02:13.539 --> 00:02:17.059 Let's say each object is like a school 41 00:02:17.059 --> 00:02:18.858 Jane is here 42 00:02:22.600 --> 00:02:23.558 John is here 43 00:02:25.419 --> 00:02:26.860 For each object 44 00:02:26.860 --> 00:02:30.100 In school, when they want to share information with everyone 45 00:02:30.100 --> 00:02:31.220 what do they use? 46 00:02:31.220 --> 00:02:33.860 They utilize a white board 47 00:02:33.860 --> 00:02:35.740 white board right? 48 00:02:35.740 --> 00:02:38.148 On the board, detention 49 00:02:40.979 --> 00:02:42.580 John 50 00:02:42.580 --> 00:02:44.380 we can write like this 51 00:02:44.380 --> 00:02:45.940 then who would've written this? 52 00:02:45.940 --> 00:02:47.699 Of course, someone must have written this 53 00:02:47.699 --> 00:02:50.822 for contents to be registered on the board 54 00:02:50.822 --> 00:02:52.979 The area where everyone has access to 55 00:02:52.979 --> 00:02:57.740 is what we call the Static area 56 00:02:57.740 --> 00:03:00.860 So this is a static area 57 00:03:00.860 --> 00:03:02.259 In this area 58 00:03:02.259 --> 00:03:05.100 we could have a detention list 59 00:03:05.100 --> 00:03:05.899 like this 60 00:03:05.899 --> 00:03:08.220 the important part is actually, who wrote this 61 00:03:08.220 --> 00:03:09.539 Someone must've written it to be there 62 00:03:09.539 --> 00:03:10.860 When the teacher comes in and asks 63 00:03:10.860 --> 00:03:12.580 who wrote this? 64 00:03:12.580 --> 00:03:14.580 So, they place the reference 65 00:03:14.580 --> 00:03:17.699 Who wrote this? Jane wrote it 66 00:03:17.699 --> 00:03:19.699 Right here, we specify Jane wrote this 67 00:03:19.699 --> 00:03:21.820 Attach Jane as a reference 68 00:03:21.820 --> 00:03:25.580 Jane. reference, like this 69 00:03:25.580 --> 00:03:27.211 Jane is the name of the class 70 00:03:31.740 --> 00:03:35.059 We can use the class name this here 71 00:03:35.059 --> 00:03:36.979 But then she writes again 72 00:03:36.979 --> 00:03:40.220 under Detention list, John, Jane wrote the same thing again 73 00:03:40.220 --> 00:03:41.300 If they wrote the same thing over and over 74 00:03:41.300 --> 00:03:43.339 the teacher can 75 00:03:43.339 --> 00:03:44.740 be angry with the kids 76 00:03:44.740 --> 00:03:46.100 So, in here 77 00:03:46.100 --> 00:03:47.660 Just like I mentioned 78 00:03:47.660 --> 00:03:50.500 Can there be two variables of the same name? 79 00:03:50.500 --> 00:03:52.940 There shouldn't be 80 00:03:52.940 --> 00:03:56.500 Since this is a storage, data area 81 00:03:56.500 --> 00:03:57.860 you can use static to register data here 82 00:03:57.860 --> 00:03:59.179 with static attached 83 00:03:59.179 --> 00:04:00.539 and utilize it 84 00:04:00.539 --> 00:04:03.619 of course we can add functions 85 00:04:03.619 --> 00:04:04.740 With one reference 86 00:04:04.740 --> 00:04:07.619 We can only register one variable 87 00:04:07.619 --> 00:04:10.259 This is what static area is all about 88 00:04:10.259 --> 00:04:11.300 This design method is 89 00:04:11.300 --> 00:04:13.619 called the Singleton pattern 90 00:04:13.619 --> 00:04:14.860 We can use this method 91 00:04:14.860 --> 00:04:17.700 to make our ScoreManager 92 00:04:19.670 --> 00:04:21.459 There are several ways of making 93 00:04:21.459 --> 00:04:23.299 different singleton patterns 94 00:04:23.299 --> 00:04:25.660 Here, we will create and use it 95 00:04:25.660 --> 00:04:27.380 in a simplified form 96 00:04:27.380 --> 00:04:29.420 But the content is the same 97 00:04:29.420 --> 00:04:30.899 Open ScoreManager.cs 98 00:04:30.899 --> 00:04:33.420 Open it from the visual studio 99 00:04:33.420 --> 00:04:35.113 I will go here 100 00:04:38.420 --> 00:04:40.220 GetScore 101 00:04:40.220 --> 00:04:42.064 below that 102 00:04:42.064 --> 00:04:44.260 and right above Start function 103 00:04:44.260 --> 00:04:45.940 let me declare 104 00:04:45.940 --> 00:04:50.500 Here, we will create a Singleton object 105 00:04:50.500 --> 00:04:52.779 public static here 106 00:04:52.779 --> 00:04:54.100 attach static over here 107 00:04:54.100 --> 00:04:54.980 grammatically 108 00:04:54.980 --> 00:04:58.380 and then, with whose name? 109 00:04:58.380 --> 00:05:00.260 with this ScoreManager's name 110 00:05:00.260 --> 00:05:02.899 it can be registered as a reference 111 00:05:02.899 --> 00:05:05.019 for the variable that comes after 112 00:05:05.019 --> 00:05:06.739 So, we first write the data type after this 113 00:05:06.739 --> 00:05:10.179 We will register ScoreManager here 114 00:05:10.179 --> 00:05:11.700 since the name is a variable 115 00:05:11.700 --> 00:05:14.220 Typically, Singleton objects are written in uppercase 116 00:05:14.220 --> 00:05:15.829 Instance like this 117 00:05:17.363 --> 00:05:20.260 Let's leave it without any value 118 00:05:20.260 --> 00:05:23.100 Then, a singleton object 119 00:05:23.100 --> 00:05:25.739 gets registered right here 120 00:05:25.739 --> 00:05:27.223 With the name of Instance 121 00:05:27.223 --> 00:05:31.220 The data type will be registered as ScoreManager 122 00:05:31.220 --> 00:05:32.579 How can we make it? 123 00:05:32.579 --> 00:05:34.339 ScoreManager.Instance 124 00:05:34.339 --> 00:05:36.339 Like this 125 00:05:36.339 --> 00:05:38.380 then we don't have when 126 00:05:38.380 --> 00:05:39.540 There's no value to it 127 00:05:39.540 --> 00:05:41.820 when are we going to specify the value here? 128 00:05:41.820 --> 00:05:43.540 What kind of value goes in there? 129 00:05:43.540 --> 00:05:46.220 When you press the play button 130 00:05:46.220 --> 00:05:47.660 the ScoreManager object will be 131 00:05:47.660 --> 00:05:49.380 loaded into memory 132 00:05:49.380 --> 00:05:50.859 meaning it will be created 133 00:05:50.859 --> 00:05:52.380 and it is instance 134 00:05:52.380 --> 00:05:54.739 When it's being created 135 00:05:54.739 --> 00:05:56.140 we can have the value in here 136 00:05:56.140 --> 00:05:57.980 then we can use Start function 137 00:05:57.980 --> 00:06:00.299 it can be good if we do that 138 00:06:00.299 --> 00:06:01.260 Start and similar ones 139 00:06:01.260 --> 00:06:03.380 are life cycle function right? 140 00:06:03.380 --> 00:06:04.859 Life cycle functions 141 00:06:04.859 --> 00:06:08.339 go through a life of getting created and removed 142 00:06:08.339 --> 00:06:10.380 These also have the point of view 143 00:06:10.380 --> 00:06:14.899 First, we have Jane here 144 00:06:14.899 --> 00:06:16.500 the number one 145 00:06:16.500 --> 00:06:17.899 this one is created first 146 00:06:17.899 --> 00:06:21.500 and then the number two is created next 147 00:06:21.500 --> 00:06:25.100 when that happens, number two wants to know about number one 148 00:06:25.100 --> 00:06:29.500 So, it uses number one dot, name dot and so on 149 00:06:29.500 --> 00:06:30.619 accessing will face no problems 150 00:06:30.619 --> 00:06:33.500 but what's the problem? this could happen 151 00:06:33.500 --> 00:06:34.700 If it's trying to access the second instance 152 00:06:34.700 --> 00:06:38.619 before it has been created 153 00:06:38.619 --> 00:06:40.579 it would cause a problem because the instance doesn't exist yet 154 00:06:40.579 --> 00:06:42.859 So, would it be a problem or no? 155 00:06:42.859 --> 00:06:44.660 Of course it will be, because it doesn't exist yet 156 00:06:44.660 --> 00:06:47.739 It just doesn't exist 157 00:06:47.739 --> 00:06:51.899 So, it is required to be assumed 158 00:06:51.899 --> 00:06:54.019 that they must exist together 159 00:06:54.019 --> 00:06:55.140 For that 160 00:06:55.140 --> 00:06:57.660 Which life cycle function should we use? 161 00:06:57.660 --> 00:07:01.500 There's a function called Awake 162 00:07:01.500 --> 00:07:03.940 This Awake function, when we press play 163 00:07:03.940 --> 00:07:05.820 we have in our world 164 00:07:05.820 --> 00:07:06.980 the ones that are registered 165 00:07:06.980 --> 00:07:08.459 ones that are already added into the hierarchy 166 00:07:08.459 --> 00:07:10.619 In those cases 167 00:07:10.619 --> 00:07:12.700 the Awake function is called first 168 00:07:12.700 --> 00:07:14.179 That's why this one is already created 169 00:07:14.179 --> 00:07:17.019 it's not born yet, only been conceived 170 00:07:17.019 --> 00:07:18.660 Then, those objects will call 171 00:07:18.660 --> 00:07:20.739 all of their Awake functions first 172 00:07:20.739 --> 00:07:22.380 and handle their initialization 173 00:07:22.380 --> 00:07:24.500 after all the Awake functions 174 00:07:24.500 --> 00:07:27.059 of the objects are called and process is complete 175 00:07:27.059 --> 00:07:31.579 Then, the OnEnabled function 176 00:07:31.579 --> 00:07:34.459 an event function is called next 177 00:07:34.459 --> 00:07:35.940 After this one 178 00:07:35.940 --> 00:07:38.500 Only after that, the Start function 179 00:07:38.500 --> 00:07:41.459 will be called for all the objects collectively 180 00:07:41.459 --> 00:07:43.909 In other words, if we set the 181 00:07:43.909 --> 00:07:45.377 ScoreManager's Instance value 182 00:07:45.377 --> 00:07:48.420 in the Awake function, the value will already be assigned 183 00:07:48.420 --> 00:07:49.380 so there won't be any problems 184 00:07:49.380 --> 00:07:51.260 So, we will create an Awake function 185 00:07:51.260 --> 00:07:54.596 and set the value there 186 00:07:56.820 --> 00:07:59.059 Right above Start function 187 00:07:59.059 --> 00:08:02.619 I will make an Awake function like this 188 00:08:02.619 --> 00:08:05.100 In here, when the Instance has to no 189 00:08:05.100 --> 00:08:11.140 If, Instance has no value, null 190 00:08:11.140 --> 00:08:12.660 What are we going to do then? 191 00:08:12.660 --> 00:08:17.579 By using this, you are referring 192 00:08:17.579 --> 00:08:19.820 to the instance of the object itself 193 00:08:19.820 --> 00:08:22.140 The Instance object refers to the ScoreManager object 194 00:08:22.140 --> 00:08:23.579 This Instance Object 195 00:08:23.579 --> 00:08:25.500 Itself wants to be in there 196 00:08:25.500 --> 00:08:27.940 So, in the world, who is it? 197 00:08:27.940 --> 00:08:31.380 It is the ScoreManager object itself 198 00:08:31.380 --> 00:08:32.820 being assigned to the Instance variable 199 00:08:32.820 --> 00:08:34.340 How do we access it? 200 00:08:34.340 --> 00:08:36.099 Use ScoreManager 201 00:08:36.099 --> 00:08:38.059 Then how do we want 202 00:08:38.059 --> 00:08:40.020 others to access me? 203 00:08:40.020 --> 00:08:41.900 When you access it here 204 00:08:41.900 --> 00:08:44.020 we are referring 205 00:08:44.020 --> 00:08:45.580 to myself by using Jane.me 206 00:08:45.580 --> 00:08:47.500 We can access and use the Instance object here 207 00:08:47.500 --> 00:08:51.460 as much as we want 208 00:08:51.460 --> 00:08:54.419 Now, let's take a quick look at how 209 00:08:54.419 --> 00:08:57.380 this makes things much more convenient 210 00:08:57.380 --> 00:08:59.659 Go into Enemy.cs 211 00:08:59.659 --> 00:09:02.859 To get the value for this one 212 00:09:02.859 --> 00:09:04.859 Find the GameObject first 213 00:09:04.859 --> 00:09:06.580 There was the inconvenience of having 214 00:09:06.580 --> 00:09:08.020 to retrieve the ScoreManager component 215 00:09:08.020 --> 00:09:10.710 Now, this part is no longer necessary 216 00:09:12.739 --> 00:09:13.739 Need no more 217 00:09:13.739 --> 00:09:18.260 Instead of using sm, you can directly use ScoreManager.Instance 218 00:09:18.260 --> 00:09:21.518 to access the ScoreManager instance 219 00:09:21.518 --> 00:09:22.500 Just like so 220 00:09:22.500 --> 00:09:26.419 Because it's directly the ScoreManager instance 221 00:09:26.419 --> 00:09:31.500 we can directly assign it here like this 222 00:09:31.500 --> 00:09:34.219 By doing this, we can access and use it conveniently 223 00:09:34.219 --> 00:09:36.539 without having to find other objects 224 00:09:36.539 --> 00:09:40.219 This is the advantage of utilizing singleton pattern 225 00:09:40.219 --> 00:09:43.029 Save it and go back to Unity 226 00:09:43.029 --> 00:09:44.679 To press play button 227 00:09:46.148 --> 00:09:53.019 the normal increase of the current score when running the game has been confirmed 228 00:09:53.019 --> 00:09:55.059 You can see that the current score is 229 00:09:55.059 --> 00:09:57.380 increasing correctly 230 00:09:57.380 --> 00:09:59.460 But if we only use it this way 231 00:09:59.460 --> 00:10:00.900 it can feel a bit inconvenient 232 00:10:00.900 --> 00:10:02.140 Why? 233 00:10:02.140 --> 00:10:05.700 It’s quite difficult to interpret here, right? 234 00:10:05.700 --> 00:10:07.460 Let's say you guys just came back after a few days of sleep 235 00:10:07.460 --> 00:10:08.900 If you looked at this code after about ten days 236 00:10:08.900 --> 00:10:11.419 you'd have to deal with the issue of interpreting it 237 00:10:11.419 --> 00:10:13.271 What is this all about? 238 00:10:13.271 --> 00:10:15.099 It means that the readability is low 239 00:10:15.099 --> 00:10:18.140 To improve the readability of this part, we can make adjustments 240 00:10:18.140 --> 00:10:19.940 Let's try using the Get Set properties 241 00:10:19.940 --> 00:10:22.737 provided by the C# language to improve this 242 00:10:24.380 --> 00:10:26.700 Let's move to ScoreManager.cs 243 00:10:26.700 --> 00:10:29.619 By using Get/Set Property form C# 244 00:10:29.619 --> 00:10:32.260 Let's create the ones 245 00:10:32.260 --> 00:10:34.460 that are under GetScore 246 00:10:34.460 --> 00:10:35.739 and SetScore 247 00:10:35.739 --> 00:10:39.140 Get set Property's grammar is very simple 248 00:10:39.140 --> 00:10:40.099 Look at it this way 249 00:10:40.099 --> 00:10:42.790 Do you know what Sphinx is? 250 00:10:42.790 --> 00:10:44.539 It has human head 251 00:10:44.539 --> 00:10:47.380 But what body does it have? 252 00:10:47.380 --> 00:10:53.397 It has a body of a lion, some kind of man beast 253 00:10:53.397 --> 00:10:57.644 It seems like the Sphinx might be strange, but it's that kind of feeling 254 00:10:57.644 --> 00:10:59.340 What is this? 255 00:10:59.340 --> 00:11:02.619 Two different species are combined together 256 00:11:02.619 --> 00:11:07.059 In this way, different types of forms have been combined 257 00:11:07.059 --> 00:11:09.260 So, you can think of the Get/Set properties 258 00:11:09.260 --> 00:11:11.099 in a similar way 259 00:11:11.099 --> 00:11:15.979 The head part is the variable being used, so it functions like a variable 260 00:11:15.979 --> 00:11:21.700 The head part is the variable 261 00:11:21.700 --> 00:11:24.340 and the body part 262 00:11:24.340 --> 00:11:27.619 the body part is the function 263 00:11:27.619 --> 00:11:30.619 This is how the Get/Set properties are used 264 00:11:30.619 --> 00:11:32.020 As we use ScoreManager 265 00:11:32.020 --> 00:11:34.099 Let's look into it in details 266 00:11:34.099 --> 00:11:37.179 Shall we first create a SetProperty 267 00:11:37.179 --> 00:11:38.940 to make the Get/Set properties below? 268 00:11:38.940 --> 00:11:41.859 Let's create GetProperty and SetProperty like this 269 00:11:41.859 --> 00:11:44.979 We will add public to allow external access 270 00:11:44.979 --> 00:11:49.659 set the type to int, and name it Score 271 00:11:49.659 --> 00:11:52.380 You will access it using the name Score like this 272 00:11:52.380 --> 00:11:56.902 How is it? Up to this point, it just looks like a variable 273 00:11:56.902 --> 00:11:59.219 but now the body part has been added 274 00:11:59.219 --> 00:12:01.140 This is the characteristic of Get/Set properties 275 00:12:01.140 --> 00:12:04.700 By adding Get/Set properties here 276 00:12:04.700 --> 00:12:07.219 we can create a function like GetScore 277 00:12:07.219 --> 00:12:10.979 Just like creating a Get function 278 00:12:10.979 --> 00:12:12.539 The role it does 279 00:12:12.539 --> 00:12:16.580 We will take the role from here and place it here 280 00:12:16.580 --> 00:12:20.460 Then, it will be able to perform exactly the same role as the GetScore function 281 00:12:20.460 --> 00:12:22.419 The content is implemented like a function 282 00:12:22.419 --> 00:12:24.987 Now, let's add the SetProperty 283 00:12:26.700 --> 00:12:30.859 The Set works the same way as SetScore 284 00:12:30.859 --> 00:12:34.900 So, you can take the part from SetScore 285 00:12:34.900 --> 00:12:36.059 select everything 286 00:12:36.059 --> 00:12:38.219 Let's cut it and place it elsewhere 287 00:12:38.219 --> 00:12:44.219 Ctrl and x and place it inside the Set function 288 00:12:44.219 --> 00:12:48.539 We have transformed the function into a Get Set property 289 00:12:48.539 --> 00:12:52.380 Why? This is done for usability and readability 290 00:12:52.380 --> 00:12:55.260 So, how do you use it? 291 00:12:55.260 --> 00:12:57.500 You can use it like a variable 292 00:12:57.500 --> 00:13:00.580 If you use it like a variable, you want to get the value 293 00:13:00.580 --> 00:13:03.059 Usually, when getting the value, how do we do it? 294 00:13:03.059 --> 00:13:08.859 In the form on the right, we have the assignment operator 295 00:13:08.859 --> 00:13:12.299 When you have int a, let's say we assign 10 to it 296 00:13:12.299 --> 00:13:14.659 Then call this assignment operator 297 00:13:14.659 --> 00:13:16.340 Right? assignment operator 298 00:13:16.340 --> 00:13:19.340 Then what do we call this part on the right? 299 00:13:19.340 --> 00:13:21.558 Usually we refer to it as R value, the value on the right side of the equation 300 00:13:21.558 --> 00:13:23.179 So, when we have this 301 00:13:23.179 --> 00:13:26.580 We call Get right away 302 00:13:26.580 --> 00:13:29.859 Get, right? 303 00:13:29.859 --> 00:13:31.259 How about on the left side? 304 00:13:31.259 --> 00:13:36.580 We are inserting the value, making it Set 305 00:13:36.580 --> 00:13:38.619 Did you understand? L value for this one 306 00:13:38.619 --> 00:13:40.580 Sending the value on the right side to the left 307 00:13:40.580 --> 00:13:44.380 Get for this side, and Set for the other side 308 00:13:44.380 --> 00:13:46.859 Did you understand? 309 00:13:46.859 --> 00:13:48.500 When you want to get a certain value 310 00:13:48.500 --> 00:13:50.219 For this value, use Get 311 00:13:50.219 --> 00:13:52.739 and for the other, use Set 312 00:13:52.739 --> 00:13:54.689 And for this one here 313 00:13:54.689 --> 00:13:56.780 use it like it's a variable 314 00:13:56.780 --> 00:13:59.739 Let's take a look at how to use it 315 00:13:59.739 --> 00:14:03.580 Since the Get and Set functions 316 00:14:03.580 --> 00:14:05.419 will be replaced with Get/Set properties 317 00:14:05.419 --> 00:14:10.059 we will go ahead and delete them 318 00:14:10.059 --> 00:14:11.780 Now, we will use Score 319 00:14:11.780 --> 00:14:15.700 and move on to Enemy.cs 320 00:14:15.700 --> 00:14:18.659 Things are made complex like this, right? 321 00:14:18.659 --> 00:14:20.020 How can we handle this part? 322 00:14:20.020 --> 00:14:21.859 We can make it a single line like this 323 00:14:21.859 --> 00:14:25.299 In ScoreManager, the Instance part remains the same 324 00:14:25.299 --> 00:14:28.179 Getting the Singleton object is the same 325 00:14:28.179 --> 00:14:30.179 But here, which do we use? 326 00:14:30.179 --> 00:14:33.539 the Score variable is a Get/Set property 327 00:14:33.539 --> 00:14:37.059 It looks like a variable, but its body is a function 328 00:14:37.059 --> 00:14:40.380 We want to increase the value here 329 00:14:40.380 --> 00:14:41.500 like this 330 00:14:41.500 --> 00:14:43.900 Then we are increasing the value 331 00:14:43.900 --> 00:14:45.739 How are we supposed to use this? 332 00:14:45.739 --> 00:14:47.700 Actually it is set up like this 333 00:14:47.700 --> 00:14:53.099 this code essentially retrieves the current value of Score 334 00:14:53.099 --> 00:14:54.979 and then adds 1 to it 335 00:14:54.979 --> 00:15:01.380 You can do this to increase by 1 336 00:15:01.380 --> 00:15:03.830 Originally, this is implemented in a way 337 00:15:03.830 --> 00:15:05.299 that allows it to be shortened 338 00:15:05.299 --> 00:15:08.340 So, as you can see, here it is getting the value 339 00:15:08.340 --> 00:15:09.619 which is the Get 340 00:15:09.619 --> 00:15:13.140 Then, when we add the two values and put the result back here 341 00:15:13.140 --> 00:15:15.140 it becomes Set 342 00:15:15.140 --> 00:15:16.260 Did you understand? 343 00:15:16.260 --> 00:15:21.780 How is the readability between the one above 344 00:15:21.780 --> 00:15:24.020 and the one below, given how simple it is? 345 00:15:24.020 --> 00:15:25.979 At once, you can know that 346 00:15:25.979 --> 00:15:26.700 this one increases the score 347 00:15:26.700 --> 00:15:28.780 This one is somewhat complicated 348 00:15:28.780 --> 00:15:30.630 So, with this part 349 00:15:30.630 --> 00:15:33.940 we will upgrade it 350 00:15:33.940 --> 00:15:36.539 Save it 351 00:15:36.539 --> 00:15:38.700 When we save it inside here 352 00:15:38.700 --> 00:15:40.619 and actually have the screen updated 353 00:15:40.619 --> 00:15:41.700 in details 354 00:15:41.700 --> 00:15:46.099 check every bit of this saves properly 355 00:15:46.099 --> 00:15:47.114 Let's play it now 356 00:16:06.419 --> 00:16:08.940 Right now, I see the current score and the high score are being updated 357 00:16:08.940 --> 00:16:10.609 I will turn it off and then turn it back on 358 00:16:12.619 --> 00:16:16.219 We can see that the save is properly done 359 00:16:16.219 --> 00:16:19.580 By applying the Singleton design pattern 360 00:16:19.580 --> 00:16:22.780 and implementing the Get/Set properties 361 00:16:22.780 --> 00:16:26.700 you can create a solution that allows you to implement 362 00:16:26.700 --> 00:16:27.871 this content in such a simple way 363 00:16:28.395 --> 00:16:32.157 Memory Management Using an objectPool 364 00:16:32.900 --> 00:16:35.140 Then, this time, let's learn 365 00:16:35.140 --> 00:16:37.440 how to utilize an objectPool 366 00:16:37.440 --> 00:16:39.219 for memory management 367 00:16:39.219 --> 00:16:41.020 An objectPool is 368 00:16:41.020 --> 00:16:45.419 a technique where, as I mentioned before 369 00:16:45.419 --> 00:16:48.769 when shooting bullets, you take the bullets from the magazine 370 00:16:48.769 --> 00:16:49.918 and use them 371 00:16:51.700 --> 00:16:54.340 There will be two places where the objectPool is used 372 00:16:54.340 --> 00:16:57.900 The first place is where the bullets are created 373 00:16:57.900 --> 00:16:59.460 The bullets are being created where? 374 00:16:59.460 --> 00:17:00.966 in the PlayerFire.cs file 375 00:17:00.966 --> 00:17:03.659 a bullet is fired whenever it's needed 376 00:17:03.659 --> 00:17:07.260 So, here, let's create a magazine where 377 00:17:07.260 --> 00:17:09.540 we can use the objectPool 378 00:17:09.540 --> 00:17:15.660 Let's first name this the objectPool Magazine 379 00:17:15.660 --> 00:17:21.099 Then, let's add the number of bullets to be placed in the magazine here 380 00:17:21.099 --> 00:17:25.370 Next, let's create an objectPool array 381 00:17:25.370 --> 00:17:33.060 corresponding to this magazine 382 00:17:33.060 --> 00:17:35.939 Then, this will be the size of the array 383 00:17:35.939 --> 00:17:39.780 So, let's add public int poolSize for that 384 00:17:39.780 --> 00:17:43.380 The name will be poolSize, and the value will be set to 10 385 00:17:43.380 --> 00:17:45.660 That means the magazine will hold 10 bullets 386 00:17:45.660 --> 00:17:49.380 The size of this array will be the value you set 387 00:17:49.380 --> 00:17:52.430 So, you will add GameObject 388 00:17:52.430 --> 00:17:54.420 and then insert the array like this 389 00:17:54.420 --> 00:17:57.620 And then, you will name it 390 00:17:57.620 --> 00:18:00.459 bulletObjectPool like this 391 00:18:00.459 --> 00:18:04.099 So, when do we add bullets to this magazine? 392 00:18:04.099 --> 00:18:07.459 At the start, we create all the bullets at once 393 00:18:07.459 --> 00:18:09.339 Then, when we fire bullets during the game 394 00:18:09.339 --> 00:18:12.180 we can take them from the magazine and shoot them 395 00:18:12.180 --> 00:18:20.339 So, when it is created, to the objectPool 396 00:18:20.339 --> 00:18:23.699 which is the magazine 397 00:18:23.699 --> 00:18:29.060 it will generate and add one bullet at a time 398 00:18:29.060 --> 00:18:31.300 Let's go ahead and implement this 399 00:18:31.300 --> 00:18:34.380 The first step is when it is created, so we will do it in the Start function 400 00:18:34.380 --> 00:18:37.130 And ultimately, what we want to do is 401 00:18:37.130 --> 00:18:39.619 add bullets to the magazine 402 00:18:39.619 --> 00:18:43.300 want to add bullets to the objectPool 403 00:18:43.300 --> 00:18:46.540 This is our ultimate goal 404 00:18:46.540 --> 00:18:53.221 Then, the second step is to generate the bullets in the bullet factory 405 00:18:56.300 --> 00:19:00.500 And how many bullets should be generated in the bullet factory? 406 00:19:00.500 --> 00:19:03.395 We need to generate 10 of them in total 407 00:19:03.395 --> 00:19:09.565 So, you need to loop to create as many bullets as the number of bullets according to magazine capacity 408 00:19:12.099 --> 00:19:13.459 So, what do we do? 409 00:19:13.459 --> 00:19:19.559 You need to first create the magazine 410 00:19:19.559 --> 00:19:21.979 with a size that can hold the bullets 411 00:19:21.979 --> 00:19:27.180 Then, if you do it in order, it will work like this 412 00:19:27.180 --> 00:19:30.020 Create the magazine with the appropriate size 413 00:19:30.020 --> 00:19:32.620 Then loop through the size of the magazine 414 00:19:32.620 --> 00:19:34.540 and create one bullet at a time 415 00:19:34.540 --> 00:19:38.260 What do you do? add it to the magazine 416 00:19:38.260 --> 00:19:42.859 So, first, I'll create the size for the magazine here 417 00:19:42.859 --> 00:19:46.819 So, you will create an array by adding 418 00:19:46.819 --> 00:19:49.780 new GameObject to bulletObjectPool 419 00:19:49.780 --> 00:19:56.540 The size of the array will be equal to poolSize 420 00:19:56.540 --> 00:19:59.780 Then, for the second step 421 00:19:59.780 --> 00:20:01.699 you need to loop and repeat the process 422 00:20:01.699 --> 00:20:05.859 Repeating means using a loop, a for loop would be appropriate 423 00:20:05.859 --> 00:20:09.109 int i equal to 0 how many i? 424 00:20:09.109 --> 00:20:12.099 so the loop will run timed by poolSize 425 00:20:12.099 --> 00:20:14.339 i++ 426 00:20:14.339 --> 00:20:16.979 Each time, you can create one bullet 427 00:20:16.979 --> 00:20:19.292 and add it to the objectPool 428 00:20:22.420 --> 00:20:24.540 Where do we create the bullets? 429 00:20:24.540 --> 00:20:28.660 Currently, when the fire button is pressed 430 00:20:28.660 --> 00:20:31.241 bullets are created and placed like this 431 00:20:31.241 --> 00:20:32.500 that's what we've done so far 432 00:20:32.500 --> 00:20:34.420 Do you know the part where the bullet is created? 433 00:20:34.420 --> 00:20:36.870 You can press Ctrl and C to copy it 434 00:20:36.870 --> 00:20:38.819 and then paste it here 435 00:20:38.819 --> 00:20:44.713 Then, this part becomes the bullet creation in the bullet factory 436 00:20:44.713 --> 00:20:47.540 Next, you want to add the bullet to the objectPool 437 00:20:47.540 --> 00:20:48.859 That means you want to add it to the array 438 00:20:48.859 --> 00:20:51.441 So at bulletObjectPool 439 00:20:51.441 --> 00:20:54.990 Which order? at i-th position 440 00:20:54.990 --> 00:20:58.859 let's add the created bullet to the pool like this 441 00:20:58.859 --> 00:21:02.819 After saving it, when you go and press the play button, right? 442 00:21:02.819 --> 00:21:06.780 Then, all the bullets will fire at once 443 00:21:06.780 --> 00:21:08.979 How is it? they all releases at once 444 00:21:08.979 --> 00:21:11.060 This is not what we want 445 00:21:11.060 --> 00:21:14.739 So, instead of automatically flying out at the start 446 00:21:14.739 --> 00:21:17.260 we want to disable the bullet 447 00:21:17.260 --> 00:21:20.310 by setting its SetActive to false 448 00:21:20.310 --> 00:21:21.979 This will deactivate the bullet 449 00:21:21.979 --> 00:21:24.500 preventing it from moving or performing any actions 450 00:21:24.500 --> 00:21:26.339 Let's go and see what happens 451 00:21:26.339 --> 00:21:28.140 Click play button 452 00:21:28.140 --> 00:21:32.740 Then, you can see that a total of 10 bullets 453 00:21:32.740 --> 00:21:35.180 have been created from here to here 454 00:21:35.180 --> 00:21:36.579 and It is disabled 455 00:21:36.579 --> 00:21:39.060 So, when we press the fire button 456 00:21:39.060 --> 00:21:42.160 we can check each one 457 00:21:42.160 --> 00:21:44.380 and make it fly one by one 458 00:21:44.380 --> 00:21:47.630 Now, let's go ahead and implement 459 00:21:47.630 --> 00:21:50.819 the part where we fire the bullet 460 00:21:50.819 --> 00:21:55.420 Until now, when the user presses the fire button 461 00:21:55.420 --> 00:21:58.939 we created a bullet and set its position 462 00:21:58.939 --> 00:22:02.060 Now, how should this part be modified? 463 00:22:02.060 --> 00:22:12.500 Exactly, now we need to take a bullet from the magazine and fire it 464 00:22:12.500 --> 00:22:15.819 However, when we take a bullet from the magazine and fire it 465 00:22:15.819 --> 00:22:19.979 you'll see that we fired one bullet 466 00:22:19.979 --> 00:22:24.020 This is the screen, and we fired one bullet here 467 00:22:24.020 --> 00:22:24.939 So, it is flying now 468 00:22:24.939 --> 00:22:28.060 It's flying, and then you fired another bullet 469 00:22:28.060 --> 00:22:32.219 Should it fly again? No 470 00:22:32.219 --> 00:22:36.020 Exactly, we shouldn't suddenly take it and shoot it again from here 471 00:22:36.020 --> 00:22:38.619 At the very least, we need to wait until the bullet leaves the screen 472 00:22:38.619 --> 00:22:40.519 before we can take it back and fire it again 473 00:22:40.519 --> 00:22:42.140 or perform similar tasks 474 00:22:42.140 --> 00:22:45.219 In other words, we shouldn't reuse a bullet 475 00:22:45.219 --> 00:22:48.660 that is already activated and flying 476 00:22:48.660 --> 00:22:50.619 the deactivated ones 477 00:22:50.619 --> 00:22:53.459 We need to make sure that only the deactivated ones 478 00:22:53.459 --> 00:22:55.660 are taken and fired from here 479 00:22:55.660 --> 00:22:57.099 If all the bullets are already created 480 00:22:57.099 --> 00:23:00.979 meaning there are 10 bullets 481 00:23:00.979 --> 00:23:04.060 and they're already prepared 482 00:23:04.060 --> 00:23:06.979 you won't be able to shoot if there are no more available bullets 483 00:23:06.979 --> 00:23:11.322 In that case, you would need to increase the size of the magazine or perform a similar task 484 00:23:11.322 --> 00:23:13.060 Fortunately, after shooting all the bullets 485 00:23:13.060 --> 00:23:16.060 this one bullet went outside, and we deactivated it 486 00:23:16.060 --> 00:23:16.979 Then what happens? 487 00:23:16.979 --> 00:23:19.739 Now, we will be able to fire this bullet again 488 00:23:19.739 --> 00:23:24.420 when firing a bullet from the magazine 489 00:23:24.420 --> 00:23:29.939 the first condition that it should be deactivated and ready to be reused 490 00:23:29.939 --> 00:23:42.260 You must fire a deactivated bullet 491 00:23:42.260 --> 00:23:48.739 This means that we are activating the bullet again 492 00:23:48.739 --> 00:23:51.420 Let's go ahead and implement this 493 00:23:51.420 --> 00:23:53.180 When taking a bullet from the magazine to fire 494 00:23:53.180 --> 00:23:54.420 it should be a deactivated bullet 495 00:23:54.420 --> 00:23:58.697 Then, we need to loop through the entire magazine 496 00:23:58.697 --> 00:24:00.819 Start with for function 497 00:24:00.819 --> 00:24:02.819 int i = 0 498 00:24:02.819 --> 00:24:07.140 Since it's the same as above, let's copy it 499 00:24:07.140 --> 00:24:14.260 if we copy it inside this function, it will work as expected 500 00:24:14.260 --> 00:24:16.979 let's try adding it up to this point for now 501 00:24:16.979 --> 00:24:19.140 this should also be inside the for loop 502 00:24:19.140 --> 00:24:20.579 but we can do that later 503 00:24:20.579 --> 00:24:22.819 let's see what happens 504 00:24:22.819 --> 00:24:26.140 First, we need to figure out if it's deactivated bullet or not 505 00:24:26.140 --> 00:24:26.819 How do we do it? 506 00:24:26.819 --> 00:24:29.939 if i-th bullet in the ObjectPool 507 00:24:29.939 --> 00:24:36.020 if bulletObjectPool 508 00:24:36.020 --> 00:24:40.500 the i-th bullet 509 00:24:40.500 --> 00:24:43.939 if it's deactivated, let's process it 510 00:24:43.939 --> 00:24:47.459 let's place it in a way that's easier to understand first 511 00:24:47.459 --> 00:24:49.300 Let's first take one bullet 512 00:24:49.300 --> 00:24:52.619 So, we can place it as GameObject bullet 513 00:24:52.619 --> 00:24:55.900 and then position it like this 514 00:24:55.900 --> 00:24:58.339 Let's move it into the for loop as well 515 00:24:58.339 --> 00:25:00.939 When this is done 516 00:25:00.939 --> 00:25:02.819 for deactivated bullet 517 00:25:02.819 --> 00:25:05.500 you can check if the bullet is currently activated 518 00:25:05.500 --> 00:25:08.619 or deactivated by asking it 519 00:25:08.619 --> 00:25:12.699 Bullet, dot give me activeSelf 520 00:25:12.699 --> 00:25:15.780 This will tell us whether it is 521 00:25:15.780 --> 00:25:17.780 currently active or inactive 522 00:25:17.780 --> 00:25:20.099 If it is true, it means the bullet is activated 523 00:25:20.099 --> 00:25:22.660 and if it is false, it means the bullet is deactivated 524 00:25:22.660 --> 00:25:24.220 What is this value? 525 00:25:24.220 --> 00:25:26.260 since it is deactivated, it will be false 526 00:25:26.260 --> 00:25:30.339 What do we want to do here? 527 00:25:30.339 --> 00:25:34.219 What we want to do is this part 528 00:25:34.219 --> 00:25:37.939 after firing, placing the bullet at the muzzle's position 529 00:25:37.939 --> 00:25:42.540 First, let's place the bullet at the muzzle's position 530 00:25:42.540 --> 00:25:45.819 So, you set the bullet's position and then activate it 531 00:25:45.819 --> 00:25:49.469 Bullet.SetActive then true 532 00:25:49.469 --> 00:25:53.180 It would be activated then 533 00:25:53.180 --> 00:25:55.180 So, now we've already fired 534 00:25:55.180 --> 00:25:57.579 Do we have to continue to figure out? 535 00:25:57.579 --> 00:25:59.300 You need to shoot only once 536 00:25:59.300 --> 00:26:06.664 We can use break to exit the for loop 537 00:26:06.664 --> 00:26:10.430 Let's save it see what happens 538 00:26:16.020 --> 00:26:19.109 As you can see, initially, the bullets are all 539 00:26:19.109 --> 00:26:21.900 in a deactivated state when they start 540 00:26:21.900 --> 00:26:23.060 Let me fire one 541 00:26:27.099 --> 00:26:30.299 after bang bang bang, suddenly 542 00:26:30.299 --> 00:26:31.900 there are only 7 bullets left 543 00:26:31.900 --> 00:26:35.660 It seems that an error has occurred, as seen in the console window 544 00:26:35.660 --> 00:26:38.099 Why does this happen, MissingReferenceException? 545 00:26:38.099 --> 00:26:40.819 Let's double click it to expand it 546 00:26:40.819 --> 00:26:42.619 This part is where an error occurred 547 00:26:42.619 --> 00:26:45.180 What this means is that when we collide with the enemy 548 00:26:45.180 --> 00:26:48.619 we're handling the situation where both 549 00:26:48.619 --> 00:26:49.660 the enemy and the player die 550 00:26:49.660 --> 00:26:52.140 In other words, we made them disappear from the world 551 00:26:52.140 --> 00:26:54.260 they were completely removed 552 00:26:54.260 --> 00:26:57.310 But when I try to use it, it says 553 00:26:57.310 --> 00:27:00.402 It's not there 554 00:27:00.402 --> 00:27:04.300 Do you understand the point of the issue? 555 00:27:04.300 --> 00:27:06.600 Then, when it collides with an enemy 556 00:27:06.600 --> 00:27:09.020 or when it collides with the DestryZone 557 00:27:09.020 --> 00:27:11.339 If it's a bullet, what should we do? 558 00:27:11.339 --> 00:27:16.180 We would need to add it back to the magazine 559 00:27:16.180 --> 00:27:18.656 In the Enemy OnCollisionEnter 560 00:27:18.656 --> 00:27:24.140 after reviewing where that both the enemy and the bullet are involved 561 00:27:24.140 --> 00:27:29.420 if it's a bullet, what should we do? 562 00:27:29.420 --> 00:27:33.865 Then we should add it back 563 00:27:33.865 --> 00:27:35.398 if we don't, Players and other objects 564 00:27:35.398 --> 00:27:37.860 will disappear 565 00:27:37.860 --> 00:27:39.819 and in order to figure out it's a bullet 566 00:27:39.819 --> 00:27:41.060 we need to proceed with this first 567 00:27:41.060 --> 00:27:45.619 if, the one collided, other 568 00:27:45.619 --> 00:27:50.099 We took a look at the name of other.gameObject 569 00:27:50.099 --> 00:27:52.945 If the name contains Bullet 570 00:27:52.945 --> 00:27:55.660 if the name includes Bullet 571 00:27:55.660 --> 00:27:57.459 what do we do when there's Bullet? 572 00:27:57.459 --> 00:27:59.219 It is Bullet 573 00:27:59.219 --> 00:28:01.380 What do we do? 574 00:28:01.380 --> 00:28:03.300 Let's deactivate it 575 00:28:03.300 --> 00:28:07.819 So, let's deactivate this 576 00:28:07.819 --> 00:28:09.939 This is the process of loading the magazine 577 00:28:09.939 --> 00:28:16.859 so, use other.gameObject.SetActive and false 578 00:28:16.859 --> 00:28:26.619 Otherwise, from else, use Destroy 579 00:28:26.619 --> 00:28:29.500 With this set up, when the colliding object is Bullet 580 00:28:29.500 --> 00:28:31.260 it will deactivate and put it back to the magazine 581 00:28:31.260 --> 00:28:33.540 or, it will be destroyed 582 00:28:33.540 --> 00:28:36.060 set this value like this 583 00:28:36.060 --> 00:28:38.260 Which other part should it go into? 584 00:28:38.260 --> 00:28:41.219 We shall set one up for DestroyZone, too 585 00:28:41.219 --> 00:28:45.184 Let me choose this part here like this 586 00:28:45.184 --> 00:28:46.819 Ctrl and C 587 00:28:46.819 --> 00:28:49.569 Comeback to DestroyZone 588 00:28:49.569 --> 00:28:51.339 Want to destroy one that's colliding 589 00:28:51.339 --> 00:28:56.699 Ctrl and V to this part 590 00:28:56.699 --> 00:28:59.180 If the object that collided is a bullet, we should deactivate it 591 00:28:59.180 --> 00:29:01.619 If it's not a bullet, we should destroy it 592 00:29:01.619 --> 00:29:03.180 That's that 593 00:29:03.180 --> 00:29:04.870 Let's play a bit 594 00:29:04.870 --> 00:29:05.870 Play 595 00:29:11.140 --> 00:29:13.577 So far, we've managed to create the bullets 596 00:29:13.577 --> 00:29:15.500 and set them up with an objectPool 597 00:29:15.500 --> 00:29:18.140 Now, let's handle the enemies in the same way 598 00:29:18.140 --> 00:29:22.260 and set them up with an objectPool as well 599 00:29:22.260 --> 00:29:24.739 To make EnemyObjectPool 600 00:29:24.739 --> 00:29:26.820 Currently, as we can see, the EnemyManager is handling 601 00:29:26.820 --> 00:29:31.060 these tasks for each Enemy 602 00:29:31.060 --> 00:29:33.780 Here, we have the EnemyManager as shown 603 00:29:33.780 --> 00:29:36.420 If each EnemyManager has its own objectPool 604 00:29:36.420 --> 00:29:37.900 it could become difficult to manage 605 00:29:37.900 --> 00:29:39.939 So, we'll use a single EnemyManager and 606 00:29:39.939 --> 00:29:43.189 let the others just reference the position where they should be created 607 00:29:43.189 --> 00:29:45.459 allowing them to use the same objectPool 608 00:29:45.459 --> 00:29:47.659 So, let's have it be used 609 00:29:47.659 --> 00:29:50.380 with the name of SpawnPoint 610 00:29:50.380 --> 00:29:53.619 Press Ctrl and D in EnemyManager to duplicate 611 00:29:53.619 --> 00:29:56.300 Then Enemy will be created at this position 612 00:29:56.300 --> 00:29:59.344 Let's name all the duplicates as SpawnPoint 613 00:29:59.344 --> 00:30:03.938 SpawnPoint, like this 614 00:30:03.938 --> 00:30:06.492 Change the name to SpawnPoint for all of them 615 00:30:09.632 --> 00:30:11.230 So, without the EnemyManager 616 00:30:11.230 --> 00:30:13.180 select all the others 617 00:30:13.180 --> 00:30:15.409 Enemy Manager script on the right 618 00:30:15.409 --> 00:30:19.109 shall be removed in Remove Component 619 00:30:19.109 --> 00:30:23.280 Then, there will be only one EnemyManager left 620 00:30:23.280 --> 00:30:26.280 and a Transform component 621 00:30:26.280 --> 00:30:28.833 And then, for this EnemyManager 622 00:30:28.833 --> 00:30:33.000 we will set it up so that enemies are created at the locations of these spawnpoint objects 623 00:30:33.000 --> 00:30:35.650 So the enemies will be generated based on their respective spawn points 624 00:30:35.650 --> 00:30:38.360 So let's dive into EnemyManager 625 00:30:38.360 --> 00:30:41.560 Just as before, let's set it up 626 00:30:41.560 --> 00:30:45.639 to use the objectPool in the same way as with bullets 627 00:30:45.639 --> 00:30:55.151 So, you'll create a size for the objectPool 628 00:30:55.151 --> 00:30:56.651 and then you'll also need an array for the enemies 629 00:30:56.651 --> 00:31:00.119 You can set public int poolSize 630 00:31:00.119 --> 00:31:02.728 so that 10 enemies can spawn at once 631 00:31:02.728 --> 00:31:04.328 just like bullets 632 00:31:04.328 --> 00:31:06.028 having maximum enemies of 10 633 00:31:06.028 --> 00:31:08.614 Next, let's create the objectPool array 634 00:31:08.614 --> 00:31:10.053 like this 635 00:31:10.053 --> 00:31:13.603 You can create the GameObject array 636 00:31:13.603 --> 00:31:19.199 and name it enemyObjectPool like this 637 00:31:19.199 --> 00:31:22.050 Next, there were the SpawnPoint objects where they would be created 638 00:31:22.050 --> 00:31:25.350 So, right now, you've placed 5 SpawnPoint objects 639 00:31:25.350 --> 00:31:27.639 To specify the positions of the 5 SpawnPoint objects 640 00:31:27.639 --> 00:31:29.905 Let's create a Transform array 641 00:31:29.905 --> 00:31:35.010 Here, let's store the relevant details 642 00:31:35.010 --> 00:31:37.036 for the spawnpoint objects in the array 643 00:31:37.036 --> 00:31:40.625 and we'll create a public transform array 644 00:31:40.625 --> 00:31:46.380 and name it SpawnPoint 645 00:31:46.380 --> 00:31:48.580 Shall we save it now? 646 00:31:48.580 --> 00:31:51.360 and go back to Unity 647 00:31:51.360 --> 00:31:53.560 In the EnemyManager 648 00:31:53.560 --> 00:31:55.210 you can see the Spawn Points here, right? 649 00:31:55.210 --> 00:31:56.959 The Pool Size is also set to 10 650 00:31:56.959 --> 00:31:59.859 by pressing + button, you can add one vehicle by another 651 00:31:59.859 --> 00:32:03.259 If you look at the top right of the Inspector window 652 00:32:03.259 --> 00:32:04.760 There's a lock here 653 00:32:04.760 --> 00:32:07.038 Let me lock this up 654 00:32:07.038 --> 00:32:09.438 So even if you select other objects 655 00:32:09.438 --> 00:32:11.238 if you click it, the lock stays locked 656 00:32:11.238 --> 00:32:13.240 it remains fixed on the EnemyManager 657 00:32:13.240 --> 00:32:17.040 Now, let's select the SpawnPoint and choose them all at once 658 00:32:17.040 --> 00:32:18.840 and then grab this SpawnPoint 659 00:32:18.840 --> 00:32:22.334 drag and drop it in here 660 00:32:22.334 --> 00:32:24.834 All the objects will be arranged at once 661 00:32:24.834 --> 00:32:29.039 Once this task is complete, I will unlock the lock again 662 00:32:29.039 --> 00:32:31.789 Now, let's implement it so that we can use the objectPool 663 00:32:31.789 --> 00:32:33.539 Let's implement this 664 00:32:33.539 --> 00:32:38.536 First, we need to fill the objectPool when the objects are spawned 665 00:32:38.536 --> 00:32:46.360 Let's add the data to the objectPool below here 666 00:32:46.360 --> 00:32:51.010 For that, the objectPool size needs to be created in advance 667 00:32:51.010 --> 00:32:57.039 So, for the enemyObjectPool 668 00:32:57.039 --> 00:32:58.739 how many should we add in the new GameObject 669 00:32:58.739 --> 00:33:00.636 Let's first create an array 670 00:33:00.636 --> 00:33:03.318 with the size of the Pool Size 671 00:33:03.318 --> 00:33:05.693 Then, we need to repeatedly add 672 00:33:05.693 --> 00:33:08.522 one object at a time to the pool 673 00:33:08.522 --> 00:33:15.672 for(int i=0;〈poolSize;i++) 674 00:33:15.672 --> 00:33:17.479 Let's create it repeatedly 675 00:33:17.479 --> 00:33:24.020 GameObject enemy equals Instantiate 676 00:33:24.020 --> 00:33:25.822 What should be added here? 677 00:33:25.822 --> 00:33:27.272 enemyFactory 678 00:33:27.272 --> 00:33:29.872 Actually, you don't need to write this yourself 679 00:33:29.872 --> 00:33:33.653 as this content is already in the Update 680 00:33:33.653 --> 00:33:36.836 Take this whole thing and paste it like this 681 00:33:39.080 --> 00:33:44.280 Then, let's add one object at a time to the objectPool each time 682 00:33:44.280 --> 00:33:47.808 And what do we need to do? deactivate 683 00:33:47.808 --> 00:33:49.358 This should fill in there 684 00:33:49.358 --> 00:33:54.199 So in here, enemyObjectPool 685 00:33:54.199 --> 00:33:58.182 place enemy in i-th order 686 00:34:00.039 --> 00:34:01.960 Then, deactivate it 687 00:34:01.960 --> 00:34:09.360 Deactivate by using enemy,SetActive and false 688 00:34:09.360 --> 00:34:12.210 After saving 689 00:34:12.210 --> 00:34:14.199 Let's see of enemies actually spawn 690 00:34:14.199 --> 00:34:15.735 If you press play button 691 00:34:18.200 --> 00:34:19.972 Not only the bullets, but if you scroll down 692 00:34:19.972 --> 00:34:24.072 you will also see that 10 enemies 693 00:34:24.072 --> 00:34:25.079 are pre created 694 00:34:25.079 --> 00:34:26.168 Everything is disabled right? 695 00:34:28.737 --> 00:34:31.787 In this way, you can create enemies 696 00:34:31.787 --> 00:34:36.119 in the same way as bullets 697 00:34:36.119 --> 00:34:38.961 Next, to use it, how do we use it? 698 00:34:38.961 --> 00:34:42.369 Come down, and in the Update 699 00:34:42.369 --> 00:34:45.600 Instead of simply creating an enemy at a specific time 700 00:34:45.600 --> 00:34:46.650 what do we do now? 701 00:34:46.650 --> 00:34:49.650 we can take an enemy from the objectPool and use it when needed 702 00:34:49.650 --> 00:34:52.839 So, this part 703 00:34:52.839 --> 00:34:59.401 Take objects from ObjectPool to use 704 00:35:01.777 --> 00:35:03.927 What do we need to do first? 705 00:35:03.927 --> 00:35:06.227 We need to detect the ones that are deactivated 706 00:35:06.227 --> 00:35:13.947 So, for(int i=0;i〈poolSize;i++) 707 00:35:13.947 --> 00:35:18.297 When this is possible, we can create enemy 708 00:35:18.297 --> 00:35:22.920 Once you are done with this, make sure to move it up 709 00:35:22.920 --> 00:35:26.420 First, let's take the enemy 710 00:35:26.420 --> 00:35:30.119 and add it to gameObject 711 00:35:30.119 --> 00:35:35.839 Let me get the i-th element from enemyObjectPool like this 712 00:35:35.839 --> 00:35:38.539 This part is the same as Bullet 713 00:35:38.539 --> 00:35:43.650 Let me skip whatever we've covered before 714 00:35:43.650 --> 00:35:45.200 If it's deactivated 715 00:35:45.200 --> 00:35:48.274 we will be using only the ones 716 00:35:48.274 --> 00:35:50.079 that are deactivated in the if enemy 717 00:35:50.079 --> 00:35:53.279 enemy.activeSelf 718 00:35:53.279 --> 00:35:55.729 What is the value? When false 719 00:35:55.729 --> 00:35:59.040 it will be deactivate right away 720 00:35:59.040 --> 00:36:02.340 You can set up it's position first 721 00:36:02.340 --> 00:36:03.540 And what do we need to do for this one? 722 00:36:03.540 --> 00:36:05.640 simply just Activate it 723 00:36:05.640 --> 00:36:11.109 enemy.SetActive and true, all is good 724 00:36:11.109 --> 00:36:13.959 enemy will be activate as well 725 00:36:13.959 --> 00:36:16.059 Now that you've created one, what's the next step? 726 00:36:16.059 --> 00:36:17.909 We don't have to keep repeating, right? 727 00:36:17.909 --> 00:36:21.959 break and end the search 728 00:36:21.959 --> 00:36:24.609 By doing this, finish up the results 729 00:36:24.609 --> 00:36:26.509 and now Enemy will be utilizing 730 00:36:26.509 --> 00:36:28.320 the ObjectPool just like Bullet 731 00:36:28.320 --> 00:36:31.020 But, we haven't set up what happens when Enemy collides 732 00:36:31.020 --> 00:36:37.160 When OnCollisionEnter happens in Enemy.cs 733 00:36:37.160 --> 00:36:39.360 When OnCollisionEnter happens 734 00:36:39.360 --> 00:36:41.410 and the enemy is supposed to die 735 00:36:41.410 --> 00:36:43.040 what are we supposed to do? 736 00:36:43.040 --> 00:36:44.890 we should deactivate the enemy and return it 737 00:36:44.890 --> 00:36:47.600 to magazine or to the ObjectPool just like for Bullets 738 00:36:47.600 --> 00:36:49.800 Do not use Destroy gameObject 739 00:36:49.800 --> 00:36:57.586 How? return it to ObjectPool 740 00:36:57.586 --> 00:36:58.936 How do we handle this? 741 00:36:58.936 --> 00:37:03.286 gameObject.SetActive and false 742 00:37:03.286 --> 00:37:05.399 this way it will work fine 743 00:37:05.399 --> 00:37:09.099 we have to consider one more thing, it is the DestroyZone 744 00:37:09.099 --> 00:37:11.499 If it's a bullet, we can do it this way 745 00:37:11.499 --> 00:37:14.576 but if it's not, we destroy it 746 00:37:14.576 --> 00:37:17.526 This part shouldn't be written like this 747 00:37:17.526 --> 00:37:20.126 For Bullet or Enemy 748 00:37:20.126 --> 00:37:22.640 For both Bullet and Enemy, they need to be deactivated 749 00:37:22.640 --> 00:37:25.290 So, add or in this part 750 00:37:25.290 --> 00:37:28.600 I will copy and paste the code above here 751 00:37:28.600 --> 00:37:31.020 Name for this 752 00:37:31.020 --> 00:37:33.470 when the name contains Enemy 753 00:37:33.470 --> 00:37:35.279 then it means this is Enemy 754 00:37:35.279 --> 00:37:39.379 If it's a bullet or an enemy 755 00:37:39.379 --> 00:37:41.359 we will deactivate it 756 00:37:41.359 --> 00:37:45.963 we can add this logic to the DestroyZone 757 00:37:45.963 --> 00:37:48.480 Let's save it and see what we've got 758 00:37:48.480 --> 00:37:49.466 hit Play button 759 00:38:00.480 --> 00:38:03.280 Doesn't the enemy seem to spin around 760 00:38:03.280 --> 00:38:04.600 or come in an odd way here? 761 00:38:04.600 --> 00:38:09.839 So, select the Enemy in the Prefabs folder 762 00:38:09.839 --> 00:38:13.880 Let's open the Rigidbody section like this 763 00:38:13.880 --> 00:38:17.839 In the Rigidbody, you'll see a section called Constraints 764 00:38:17.839 --> 00:38:20.079 Here, you'll see that everything is set to Freeze 765 00:38:20.079 --> 00:38:23.229 The Freeze on Position and Rotation in the Rigidbody means 766 00:38:23.229 --> 00:38:26.200 that it prevents the object from being affected by physics 767 00:38:26.200 --> 00:38:28.030 Let's play again 768 00:38:39.428 --> 00:38:42.760 We can see that enemies generate normally 769 00:38:42.760 --> 00:38:46.010 Next, for position 770 00:38:46.010 --> 00:38:48.479 Since enemy is being generated only from this one position 771 00:38:48.479 --> 00:38:50.479 So, let's modify to have enemies created 772 00:38:50.479 --> 00:38:52.760 from the SpawnPoints 773 00:38:52.760 --> 00:38:55.810 When creating this at EnemyManager 774 00:38:55.810 --> 00:38:57.919 It is currently set to its own position 775 00:38:57.919 --> 00:39:00.623 But what do we do now? 776 00:39:00.623 --> 00:39:05.799 Let's have enemies come out from SpawnPoints 777 00:39:05.799 --> 00:39:09.130 We will set it randomly 778 00:39:09.130 --> 00:39:11.400 So, let's pick a random index 779 00:39:11.400 --> 00:39:14.550 Pick a random index with int index and then where? 780 00:39:14.550 --> 00:39:18.719 Random.Range 781 00:39:18.719 --> 00:39:25.519 from 0, spawnPoint size and length 782 00:39:25.519 --> 00:39:27.280 If we set up like this, what happens? 783 00:39:27.280 --> 00:39:32.520 From here, it will pick the corresponding value, up to -1 784 00:39:32.520 --> 00:39:34.599 Because arrays start from 0 785 00:39:34.599 --> 00:39:37.999 so bring our attention here 786 00:39:37.999 --> 00:39:40.610 instead of using the transform's position, who? 787 00:39:40.610 --> 00:39:46.352 index-th which is at spawnPoints 788 00:39:46.352 --> 00:39:47.880 We’re saying let’s take the position 789 00:39:47.880 --> 00:39:51.599 from the one we randomly selected and use it 790 00:39:51.599 --> 00:39:55.795 Now it will spawn between these spawn points 791 00:40:01.455 --> 00:40:04.822 We can see it randomly spawning from various places 792 00:40:04.822 --> 00:40:06.972 If you think it's coming out too slowly 793 00:40:06.972 --> 00:40:08.920 In this case, in EnemyManager 794 00:40:08.920 --> 00:40:12.440 the minTime and maxTime are not public 795 00:40:12.440 --> 00:40:15.320 So if you change it to public 796 00:40:15.320 --> 00:40:17.960 it will be exposed in the editor 797 00:40:17.960 --> 00:40:21.280 Save it, and let's see 798 00:40:21.280 --> 00:40:23.230 It would be good if you could adjust 799 00:40:23.230 --> 00:40:26.000 the Min Time and Max Time appropriately 800 00:40:26.000 --> 00:40:31.520 If we set it between 0.2 to 1 second, or between 2 seconds 801 00:40:31.520 --> 00:40:34.719 it could spawn very frequently in short intervals 802 00:40:39.874 --> 00:40:42.200 By making these modifications 803 00:40:42.200 --> 00:40:45.300 you will have learned how to use the enemy 804 00:40:45.300 --> 00:40:46.959 objectPool 805 00:40:46.959 --> 00:40:50.309 Now, let's look at the issues 806 00:40:50.309 --> 00:40:51.959 with using an array in this case 807 00:40:51.959 --> 00:40:53.559 Right now, the array is set to 10 elements 808 00:40:53.559 --> 00:40:55.360 but if we had 10,000 809 00:40:55.360 --> 00:40:57.599 for example, and we had to detect 810 00:40:57.599 --> 00:41:00.160 the 10,000th element in a for loop 811 00:41:00.160 --> 00:41:02.160 we would have the problem 812 00:41:02.160 --> 00:41:04.260 of the loop running 10,000 times every frame 813 00:41:04.260 --> 00:41:06.279 This kind of problem can occur 814 00:41:06.279 --> 00:41:07.560 when simply detecting the element 815 00:41:07.560 --> 00:41:11.480 So, when using an array, the detection time can become long 816 00:41:11.480 --> 00:41:14.280 and this could result in a situation where not using 817 00:41:14.280 --> 00:41:16.639 an objectPool is actually better 818 00:41:16.639 --> 00:41:19.239 This time, by using a List 819 00:41:19.239 --> 00:41:23.400 Let's improve the objectPool's search speed 820 00:41:23.400 --> 00:41:26.239 In an array, data is written in order 821 00:41:26.239 --> 00:41:30.480 but in the case of a List, the data is stored here 822 00:41:30.480 --> 00:41:33.480 and then in the below, there's an address 823 00:41:33.480 --> 00:41:37.430 It's not written in order 824 00:41:37.430 --> 00:41:38.599 in the memory space like an array 825 00:41:38.599 --> 00:41:41.599 instead, the data scattered across different locations in memory 826 00:41:41.599 --> 00:41:45.120 So, who does this data point to? 827 00:41:45.120 --> 00:41:48.236 You can point to it like this, using its address 828 00:41:48.236 --> 00:41:50.945 And it can point to its address like this 829 00:41:53.539 --> 00:41:57.440 This is what you can consider the structure of a List 830 00:41:57.440 --> 00:41:59.360 If you want to remove it 831 00:41:59.360 --> 00:42:00.559 then how? 832 00:42:00.559 --> 00:42:03.209 If we remove this, we can just cut this List 833 00:42:03.209 --> 00:42:05.879 and switch the reference address 834 00:42:05.879 --> 00:42:09.400 And if you want to add it, you can simply add it like this 835 00:42:09.400 --> 00:42:14.279 So, the List makes adding and removing data very convenient 836 00:42:14.279 --> 00:42:18.320 So, by adding only the deactivated ones to the List 837 00:42:18.320 --> 00:42:21.639 when they are activated, we can remove them 838 00:42:21.639 --> 00:42:25.679 By constantly taking the first item, deleting it, and doing this 839 00:42:25.679 --> 00:42:28.240 the remaining items will stay in the List 840 00:42:28.240 --> 00:42:30.759 So, we only bring in and use the ones that are deactivated 841 00:42:30.759 --> 00:42:34.720 Then, after using them, add the ones that are finished to the back 842 00:42:34.720 --> 00:42:37.679 and this way, we can work very efficiently 843 00:42:37.679 --> 00:42:39.919 Even if there are 10,000 items like in a for loop 844 00:42:39.919 --> 00:42:42.000 we can create a structure that allows us to retrieve them 845 00:42:42.000 --> 00:42:43.880 through a search in a single step 846 00:42:43.880 --> 00:42:46.080 So, now we will change this part 847 00:42:46.080 --> 00:42:48.720 where we are using 848 00:42:48.720 --> 00:42:51.880 what are we going to do? change an array to a List 849 00:42:51.880 --> 00:42:54.480 So, instead of using an array 850 00:42:54.480 --> 00:42:58.479 let's change it to public List and GameObject 851 00:42:58.479 --> 00:43:02.479 and switch the array to a List 852 00:43:02.479 --> 00:43:05.600 Let's first change the bullet, not the enemy 853 00:43:05.600 --> 00:43:15.399 In PlayerFire, set it as a public List 854 00:43:15.399 --> 00:43:17.919 and then we’ve created it using a List 855 00:43:17.919 --> 00:43:21.151 So, instead of being limited to the array size 856 00:43:21.151 --> 00:43:26.279 we can create it using equal sign and new 857 00:43:26.279 --> 00:43:29.240 Now we've created the List object 858 00:43:29.240 --> 00:43:33.039 From now on, instead of specifying 859 00:43:33.039 --> 00:43:34.279 the index to insert it 860 00:43:34.279 --> 00:43:36.399 you can simply add it here 861 00:43:36.399 --> 00:43:40.899 By using the .add function with the List 862 00:43:40.899 --> 00:43:44.119 when you add the Bullet 863 00:43:44.119 --> 00:43:47.240 it will be inserted at the end of the List 864 00:43:47.240 --> 00:43:49.559 continuously adding it to the back 865 00:43:49.559 --> 00:43:50.809 You can structure it exactly like 866 00:43:50.809 --> 00:43:52.720 an array by using a List in this way 867 00:43:52.720 --> 00:43:56.440 The way you use it and retrieve items is the same as with an array 868 00:43:56.440 --> 00:43:59.000 How? You can retrieve it like this 869 00:43:59.000 --> 00:44:02.199 However, if until now you had to detect 870 00:44:02.199 --> 00:44:07.399 and find deactivated objects every time the fire button was pressed 871 00:44:07.399 --> 00:44:09.520 here you will make sure to only store what? 872 00:44:09.520 --> 00:44:12.759 Only store deactivated objects 873 00:44:12.759 --> 00:44:15.399 Already, here, the deactivated objects have been set up 874 00:44:15.399 --> 00:44:18.080 So, you only need to retrieve the first one here 875 00:44:18.080 --> 00:44:20.399 However, if the magazine is empty and there are no bullets left 876 00:44:20.399 --> 00:44:21.399 then that won't work 877 00:44:21.399 --> 00:44:26.880 So, how do we handle this part? It should be done like this 878 00:44:26.880 --> 00:44:31.735 If there are bullets in the magazine 879 00:44:31.735 --> 00:44:36.880 let's take the first bullet from it 880 00:44:36.880 --> 00:44:39.279 This way, it will work 881 00:44:39.279 --> 00:44:42.329 Why? Because this magazine will only contain 882 00:44:42.329 --> 00:44:44.119 deactivated objects 883 00:44:44.119 --> 00:44:46.931 So if you look at if there are Bullets in the magazine 884 00:44:46.931 --> 00:44:51.331 look at, if, bulletObjectPool 885 00:44:51.331 --> 00:44:52.809 We can use a function called Count 886 00:44:52.809 --> 00:44:54.659 This uses the size of the List 887 00:44:54.659 --> 00:44:56.600 to get how many are currently present 888 00:44:56.600 --> 00:44:58.959 If there are any, it would be if the size is greater than 0 889 00:44:58.959 --> 00:45:01.320 Since there are always items 890 00:45:01.320 --> 00:45:06.480 At that point, instead of using a for loop 891 00:45:06.480 --> 00:45:08.720 we can change it to an if statement 892 00:45:08.720 --> 00:45:09.640 We don't need break here 893 00:45:09.640 --> 00:45:12.119 Since we're only retrieving one 894 00:45:12.119 --> 00:45:16.959 instead of using i, we just need to get the 0th element 895 00:45:16.959 --> 00:45:19.959 And there’s no need to detect deactivated bullets 896 00:45:19.959 --> 00:45:24.440 Since only deactivated bullets will be placed here anyway 897 00:45:24.440 --> 00:45:29.480 So, I will move this part up like this 898 00:45:29.480 --> 00:45:33.279 And I will remove the part where detection is done as well 899 00:45:33.279 --> 00:45:35.480 Then things get really simple 900 00:45:35.480 --> 00:45:38.279 After retrieving the bullet and activating it 901 00:45:38.279 --> 00:45:42.600 you need to remove that bullet from the list 902 00:45:42.600 --> 00:45:51.279 Once it's activated, you can remove it from the bulletObjectPool by using Remove function 903 00:45:51.279 --> 00:45:55.440 Who? Remove the bullet 904 00:45:55.440 --> 00:45:58.359 Then, that removes the bullet from the list 905 00:45:58.359 --> 00:46:00.440 Why? Because it's been activated 906 00:46:00.440 --> 00:46:03.390 It can no longer be added to the pool 907 00:46:03.390 --> 00:46:04.959 which only contains deactivated objects 908 00:46:04.959 --> 00:46:07.760 That's why we remove it 909 00:46:07.760 --> 00:46:10.160 Now, let's check it out 910 00:46:10.160 --> 00:46:12.720 after writing it this way 911 00:46:12.720 --> 00:46:17.297 Press the play button, and it should be deactivated in the same way 912 00:46:19.119 --> 00:46:21.239 I fired a bullet 913 00:46:21.239 --> 00:46:27.320 However, if you look now, all the deactivated bullets 914 00:46:27.320 --> 00:46:28.920 have disappeared 915 00:46:28.920 --> 00:46:31.519 but if one is deactivated, it should be activated 916 00:46:31.519 --> 00:46:33.279 yet there are cases where that doesn't happen 917 00:46:33.279 --> 00:46:36.760 What’s happening is that when the enemy collides with the bullet 918 00:46:36.760 --> 00:46:39.359 it should be put back into the magazine 919 00:46:39.359 --> 00:46:41.359 but right now 920 00:46:41.359 --> 00:46:43.687 all we're doing is deactivating it 921 00:46:43.687 --> 00:46:48.279 So, we need to add the bullet back into the magazine 922 00:46:48.279 --> 00:46:52.799 Add it back into the magazine, this step is necessary 923 00:46:52.799 --> 00:46:53.920 In case of Bullet 924 00:46:53.920 --> 00:46:56.239 So, where is this magazine? 925 00:46:56.239 --> 00:46:57.640 It's in PlayerFire 926 00:46:57.640 --> 00:47:01.760 This is a component attached to Player 927 00:47:01.760 --> 00:47:05.239 So this PlayerFire is 928 00:47:05.239 --> 00:47:06.880 I would put it as Player 929 00:47:06.880 --> 00:47:09.799 We can use GameObject.Find 930 00:47:09.799 --> 00:47:12.920 to find the Player in the world 931 00:47:12.920 --> 00:47:15.519 Among the components attached to it, which one? 932 00:47:15.519 --> 00:47:16.839 PlayerFire 933 00:47:16.839 --> 00:47:19.320 This is what we are looking for 934 00:47:19.320 --> 00:47:23.399 Who should we get it from, attached to it? 935 00:47:23.399 --> 00:47:27.040 You can use Add on bulletObjectPool 936 00:47:27.040 --> 00:47:28.320 to add the bullet 937 00:47:28.320 --> 00:47:30.200 Now, you can add this bullet 938 00:47:30.200 --> 00:47:35.359 By simply inserting the gameObject into other 939 00:47:35.359 --> 00:47:36.640 since it is deactivated 940 00:47:36.640 --> 00:47:39.880 this will complete the task of putting it back into the magazine 941 00:47:39.880 --> 00:47:42.399 save it now 942 00:47:42.399 --> 00:47:45.399 he same issue would occur when the bullet collides 943 00:47:45.399 --> 00:47:47.600 with the DestroyZone 944 00:47:47.600 --> 00:47:50.519 You can press Ctrl and C 945 00:47:50.519 --> 00:47:53.519 and then add it to the DestroyZone as well 946 00:47:53.519 --> 00:47:56.040 in the OnTriggerEnter of the DestroyZone 947 00:47:56.040 --> 00:47:58.440 you perform these actions 948 00:47:58.440 --> 00:47:59.359 when it's a Bullet or an Enemy 949 00:47:59.359 --> 00:48:01.559 It seems like there’s a need to separate 950 00:48:01.559 --> 00:48:02.920 and handle these tasks 951 00:48:02.920 --> 00:48:08.559 So I would close this OR part 952 00:48:08.559 --> 00:48:13.052 After placing it like this, using else 953 00:48:13.052 --> 00:48:19.000 or else if to modify it again 954 00:48:19.000 --> 00:48:22.079 For the bullet case, we can do it like this 955 00:48:22.079 --> 00:48:25.760 Since deactivating them is the same for both 956 00:48:25.760 --> 00:48:28.200 let's handle it like this 957 00:48:28.200 --> 00:48:31.079 For the enemy case, we haven't handled it yet 958 00:48:31.079 --> 00:48:34.029 For the bullet case, this task of reassigning it 959 00:48:34.029 --> 00:48:35.799 to the player is necessary 960 00:48:35.799 --> 00:48:37.320 Now, save 961 00:48:37.320 --> 00:48:40.440 In the Enemy, this part of adding it to the magazine 962 00:48:40.440 --> 00:48:42.159 In the DestroyZone, the part 963 00:48:42.159 --> 00:48:43.760 where we currently add to the magazine 964 00:48:43.760 --> 00:48:45.119 is handled like this 965 00:48:45.119 --> 00:48:49.104 Save the changes, and then go ahead and test it again 966 00:49:03.170 --> 00:49:05.559 It seems like the part is working correctly now 967 00:49:05.559 --> 00:49:07.559 But we have a problem here 968 00:49:07.559 --> 00:49:10.760 If you click on it, what issues do you see? 969 00:49:10.760 --> 00:49:12.919 It says we have an error, here 970 00:49:12.919 --> 00:49:14.919 It seems like the error 971 00:49:14.919 --> 00:49:17.880 we are encountering is a null reference error 972 00:49:17.880 --> 00:49:19.440 what is a null? 973 00:49:19.440 --> 00:49:21.080 In here, what null is 974 00:49:21.080 --> 00:49:24.159 This happens when you're trying to retrieve a value from ones that don't exist 975 00:49:24.159 --> 00:49:25.919 Exactly, since the player has died 976 00:49:25.919 --> 00:49:27.320 after colliding with the enemy 977 00:49:27.320 --> 00:49:29.159 But it is already dead 978 00:49:29.159 --> 00:49:30.719 but trying to access the PlayerFire component 979 00:49:30.719 --> 00:49:33.880 We cannot retrieve the component of an already dead object 980 00:49:33.880 --> 00:49:34.760 Nope 981 00:49:34.760 --> 00:49:37.660 So, this part needs to be handled 982 00:49:37.660 --> 00:49:40.760 by detecting it beforehand 983 00:49:40.760 --> 00:49:43.719 Sure, let's try modifying the code here a bit 984 00:49:43.719 --> 00:49:48.840 Let's first create a GameObject and add it here 985 00:49:48.840 --> 00:49:52.719 Let's name it "player" and proceed 986 00:49:52.719 --> 00:49:54.559 Position it like this 987 00:49:54.559 --> 00:49:57.479 Let's change the name of the object here to pf 988 00:49:57.479 --> 00:49:59.440 Since it's PlayerFire 989 00:49:59.440 --> 00:50:02.640 Let's change it like this 990 00:50:02.640 --> 00:50:07.440 Now, retrieve the component from this player object 991 00:50:07.440 --> 00:50:09.919 this is what we are going to have 992 00:50:09.919 --> 00:50:11.359 Found the Player now 993 00:50:11.359 --> 00:50:13.799 Then, retrieve the PlayerFire component from the player 994 00:50:13.799 --> 00:50:15.359 Yes, isn't this the same issue? 995 00:50:15.359 --> 00:50:20.640 But here, if the player exists 996 00:50:20.640 --> 00:50:23.440 we can add a check to detect it like this 997 00:50:23.440 --> 00:50:26.817 You can handle it like this 998 00:50:29.520 --> 00:50:32.919 so that the code inside the 999 00:50:32.919 --> 00:50:35.359 if block only runs when the player exists 1000 00:50:35.359 --> 00:50:38.559 Only to be handled when the player exists 1001 00:50:38.559 --> 00:50:41.520 the same issue would occur with the enemy as well 1002 00:50:41.520 --> 00:50:43.970 Let's take, add Bullet into the magazine 1003 00:50:43.970 --> 00:50:45.400 Ctrl and C 1004 00:50:45.400 --> 00:50:48.880 Just like Player, when Enemy dies 1005 00:50:48.880 --> 00:50:50.679 we are not supposed to handle this 1006 00:50:50.679 --> 00:50:52.644 add Bullet into the magazine, this part 1007 00:50:52.644 --> 00:50:54.559 change it like this 1008 00:50:54.559 --> 00:50:57.000 Save it and then run test again 1009 00:50:57.000 --> 00:50:59.799 Now, we should be able to see that the issue has been resolved 1010 00:51:07.799 --> 00:51:10.000 We don't get the error message at all 1011 00:51:10.000 --> 00:51:12.146 So like this 1012 00:51:12.146 --> 00:51:15.599 We've tried changing the objectPool to use a List 1013 00:51:15.599 --> 00:51:18.599 The same work can be done for the enemy as well 1014 00:51:18.599 --> 00:51:22.903 In EnemyManager, you can change it like this 1015 00:51:22.903 --> 00:51:24.640 and switch it to a List 1016 00:51:24.640 --> 00:51:30.090 Then, you can simply use new 1017 00:51:30.090 --> 00:51:33.200 and add it like this 1018 00:51:33.200 --> 00:51:35.400 Next, instead of directly 1019 00:51:35.400 --> 00:51:36.799 assigning the enemy with equal sign 1020 00:51:36.799 --> 00:51:39.599 and use Add function 1021 00:51:39.599 --> 00:51:42.599 change it to add the enemy in the form of an addition 1022 00:51:42.599 --> 00:51:45.880 It's exactly the same as adding the bullet 1023 00:51:45.880 --> 00:51:49.280 Then, move down and update it so that after a certain amount of time 1024 00:51:49.280 --> 00:51:51.239 we have the process of detecting 1025 00:51:51.239 --> 00:51:56.389 So, when it's in the magazine or objectPool 1026 00:51:56.389 --> 00:52:01.378 objectPool 1027 00:52:01.378 --> 00:52:08.078 use if and enemyObjectPool.Count 1028 00:52:08.078 --> 00:52:09.880 What do we want to do? 1029 00:52:09.880 --> 00:52:12.880 Instead of using a for loop 1030 00:52:12.880 --> 00:52:16.200 we just retrieve the 0th element 1031 00:52:16.200 --> 00:52:19.119 and is there any need to check if it's deactivated? 1032 00:52:19.119 --> 00:52:23.159 No, therefore move it outside of the if statement and remove the if block 1033 00:52:23.159 --> 00:52:28.559 you can remove the if statement like this 1034 00:52:28.559 --> 00:52:32.479 And finally, you should remove 1035 00:52:32.479 --> 00:52:36.320 the enemy from the enemy objectPool 1036 00:52:36.320 --> 00:52:40.960 So, use enemyObjectPool.Remove 1037 00:52:40.960 --> 00:52:43.660 to remove Who? the enemy 1038 00:52:43.660 --> 00:52:47.280 from the objectPool like this 1039 00:52:47.280 --> 00:52:52.200 Great! Now, when it collides 1040 00:52:52.200 --> 00:52:54.352 When the enemy dies, what happens? 1041 00:52:54.352 --> 00:52:57.479 we need to add it back to the objectPool in the same way 1042 00:52:57.479 --> 00:53:01.679 Enemies can't collide with each other 1043 00:53:01.679 --> 00:53:05.359 so this part needs to be handled accordingly 1044 00:53:05.359 --> 00:53:09.039 this should only be handled in the DestroyZone 1045 00:53:09.039 --> 00:53:12.200 At this point, the enemy will be deactivated 1046 00:53:12.200 --> 00:53:14.320 but where is it in the objectPool? 1047 00:53:14.320 --> 00:53:15.520 It's in the EnemyManager 1048 00:53:15.520 --> 00:53:18.400 If you add it to the EnemyManager 1049 00:53:18.400 --> 00:53:21.880 it will make the process easier to manage 1050 00:53:21.880 --> 00:53:26.000 if you make it a singleton design pattern, it will be easier to manage and access 1051 00:53:26.000 --> 00:53:28.359 I will just let you guys figure that part out 1052 00:53:28.359 --> 00:53:31.159 We will take the content here and 1053 00:53:31.159 --> 00:53:35.159 use it by simply changing the name 1054 00:53:35.159 --> 00:53:36.880 Deactivate 1055 00:53:36.880 --> 00:53:41.400 This time, instead of the magazine, what instead? 1056 00:53:41.400 --> 00:53:45.479 Enemy, enemyObjectPool 1057 00:53:45.479 --> 00:53:47.559 This time, we are looking for whom? 1058 00:53:47.559 --> 00:53:50.080 we need to find EnemyManager 1059 00:53:50.080 --> 00:53:53.159 The one in the EnemyManager 1060 00:53:53.159 --> 00:53:55.000 let's put it as em 1061 00:53:55.000 --> 00:53:59.960 Since it's EnemyManger, right? 1062 00:53:59.960 --> 00:54:06.239 Who do we need to get inside EnemyManager? 1063 00:54:06.239 --> 00:54:09.799 You need to retrieve the EnemyManager class 1064 00:54:09.799 --> 00:54:11.840 this component 1065 00:54:11.840 --> 00:54:14.960 get EnemyManager component 1066 00:54:14.960 --> 00:54:17.880 We can keep the variable as pf as it is 1067 00:54:17.880 --> 00:54:21.000 This would now be which, not bulletObjectPool? 1068 00:54:21.000 --> 00:54:25.960 enemyObjectPool 1069 00:54:25.960 --> 00:54:30.892 If it’s a bit confusing, you can refer to it as manager 1070 00:54:30.892 --> 00:54:32.440 Great 1071 00:54:32.440 --> 00:54:33.760 We just changed the name here 1072 00:54:33.760 --> 00:54:35.320 It’s exactly the same as the upper part 1073 00:54:35.320 --> 00:54:38.280 By simply changing the name, get GameObject 1074 00:54:38.280 --> 00:54:39.680 then get the EnemyManager component 1075 00:54:39.680 --> 00:54:41.799 attached to that GameObject 1076 00:54:41.799 --> 00:54:43.599 Afterward, we access the objectPool attached to it 1077 00:54:43.599 --> 00:54:46.191 and complete the task in this way 1078 00:54:48.963 --> 00:54:51.400 So, we've learned how to retrieve 1079 00:54:51.400 --> 00:54:53.719 deactivate, and add it back to the enemy objectPool 1080 00:54:53.719 --> 00:54:57.190 completing the entire process 1081 00:54:57.190 --> 00:54:59.808 Let's save and find out if it works 1082 00:55:25.039 --> 00:55:30.359 Now, you can see that the enemies are coming in like this 1083 00:55:30.359 --> 00:55:32.320 then it stops coming in 1084 00:55:32.320 --> 00:55:33.479 we've got ourselves a problem here 1085 00:55:33.479 --> 00:55:36.880 Let’s take a look at what issues might be present 1086 00:55:36.880 --> 00:55:39.320 When the EnemyManager is created 1087 00:55:39.320 --> 00:55:43.200 In the DestroyZone 1088 00:55:43.200 --> 00:55:46.400 when the enemy collides with it 1089 00:55:46.400 --> 00:55:48.520 it's correctly added back into the objectPool 1090 00:55:48.520 --> 00:55:54.320 When the enemy collides with a bullet or the player 1091 00:55:54.320 --> 00:55:56.320 is there a part where it's added back to the objectPool? 1092 00:55:56.320 --> 00:56:00.440 We have none, when the bullet hits the enemy 1093 00:56:00.440 --> 00:56:02.400 there's currently no possibility for that enemy to be recreated 1094 00:56:02.400 --> 00:56:03.880 or added back to the objectPool 1095 00:56:03.880 --> 00:56:07.400 because the enemy isn't being added back to the objectPool 1096 00:56:07.400 --> 00:56:09.919 So, this part in the DestroyZone 1097 00:56:09.919 --> 00:56:13.039 if it collided with a Bullet 1098 00:56:13.039 --> 00:56:15.640 for the enemy when it collides with a bullet 1099 00:56:15.640 --> 00:56:19.919 it's just deactivating enemy only 1100 00:56:19.919 --> 00:56:24.080 but what about me? what am I doing? 1101 00:56:24.080 --> 00:56:26.760 It's simply being deactivated 1102 00:56:26.760 --> 00:56:28.599 where should I add into? 1103 00:56:28.599 --> 00:56:32.080 it should be returned to the objectPool 1104 00:56:32.080 --> 00:56:34.080 So, let's take this part and place it 1105 00:56:34.080 --> 00:56:36.630 in the corresponding section of 1106 00:56:36.630 --> 00:56:38.200 Enemy.cs from DestroyZone 1107 00:56:38.200 --> 00:56:41.599 For the deactivation part, let's add it back to the objectPool 1108 00:56:41.599 --> 00:56:45.599 Ctrl and C this part 1109 00:56:45.599 --> 00:56:48.799 In Enemy.cs, after SetActive false, go ahead 1110 00:56:48.799 --> 00:56:50.799 and press Ctrl+V to paste it there 1111 00:56:50.799 --> 00:56:52.400 What happens? 1112 00:56:52.400 --> 00:56:55.440 after deactivating it, you need to bring the EnemyManager back 1113 00:56:55.440 --> 00:56:58.640 and reassign it, all the way through this process 1114 00:56:58.640 --> 00:57:00.000 worked right? 1115 00:57:00.000 --> 00:57:02.799 In the OnCollisionEnter section of the Enemy 1116 00:57:02.799 --> 00:57:06.440 the enemy itself is not currently being added back 1117 00:57:06.440 --> 00:57:08.159 to the objectPool at the end 1118 00:57:08.159 --> 00:57:11.160 So, you can add that part here to ensure the enemy is added back 1119 00:57:11.160 --> 00:57:13.330 Save and go play 1120 00:57:16.359 --> 00:57:18.076 before pressing play, for testing 1121 00:57:18.076 --> 00:57:20.976 You can try setting the objectPool size 1122 00:57:20.976 --> 00:57:22.920 to just 3 for now 1123 00:57:22.920 --> 00:57:24.814 When you play 1124 00:57:27.239 --> 00:57:29.880 the objectPool will contain 3 objects 1125 00:57:29.880 --> 00:57:33.479 What happens if I shoot once 1126 00:57:33.479 --> 00:57:34.252 Now 1127 00:57:37.885 --> 00:57:40.319 It seems that in the objectPool 1128 00:57:40.319 --> 00:57:42.319 other objects besides the enemy are 1129 00:57:42.319 --> 00:57:44.040 being added to the enemy objectPool 1130 00:57:44.040 --> 00:57:47.800 If you look, Bullet is added 1131 00:57:47.800 --> 00:57:50.884 We see that bullets are being added to the objectPool as well 1132 00:57:53.280 --> 00:57:54.400 Why is this happening? 1133 00:57:54.400 --> 00:57:57.119 If you take a look at code, we did something wrong 1134 00:57:57.119 --> 00:57:59.239 It looks like this happened because of a simple copy paste 1135 00:57:59.239 --> 00:58:02.160 Which do we need to return the enemy to the objectPool? 1136 00:58:02.160 --> 00:58:03.880 Instead of adding the object that collided with 1137 00:58:03.880 --> 00:58:06.830 it should add myself back to the objectPool 1138 00:58:06.830 --> 00:58:08.640 by only adding myself 1139 00:58:08.640 --> 00:58:14.009 since it's the enemy, you need to add the enemy back into the enemyObjectPool 1140 00:58:14.009 --> 00:58:15.520 We should add its own GameObject 1141 00:58:15.520 --> 00:58:19.195 not the GameObject of Other 1142 00:58:19.195 --> 00:58:22.119 Let's save it and check again 1143 00:58:22.119 --> 00:58:24.119 Play 1144 00:58:24.119 --> 00:58:25.319 All the enemies are inside now 1145 00:58:25.319 --> 00:58:26.520 Bang! 1146 00:58:26.520 --> 00:58:27.460 Now 1147 00:58:30.839 --> 00:58:32.590 Enemy comes out 1148 00:58:34.560 --> 00:58:36.880 And we see Enemy gets added back into the pool 1149 00:58:36.880 --> 00:58:38.880 We can see how it works 1150 00:58:38.880 --> 00:58:41.040 If we increase the objectPool size to 10 1151 00:58:41.040 --> 00:58:43.005 10 objects will be added at once 1152 00:58:47.199 --> 00:58:50.719 As enemies appear on the screen, the pool will gradually decrease 1153 00:58:50.719 --> 00:58:53.839 there are 8 objects in the pool, and since 2 have been used, only 8 remain available 1154 00:58:53.839 --> 00:58:56.289 So, we have learned how to implement 1155 00:58:56.289 --> 00:58:58.160 the work up to the beta version 1156 00:58:58.160 --> 00:59:01.599 I will summarize the content learned from this chapter 1157 00:59:01.599 --> 00:59:04.399 First, we learned how to create a manager 1158 00:59:04.399 --> 00:59:06.920 using the Singleton design pattern 1159 00:59:06.920 --> 00:59:08.920 We understood the Singleton design pattern 1160 00:59:08.920 --> 00:59:10.520 and learned how to implement 1161 00:59:10.520 --> 00:59:12.670 Score Manager as a Singleton object 1162 00:59:12.670 --> 00:59:15.680 using the static keyword 1163 00:59:15.680 --> 00:59:17.730 Then, using the Singleton object 1164 00:59:17.730 --> 00:59:20.319 modified the code to set the score 1165 00:59:20.319 --> 00:59:23.199 We learned how to improve code readability 1166 00:59:23.199 --> 00:59:27.199 by using the Get/Set properties in C# 1167 00:59:27.199 --> 00:59:32.319 Next, we learned about memory management using the objectPool 1168 00:59:32.319 --> 00:59:35.400 First, we implemented an objectPool using an array 1169 00:59:35.400 --> 00:59:37.599 and explored its drawbacks 1170 00:59:37.599 --> 00:59:39.400 Then, we improved the objectPool by using 1171 00:59:39.400 --> 00:59:44.439 a list data structure to enhance the search speed 1172 00:59:44.439 --> 00:59:47.339 We implemented this objectPool 1173 00:59:47.339 --> 00:59:50.760 for the creation of bullets and enemies 1174 00:59:50.760 --> 00:59:52.738 Great job so far! 1175 00:59:53.161 --> 00:59:54.051 Creating a manager using the Singleton design pattern The Singleton design pattern A method of registering and using only one object instance as static 1176 00:59:54.051 --> 00:59:54.911 Since ScoreManager is the only manager that handles the score, it is created as a Singleton object for use 1177 00:59:54.911 --> 00:59:55.661 I moved to the Enemy.cs script and changed it to access the Instance member of ScoreManager 1178 00:59:55.661 --> 00:59:56.552 Get, Set Property Create a Get and Set property named Score in ScoreManager 1179 00:59:56.552 --> 00:59:57.361 Copy the implementation of the GetScore function into the getter of Score Copy the implementation of the SetScore function into the setter of Score 1180 00:59:57.361 --> 00:59:58.156 Remove the GetScore and SetScore functions Move to the Enemy script and change the score modification code to use the Get/Set property 1181 00:59:58.156 --> 00:59:59.169 Memory management using an objectPool Creating a bullet objectPool Add an objectPool size property and an array for the objectPool in PlayerFire.cs 1182 00:59:59.169 --> 01:00:00.291 Implementation order Create a magazine with a size to hold bull Repeat bullet creation Create bullets Add bullets into ObjectPool 1183 01:00:00.291 --> 01:00:01.244 Create the bulletObjectPool array with the size of the pool Since it requires repetitive actions, implement it using a for loop in C# 1184 01:00:01.244 --> 01:00:02.270 Modify the bullet creation code in the Update function of PlayerFire to use Deactivate the used bullet instead of removing it and return it to the mag 1185 01:00:02.270 --> 01:00:03.235 Add the same code to DestroyZone.cs as well 1186 01:00:03.235 --> 01:00:04.285 Creating an objectPool for enemies Creating SpawnPoint Select the EnemyManager game object and press Ctrl and D to duplicate it 1187 01:00:04.285 --> 01:00:05.335 Exclude EnemyManager and rename duplicates to SpawnPoint Remove the EnemyManager component from all SpawnPoint objects 1188 01:00:05.335 --> 01:00:06.326 Declare a SpawnPoint array to remember the positions enemies will spawn Create an objectPool with a size capable of holding enemies, and use a loop 1189 01:00:06.326 --> 01:00:07.285 Modify the Update function to use the objectPool and find any deactivated Enemy to activate it Modify Enemy.cs to deactivate the Enemy 1190 01:00:07.285 --> 01:00:08.080 Add a condition in DestroyZone to deactivate the Enemy Move to EnemyManager.cs and assign the generated enemy's position to the SpawnPoint location 1191 01:00:08.080 --> 01:00:08.872 Create an objectPool using a list Replace the bullet objectPool with a list Change the data type of the PlayerFire.cs object pool to List 1192 01:00:08.872 --> 01:00:09.573 Modify the Start and Update functions to use a List Insert the bullet into the objectPool in DestroyZone.cs when it's a bullet 1193 01:00:09.573 --> 01:00:10.273 Move to the Enemy class and get the PlayerFire object to insert values into the bulletObjectPool list 1194 01:00:10.273 --> 01:00:10.986 Replace the Enemy objectPool with a list Move to EnemyManager.cs and change GameObject enemyObjectPool to a List 1195 01:00:10.986 --> 01:00:11.656 Modify the Start function to replace object creation with a List and use the Add function to insert values 1196 01:00:11.656 --> 01:00:12.315 Modify the Update function to use a List instead of a for loop for checking Insert the Enemy into the objectPool in DestroyZone.cs using a List 1197 01:00:12.315 --> 01:00:12.999 Move to the Enemy class and, on collision, insert the Enemy back into the EnemyManager's List objectPool