Unity Game Tutorial: 3D Memory Game / 3D Matching Game | Octo Man | Skillshare

Playback Speed


  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

Unity Game Tutorial: 3D Memory Game / 3D Matching Game

teacher avatar Octo Man, Let's make your dream game a reality!!

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

51 Lessons (6h 43m)
    • 1. #1 Introduction

      2:27
    • 2. #2 The Concept

      6:10
    • 3. #3 Unity Setup

      7:33
    • 4. #4 Card Sprite Atlas

      9:34
    • 5. #5 Card Preparation 1

      10:42
    • 6. #6 Card Preparation 2

      5:08
    • 7. #7 Animating the Card

      12:12
    • 8. #8 Animator Setup

      8:17
    • 9. #9 Player Input 1

      11:30
    • 10. #10 Card Script 1

      6:50
    • 11. #11 Card Script 2

      6:46
    • 12. #12 Updating Card Prefab

      1:38
    • 13. #13 The Card Manager 1

      5:44
    • 14. #14 The Card Manager 2

      12:12
    • 15. #15 The Card Manager 3

      6:23
    • 16. #16 The Card Manager 4

      10:03
    • 17. #17 Error Checking Playfield

      3:22
    • 18. #18 Camera Setting

      5:05
    • 19. #19 Choose only 2 Cards

      10:05
    • 20. #20 Checking for a Match

      10:18
    • 21. #21 Checking for Win

      7:50
    • 22. #22 Hide or Show Matches

      5:32
    • 23. #23 Editor Script 1

      9:37
    • 24. #24 Editor Script 2

      14:27
    • 25. #25 Visualize Playfield

      8:29
    • 26. #26 Timer

      9:12
    • 27. #27 Timer Graphics

      12:16
    • 28. #28 Coding the Timer Bar

      11:06
    • 29. #29 Timer Text

      6:32
    • 30. #30 Scoring System

      9:34
    • 31. #31 Adding Score

      3:52
    • 32. #32 Turn System

      7:47
    • 33. #33 Game Over Setting

      4:41
    • 34. #34 Particle Confetti

      12:46
    • 35. #35 Activate Confetti

      11:04
    • 36. #36 Stopping Timer on Win

      5:37
    • 37. #37 Picking Random Sprites

      11:54
    • 38. #38 Game Over Panel

      14:59
    • 39. #39 Fixing Game Over Panel

      17:01
    • 40. #40 Win Panel

      3:05
    • 41. #41 Win Screen Confetti

      8:01
    • 42. #42 Show Hide Panels

      6:00
    • 43. #43 Button Script

      6:34
    • 44. #44 Menu Scene

      9:26
    • 45. #45 Different Game Modes

      9:56
    • 46. #46 Website Button

      3:01
    • 47. #47 Adding Desk Background

      6:28
    • 48. #48 Menu Background

      4:10
    • 49. #49 Cleaning Debugs

      1:59
    • 50. #50 Conclusion

      4:39
    • 51. #51 Bug Fix

      3:30
  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels
  • Beg/Int level
  • Int/Adv level

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

25

Students

--

Projects

About This Class

In this Unity Video Course you will learn how to create your own 3D Memory Game or 3D Matching Game using the Unity Game Engine. For the functionality we write C# Code in Monodevelop, Visual Studio or which ever IDE you choose.

Unity (2020.3 used in this course)

  • You will learn to create a new 3D Project in Unity and set up everything needed

  • I will show you how you can setup the playfield and create our own cards.

  • I will show you to interact with the cards and flip them using the Animator

C#

  • We will put in functionality with scripts using Monodevelop and C# (you can use Visual Studio or any other IDE)

  • Also we implement a Timer, Score and Turns for more User Experience

  • We create an Editor Script to simplify our Game Playfield or Grid settings

  • We create some helper fuctions to visualize the playfield as well.

Conclusion

As a result of this course you should be able to create your own level with different sizes and cards for your Memory Game.

In the end of this course you will have a fully functional 3D Memory Game.

Course Material

  • 1 Card Deck with 10 Animals

  • 7 UI Atlas with different UI Grafics

  • 1 Checkerboard Texture

  • 1 extra Background for UI Menu

The Course Material is for education purposes only, so if you want to release your own game, create your own grafics for that. Projectfiles and Scripts are not included!

So what are you waiting for?

Let's make your dream game a reality!!

Level: Beginner+
Video Course Length: ~6h 13mins
Unity Version required: 5.6+

Meet Your Teacher

Teacher Profile Image

Octo Man

Let's make your dream game a reality!!

Teacher

Class Ratings

Expectations Met?
  • Exceeded!
    0%
  • Yes
    0%
  • Somewhat
    0%
  • Not really
    0%
Reviews Archive

In October 2018, we updated our review system to improve the way we collect feedback. Below are the reviews written before that update.

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. #1 Introduction: Hello and welcome to the course. My name is Aquaman and I'm your instructor for the next couple of hours here on how to create a 3D memory game in Unity, we are going to learn how to implement user interface, how to use interactive buttons as well as visiting a homepage by pressing them buttons. And we are going to create the game in 3D mode. We're going to learn how a timer works. So a time counts don't words and we're going to let say fill the amount of that by the rest of the time. We're going to implement a scoring as well as animating system of here. So whenever we get a match, we're going to score some points. We can set the points really up if we want to, and we create some particle facts of confetti. We're just going to show us, hey, he has made some good progress of here. So the player in this case, we are creating those cards and all the animations around them, as well as we are going to count how much turns we have taken to solve the actual memory game. Once that is going to be completed, we're going to go over and show some win or lose screen depending on if the time has been down or not. And once we are there at this point, we can choose if we want to play another round or if we want to go back to the main menu and switch to another, let's say again mode for example. So now I'm actually filming this one up. And we now are able to play an extra round or go back to the main menu. Also again, in the background, we are going to learn how to create those particle facts. Again, we just treat them a bit. And then we can go back to the menu. We can choose any other game mode, but that's literally everything we are going to learn in this course. So if you are interested into that, feel free to turn in because we are also taking a look in editor scripting and wet. So it makes your life laid on easier if you know what you're doing. I hope to see you in the course. Feel free to turn in and see if you can learn even more and become a better game developer. 2. #2 The Concept: Hello and welcome to the course. My name is Aquaman from Ottoman games.com. And in this game tutorial, we'll learning how to create a 3D matching game inside Unity engine. What we are going to learn are multiple things. We are, first off starting to create cards and give them our own graphics. You can use mine or you're gonna create your own. It's totally up to you. Then we start to go and learn how to animate them whenever we click on them. And then we're going to make sure that we flip them over back again once the animation has been ended. Also, we are designing a card manager to actually manipulate and change the content accordingly. Also counting up how much of the actual cards have been matched. And so we can flip them back or actually, yeah, keep them open. Also, we add a different scenario or an option for you to set up. If you want the cards to disappear. To disappear the cards, there's one extra thing you need to take into consideration later on, which is part of the particle effects we are going to add, since once we are actually playing them particles and we delete that, the particle effects will be deleted as well because we were just connecting the particles are, we are connecting them to the cart. So, but that is something you need to take care of. Later on. Anyways, we are going to create particles which are looking on like. In the preview, you have seen the looking like confetti Soviet going to take a look into how we can make beautiful confetti particle facts, as well as we can go and discover how we can implement the different UI elements, like a bar, a time of bar, which is going to reduce its size based on the rest of the time, based on the time settings we have made. Also, we're going to put in some score field over here and you can define a score system on your own. How much score you want to give each player whenever he has a match. Also, we are counting turns, like whenever we do a turn, it doesn't matter if it is a matching turn or not that we are going to have them implemented over there as well. So we can later on do probably or you can implement something like a star system that whenever you have less than, let's say 10 turns, depending on, of course, the settings of the actual screen over here, you get three stars, otherwise you get two or one star. But that's not what we have implemented over here, but that are some ideas you can use to. Also we're going to go over a bit and added a scripting, which means whenever we do this, added the scripting. This is going to make our life. A bit easier. That means whenever we do add how much cards we want to lay down over here like a four by five field. As an example, the paramount is calculated automatically and give us a hint whenever we don't have enough sprites inside our actual sprite list to use. Also when you randomize sprites and we shuffled the complete deck. Whenever we create them, the cards inside the playfield. Well, we also do is we do level layout scripting, meaning we are using gizmos to showcase where the cards are going to land at the end. So we can plan a bit further and more. The camera set setting has to be as well as probably changed some other things based on this grid. The final step was we add some background over here. So it looks like a complete 3D scene and is not like a gray or something like that in the background. You can add in any graphics, any content around this game scene. As you please in like you could even put into stones and plants or whatever rounded depending on, again, how you like that. But that needs your 3D skulls to be implemented over here. So you get a feeling for that and you can make it as beautiful in the end as you want. So that is basically everything we learned also, we learn how to implement user interface for menu so we can load the different scenes like an easy seen as normal mode, Hard mode and so on and so forth. So whenever we are able to load one of them seems that we haven't maybe different settings and time-like one insane round probably has only 80 or 60 seconds, but has a huge field to solve. So we do, or you need to do some calculations because the open close animations take some time as well for the cards. So probably 80 seconds as the reza close. 60 might be impossible in this particular case, but maybe you're lucky and you're still April or the players are lucky and still able to solve that. But all of that ideas and stuff like that are laid on totally up to you. So you can go in and implement even more functionalities, even more buttons if you want to. You could even go in and see if you can pause the game as you're like, I don't pause the game. I dust whenever I think we're going to decide to play the game that we don't need to pause it or leave it or whatsoever. So basically that's everything I'm going to cover in this tutorial series. And I hope to see you coming into and join me on my little route of a here. And probably you become a better game developer in the future by learning and just doing over here. Thanks a lot for tuning in and I see you in the next video. Bye-bye. 3. #3 Unity Setup: Welcome back to the course. In this video, we are going to start to create a project file. So first off, if you're using Unity Hub, you can either choose for using a 3D scene setting of a year or you can also go directly with the unity, or in this case, universal ran a pub line. Both of them are, okay. I'm going to start with 3D because we can light on necessarily implemented the render pipeline afterwards. Anything else is not really needed, at least not for the moment, even if you could go all so at anytime for mobile 3D, on mobile 2D. But since we are creating a 3D game which is pliable laid on, on any device, literally in a PC, in a web, as well as on a phone or a smartphone, or even an iOS. We're going to go for the moment just for 3D. So give your project a name. In my case, it's 3D memory game. Put a location to the engine, just press Create. I'm going to use Unity version 2020, 0.3 f, I guess on one F. So we are going to be rather new and fresh with the newest version at the time of release. So this video's become older later on this course, who becomes later on, of course, some things may have changed, but code-wise, usually there are no changes at all. This process is going to take a minute or two. And once that is actually completing and implementing all the necessary packages for unity, then we're good to go and set up our scene. So once the scene and everything has been loaded and started, the first thing you wanna do is we want to deactivate the other check over here just by closing the window, if you want to, you can disable the tech foreign obtains button at the bottom, down below before we are going to work with any kind of a project. And I assume you are probably beginning of the Unity itself. We're going to have multiple screens we're going to take care of and which one we want to see at anytime in game development. The first one and then most necessary is the scene view. This is going to be the first tab you're going to see once you're starting an opening, unity. And depending on whichever Unity version you are going to use in the future or in the past. This will usually be at the same spot. Next one is the hierarchy panel. The hierarchy panel is responsible for all the items, all the objects we can put into the scene. And we're going to see everything over there. So we need to make sure that naming convention is going to be correct light on. So we always at anytime find the objects we want to work with. Usually in a 3D scene, we have a main camera as well as directional light. Set it up. If you want to. You can put these bars at any place you want to. Usually I have my hierarchy panel to the left or to the right of the scene view. The next one, which is also important, is going to be inspector window. You want to make sure that the inspector window at anytime is active and visible. Since whenever we click a component or an object inside the hierarchy, we're going to see any settings and parameters or the components of this objects and so on. The next window you want to always see as the game view. And currently you can see the game view is just next to my senior year. I want to make sure that I put my game view and the bottom down below. Why do I want to do this? Because if I do any change to the camera, I can always see the effect inside the game view. Next one is going to be the project panel. The product is going to hold all the assets we're going to create. All the installed starting was packages and upcoming packages. You always want to see this so it can easily put stuff in it. I usually drag this aside my most of the time below, like around or somewhere in the bottom of the hierarchy panel. The next most important setting or the next potent window is going to be the console. If you don't see the console, make sure you activated inside Window, general console, and all the other ones aren't basically doing the same. Make sure those are always visible in the screen or in the scene. Or in this case in our interface over here, the Asset Store tab over here is not important, at least not for the moment. And proteosome, not for this part. But this should be your setting kind of like that. So you always see gave, you always see scene view and a 10 percent always see the console as well as the hierarchy and the project panel as well as the inspector. If you want to make your life later on easier, you can also go to rendering lighting, and this is going to open another lighting tab can usually put next to your inspector window. So at anytime if there is no lighting active like here, we currently don't have any lighting settings. We can go and down below and click the auto-generate relighting button. Otherwise, we need to do this manually. But we go there once we are starting creating the game and so on. And the last thing you want to setup over here is the aspect ratio of your game view. So open this one up as March as, Until you can see gizmos over here and go and select Free Aspect. Currently, free aspect means we can see anything and the camera is changing to the aspect of the game view. So whenever I now go and zoom out and change the aspect ratio of my screen or the game view, the camera's changing. This is not good practice. We want to make sure that we hit either ten by nine or in this case, nine by 16 by nine or six and 10. Usually I work in 16 by 9 if I go like portrait or landscape mode. And nine by 16 if I go in to portray mode. So I'm gonna go with 16 by 9, since that is going to be the resolution I'm going to work with. This is important later on for Canvas visibility and all the advocate stuff. So once that is set up, we are actually good to go. We want to make sure that we see all the gizmos inside. Our main view over here is not. Make sure you activate gizmos over here, just highlighted so it's lit up and we can see everything the day. If you don't see a grid over here, you can also go here to this little toggle and toggle it on or off. In my case, I always use the grid. I always wanted to see where I am in this space. If you need to go Nate on Tuesday because we are going to work on the camera. We can also use a 2D mode over here in which we have like a flat or isometric view over the z axis. But that's everything we need to do in setting up our unity. And the final part is if you want to start a new project and probably all complete setting over here is ruined. You can go here into layout and you can save the current layout. Once that is completed, you're gonna give it a name. I have mine here as well. I can press on that and everything is going to be set up as my setting inside my layout over there. And as you can see, I've seen safe this one before and everything is as it has been before. 4. #4 Card Sprite Atlas: Welcome back to the course. In this part, we want to start to create the first card. Since we are working in a 3D version of a here, we want to create 3D objects for that. What we're going to create as a 3D cube in our scene, again, go right-click hierarchy, create a 3D object cubed. We can rename this to be, let's say our memory card or a card prevent or just card. We're going to change them look of the cart just a bit. So first off, we're gonna go into the inspector and check all the settings in the transform. What I want to do is I want to reset the transform. So I go to the little three dots and press reset this receptor it and to the world space position 0, 0, 0 and resizes back to its original scale of 111. Also, it actually resets to rotation. This box already contains a collider, in this case a box collider component. But we don't touch that for the moment. All we wanna gonna do is we want to scale this object down so it's runs a flat, let say 2.1 or something and the y-axis. So we can type in 0.12, the scale over here, or you can just drag it around however you please. And like. So this is going to be later on our card or our card handler. But what we also need a several components which are responsible for the look of the card, as well as some functionalities by clicking on this card so it can flip over. So we open a card. And also later on we need fountains to flip close the cards as well. So that means we also want to animate those cards laid down in any way we want as fast as we want, give some effects to it and all the other good stuff. But before we go there, we want to implement even more things. First off, I want you to go to Assets folder in the project window and right-click create a new folder. And this is going to be our Textures folder and textures. I want you to implement the underwater set one PNG, or your very own specific underwater card set you have created. So you go there and just drag it into the textures folder. Now we want to prepare one of the things. That case, we wanna go from texture psi of t fold to strike a DUI and apply the changes. Since that is going to be not a sprite mode single, but a sprite mode multiple. We need to implement the Sprite Editor. So we hit Sprite Editor and apply. As you can see, no Sprite Editor window is registered. Please download the 2D package for the package manager. To do so we do as unity tells us, we go to Window Package Manager and we wait until everything has been loaded. If it tells. It only shows us the projects only or packages only in Project, we go and change this one back to Unity Registry. That case, we can see the 2D sprite package over here. Use Unity Editor window to create added sprite as a properties like the perfect, the borders and the physics stage. We're going to click on install in the bottom right. We wait until everything has been implemented and downloaded. So you need to make sure you are connected to the Internet and we're good to go. So once everything has been closed, we can close the Package Manager window. And as you can see, this package now has been implemented over here. We don't need to do anything to the code. What we need to do is we go back to our actual taxes folder. When you select our underwater said one in my case, you can set your own or select your own. We go to Sprite Editor. In here we're going to see the full set of cards I am sending you with the actual project. What do you want to do is you wanna go to slice automatic pivot center. And then we say slice. We can close that by just clicking anywhere but the window and now everything on these little objects or cards should be correctly set it up. Some of them may or may not fit 10 percent because there might be a little offset or a shadow which like this one, as you can see, it has no input over here. This one here is going to be not necessarily in my pointer. I can just delete it by hitting the delete key. For Mac users, I'm not 100% sure how that works. Now we need to make sure that all our assets are correctly set it up. As you can see, there's a little offset or a little, let say gradient on my cards, which is not too ugly at the, at all. But we just need to make sure that these little blue lines over here of each of them cards is going to be rather close to him. So we don't have any bad looking cards in the end. If you are not 100 percent sure about the size, you can always check it out over here. We want to make sure and myopia, in my case, it's 428 and the length and then the hide going to type it in four to eight by four to eight. And then we just drag a box around until it fits the position of the card. You can avoid using them empties. But if you later on want to use them for whatever reason, then that's why I send them to you. Again, you can avoid using them. They don't really need to be insight our game here. So I have the backside of my currents, which are going to be the same size hopefully. And if not, then we need to make them a bit bigger. But I guess they should have the same size of four to eight. We move it into the corner of the card. Check out the opposite corner. Looks good. And the next one, you can decide which one you want to use as being the backside of the card. That is totally up to you. So I'm going to put in again four to eight for the other cards here. And then drag the current and 21 of them corners. So then kind of fit my design. Same for the other ones. Four to 84 to eight. If it looks good and is the correct position, then go to the next one. Again, this can always happen if you actually export objects or graphics from any, from any graphics software. So bear with me. This is happening. So not, not always, errors in works 100%. So keep that in mind as you become, or if you know how that works later on. If you are as 2D artist or any kind of artist, you know that this can happen to this rule, gradients, shadows, and anything else like that. Kinda put this into the right corner. We are almost done over here, so just two or three more. Just repeat the process. I know it takes time, but you want to go through that and make it as precise as possible. So four to eight by four to 80 not wants too much. Make sure one of them corners as correctly lined up. And the last one is going to be the shark over here. I line up the graphic and everything should be fine. If you want to go and even get away from with one of them. Yeah, gradients in the bottom of a year, you can even resize this one smaller, so it can go with something like 420. But make sure that you don't overdo it because the card or the image of them, of all of them need to have the same size of the lice day stretch weirdly laid on in the game. So once again, check them all if you want to. You can also give them a name. Like however you want to. Like. For example, you can say this is the back backside one or just card back one. So you can give it a name over here. And we're going to see this change later on in the inspector or in the assets folder as well. So called back to again later on which we choose one of them and then we have the other ones. You can also use one of these as being the card back, again, totally up to you. Don't forget to apply the changes in the top-right corner and close the Sprite Editor window. 5. #5 Card Preparation 1: Welcome back to the course. In this part, we're gonna go and continue working on the card prefab over here. First things first, when you have an actually renamed your cards of the day, you can see that they just keep on take the name of whatever you set them inside the Sprite Editor. Now what I want to do is I'm going to create the card. So first of all, I want to lay down the card back on one side. And any, let's say empty card front onto the other side. Do we do this? We first of open one of our card backs over here. I go with card back to and I drag it directly onto, on the top of my card. What's happening is that it's going to resize itself. It creates a new object, and the object contains a sprite renderer. This is going to render the sprite according to whatever it is inside. As you can see, the y-axis scale to tens. So I'm going to put it down. No, I keep it actually as 10 since it is part of it, it just gets back the y scale directly over on its own, on its charged object. So the child object means this is a sub object of that object. So we can now hit E for rotate or go to the rotation tool, hold down control and snub rotate over ax or of, of AKS. But as you can see now, this even skills even further. So the best way to avoid that is not dragging the card back onto the top itself. So we're gonna do the same, but we drag it outside of the card as being created a new object. As you can see now the scale of the object is 1, 1, 1. So it doesn't scale whenever we rotated at the current place. Let's try that again. I hold down control, rotate by 90 degrees until it's flat and we're good to go. Now, I'm going to hit the W key. The W key makes our move tool enabled. So keep them in mind to speed up your own process. I'm going to bring it up a bit until I cannot see the top of the card anymore, also square or cube actually. Then I hit the R key or you can also select the scale tool over here. And we score scale down uniformly. How long we want to scale is rather simple until we don't see anything of the card anymore. It might be a bit heavy with the numbers, so we need to figure out what could be the correct numbers. At this point. I'm going to try a 0.25 over here. Probably in 0.4 is a bit better. In x and y. That doesn't seem to fit 100%. So I got to go and take this number 2.4 here as well. But as you can see, there are still a little gap. So we don't, or I haven't hit 100% of here with the scale. Well, it can also do is we can use the 2D tool, which is the rec tool, which can be, or which means we can go in the top view over here by just selecting the y, in this case over here. And then we drank one of them sides until we see a bit of a white. And we're going to do this like for one axis only, so we know the exact amount. Then I copy that over and bring this over to the y and to the zed value. That value actually doesn't need to be the correct one, but just in case, I'm going to put it over here. So now everything is in place. And since we know that this one is a size of 0.1, we can know now position this one incorrectly onto the card itself. So we drag this one now on top of the card. And now we can also see positioning that 1.52 over here would help us a bit. But as you can see, it starts to Flickr. And since we don't want us to Flickr, we need to lift it up just a bit more. So point 51, for example, should do the deal. Looks okay. There's a slight offset on X i 0 this one out. So I don't have any weird numbers at all anymore. As you can see, there's still a slight gap or slow, still a small white border over here. So we may go and bring this number up here to 0.234, 2, 3, 4 here as well. Probably we need to go a bit further with this number. So 0.3 or 0.236. And down we don't see any of those weirdness anymore. Again, this is to us through the weird graphics and all the other good stuff. There's maybe a ramp or gradient or something similar or related to this. If you are a 3D artists, you can also create five or 10 of them UVs and then create multiple materials for multiple cards. So that is possible here as well. But if you're not, then we're going to go this route or this way. Now we need to have the other side here as well. In that case, I'm going to use one of the top ones which don't contain any image. Since I don't have that, I could also use any of them. Or what we can do is we can go back to the Sprite Editor and say, Okay, we need one more here. How does it work? We just drag into the scene over here into this object, tried to hit the border. Remember the number 428428. Put this position, this one so that everything is visible at any time in any place. And once we're happy with that, we can also rename this one to be an empty tile or just empty, and apply the changes to the sprite itself. Close that and now I have an empty car piece and I can put this into the bottom. So the fun part now is we just need to duplicate the top. So we hit control D beforehand. Make sure you double audio select as one Control D. We drag this one downwards until we can see the card back. And now we put the empty inside the sprite renderer. Now we have both cards on boats, both sides visible. We have this one on the top, we have the other one on the bottom. And we have the cube for our 3D log in the middle. Pretty good. Now we can create a material which is going to cover the sides or the actual 3D object of a here, which is going to give it a bit warmer look, I would say. But again, you can fiddle around with all these sizes, see what makes you happy. You can actually make them smaller or bigger so you don't have any weird, Let's say, gradients onto the side. Meaning you can always go into one of them sets again, say Sprite Editor. And instead of going with that, say four to eight, you can also go with a four to four for example. So it reduces the size of all sides. And you shouldn't see any of the gradients. You just want to make sure that you do not or you are not outside. And the distance between the golden border and the golden border here is going to be said the way that nothing of the actual outsides are going to be visible. And everything is like, let's say, rendered from the center on. That is even tools to small amount of a here or not good enough for you. Again, you can even go further, can tell our videos the size of them totally to, let's say 420. So everything will fit 100% at this point. Well, that's what I would say. Just make sure everything is always located all around the actual pivot point in the center. So if you go with a four to 44 to four here as well, you can see it's going to go from one corner to the other. So we replace it so that everything is visible. But no, we had yak radians are going to be visible at this point. Again, you can do that. However you please, unlike same here, I can reduce this one by one pixel to the right maybe, and check the other sides as well. Reduce a tear to one pixel. And so I don't have this half transparent pieces visible at this point, and same for the other ones. And you can always come back and change that to your needs here. Same down below, that looks good. Apply the changes once you are done and happy with all your card settings and close the Sprite Editor. And it should look a bit better. Now, again, if you don't like the look of it, go into y-axis and in that case, take the rect tool and try to figure out the correct placement of that. Wanna go isometric. You can select the center of a hero or the top view over there. So this is going to be like an isometric view which shows you kind of girl and how much you are over the border on each of them sides over here. But you can also correct the actual positions and laid on on x and that, so you know, you're kind of in the center of the actual 3D object over here. Pretty good so far. 6. #6 Card Preparation 2: Welcome back to the course. In this point we're going to finalize the card itself. So I was playing around with them corners of here and trying to fit it so that none of the corners are, let's say, overlapping too much. How did I do this? I go into the actual isometric view and choose one of the sides. As an example, I can use the x axis, I zoom in it and use the rank tool and select one of them cards. For you. It might be something like here, so it's little overlapping. So meaning if you want to, you can drag around them until the wide line of the rec tool for the kind of the wide line of the 3D object. So it's a bit fiddly, but you're going to find out how that works. Zoom in a bit as much as you can. And 12, if you cannot zoom in more than, I don't know, a good amount of a here. Then press F4 focus so it can focus the camera on this current object we're working on. Because sometimes if you go to close over here was the camera, you cannot see too much at this point. In my case, I'm going to focus on the card itself in the middle, press on one of them objects, and then try to figure out where to go. Once you're down was one side, like from left to right and right to ask, select the z-axis or z axis over here and do the same. And also repeat the steps at the bottom. Do it for the xhat as well as for the x-axis. Once you're happy with the result, I going to rename the second piece of here by hitting F2 or you can just go over here inside the inspector. This is going to be my card front. This is laid on unnecessary because I need to talk to the conference by encode, going to rename this one to be the card back. And this is now our full card. Go back out of isometric views. So your backend perspective view, everything should be fine now, we can use any tool again and position these things. But what we want to do is we want to create a prefab out of it. So select the assets folder inside the project window. Right-click Create New Folder, prefabs. We don't need much prefabs and this product, but we want to make sure of that we have at least one which is going to represent our card. To create a prefab, we just go inside the folder, just selected inside the acid, and drank the card into this folder. Depending on the version you are going to use, the prefab handling is a bit different. But if you'd only see now the card over here, you're on the right track. If it is blue, in this case, a new Unity 2020 that turns blue. I believe it started to turn blue in 2019, something. You are no know that this object is a prefab. What is a Prefab? A prefab is kind of a template object which we can refer to and actually, yeah, instantiated anytime or created anytime it, any runtime and so on and so forth. As long as we have a connection to the prefab itself. And that's what we're gonna do whenever we create our actual playfield. Since we want to alternate the playfield creation, we want to have one prefab, so we don't have to take each card into a new single prefab to be created. So we just need one prefab, one template. The bottom is literally empty. And the card later on gets an information about what type of card is this going to be. So we can create code which is able to compare the actual cards we have opened. So for example, using an ID or anything else. And we can then also change the card front for with any sprite we want to put into. For example, we can automatically create this little card here or the column fish or anything else we want to can make use of them. And then we're going to set them up automatically. But that's what we're gonna do in one of the next videos. So now we have our prefab done. Meaning whenever I delete the card from the scene and I go to my Prefabs folder. I can go and drag it in back and everything as it is, has been set it up. Co-req may also, if we want to do any change, we're going to do the change inside the prefab and everything who is correlating or is referring to those template. The end we change something on the template. The card itself will change itself and each of the single instances inside our scene are going to do the same. 7. #7 Animating the Card: Welcome back to the course. In this part we want to animate the cart to flip open as well as flip close. To do that, we have to do a bit more stuff to the cart before we can do that actually. So the first thing I wanna do is I want to create an empty game object. This empty game object is going to be our card holder. You can rename this to whatever you want. This is basically going to be the positioning of the card itself and is just holding the card on top of it. Why is that important? If we are actually animating this card on whatever position we are going to do this. And we lift it up and down and all the keys are going to be recorded. The problem is that all the animations would be at the same position, no matter where the other cards are, there would go automatically to the cards position wherever we have positioned that. To avoid that, we're going to go and create this little holder over here. And I reset position on 000 000, so it's in the center of the card. Now we take this card, I need to make sure that this is also position 0, 0, 0 over here. And I want to make it so that the card holder is holding our actual card prefab. We're going to change the prefab in a minute as well. Now whenever we move the cart itself up and down or we rotated, the card holder is not affected. The cool thing about that is if I now put a copy and animate this one, all the cards will animate directly with the card holder is, but not where the actual card is. Since, again, we are politically animating the card itself being child object of the card holder. So since animating always happens in a world space or in a local space, in that case, we want to animate the card and the local space of the card holder. So the card holder can be anywhere underworld and the COD will automatically follow at this point. To do that, we first off select the carts and status the one we want to animate. I want to create an animation where the card goes a bit up, rotates by 180 degrees in any direction and pops bar pops down to its original position. And we want to do the same backwards. We can also do another flip animation basically to the card itself. So where we go is Window Animation. Animation. Make sure you have the card prefab over here selected over there. Now we hit Create and create a new card animation. For that, I'm going to go and create a new folder inside our assets folder. So create a new folder for me, it's German over here, so no worries. And I named this animations, since we will have multiple of them. Then and the bottom over here, we give it a name. In my case, let's say flip card open. And then we hit enter to save that. We now have a timeline over here in which we can do all these animations. First off, we need to press the record button. Now, what we can do is we can flip the card over, and since we are having a keyframe over here, we can hold on the leftmost key to go through the time. You can also select the time of the. So we will test it out a bit and see what a good animation is going to be. So I want to get bringing this one at first up to a position, whatever position that is not really necessary. We can also do a small movement of the hair so we can move it up, rotated at point and bring it back what's done? So it lays open onto the field. So for example, we can say, okay, we want this to be rather quick, 2.5th as an example, we want to bring the card up, so we just drag it up inside the scene view. So when we go with the time slider, we can see no, okay, this moves up over here. We do have an ease in and ease out on these curves, but we're going to take a look into them later on. Then I want to keep that one until like maybe 45. So quarter or three quarter of a second to 0, or 0, 45 over here, which is 45 milliseconds, I would say. That is going to represent 1 second of there. Now I want to make another keyframe. I want to copy this position key frame over here. So I hit Control C. When I selected with the mouse like that Control C. And I go to the frame and then I press Control V, so I can duplicate this key from here to here. So it has like an idle position on top. And then I want to slam down the card, let's say up to 1 second over there. For this key here, we can also use differs key we're creating or we were starting it. So I copy this one and now hit Control V. So I duplicated to the 1 second. When I now press Play, it goes up, holds it, and brings it down. Pretty good. Meanwhile, we are now here on the top. We want to do a 180 degree rotation. For that case, I hit E for rotate, hit Control. Don't forget, the record has to be enabled and then rotate this one now to 180 degrees. But as you can see that we are going to flip it on top of here right now and then we pull it down. So that is actually not a good way. It's not a bad way actually. But we can also refine that we can take this key here and this key over here. That means the rotation only happens once the cards on top. And then we bring the car down. Pretty good if we play now, we open that, it flips over and we are good to go. Well, we can also do is we stopped that. We take the key, lets say a bit more here. So we have meanwhile moving it up already, The rotation over there and then we bring down the card. You can also say you want to flip this completely. You don't want to hold it in there, the air and bring it basically down, or you bring it up, flip it as Meanwhile doing so an incentive go downwards one Steve rotation is done. Again. All of that is totally up to your own personal opinion, I would say. So. I'm happy with that. The complete animation now takes 1 second. So whenever we want to actually animate this to flip open, we can do so. We now do the same thing to no animation because we need to have a flip close animation as well. To do that, we can now create a new clip. We hit Create New Clip. We're going to name it as whatever we want to. In this case a flip close or in this case flip card close. Now we hit Save and then we're going to do the same thing or however we want to do this. For example, we can go to Flipkart open and we can copy all the keys. But in that case, we need to start with the rotation open. So basically what we need is this key and the position key at the bottom. So first we copy the first frame or the first position key over here, copy control C. We go to the other animation, goes the timeline at the very bottom and hit Control V is that it's possible. That is not possible. We're going to be able to move that as we did before. So I try Control C. And since we don't have the property, we can maybe have to add the position of the cart. So now it's starting with the position of a here. No matter what. What we wanna do is we want to try to do the same thing as we did with the other animation. So we delete the last key over here or we can keep it over there. Basically, that's where we want to be anyways, after 1 second, go back to the other one to get the keys right. So first off, we do have a rotation of here. We start this as 20 or 20 milliseconds or 20 frames. Actually. We can also add a rotation property, or we're going to go to the time-frame of 20 or just start at one. Basically, it doesn't matter how we do our 180 degree rotation, but we need to make sure that we are starting flipped. So we go and add property transform, rotation and hit the plus. And over here we go with our key and we had record. First thing is we want to hit E to rotate, hold control and snap rotate. So we are starting at the full rotation of 180 degrees into that direction or rotation. Or in this case, this add access. What we wanna do now is we want to keep holding the card until the 20th frame onto this key. So we can also do drag the key until we are at this point. Once again, if we go to Flipkart open, we do the same over here, but we also have a key or an AP away movement in the positioning up until the sturdiest for oil the 30 frame. So I tried to copy this key, Control C, go to the other one, moved 230 over here and hit Control V, if that is possible. In my case, sadly, that is not possible. So we're going to lift up the key of the actual card to the position where we have Kumar actually lifted this one up. So in that case it can go with this frame over here, and we can see this number on the y axis. This is what we can copy. So I hit Control C one, marking this one, go to the close one, move to 30. And now I paste the amount. So we do have the actual lift up amount of a here. Now the rotation is going to happen because we want to close the actual card. We can go again here to check that for the timing in our flip open card animation, which is going to close the card until the 45 over a day. So we go back, Flipkart close 45 and which what we wanna do is we want to take the complete current rotation and close this one over here and then the cart go down. So in this case we now flip over the opened cart, close it and bring it downwards. If you want to do this one faster because maybe the animation is not fast enough for you. You can also do so. You can take all the keys at the same time and use the little blue line over here to shrink down or scale down to complete animation based on their current position. I don't do this. I keep the one seconds and status going to be a rather okay. One over there. There are two more animations we need to create, but we're going to continue with that. And then next video. 8. #8 Animator Setup: Welcome back to the course. In this part, we want to create two more states for our card. Since whenever we are animating things, we may need to have some idle states because we want to later on talk to the card and open it. And we can also do it the different. So there are two ways that really on how we can set up our animations. Let's take a look. We do have an animator component now on our card itself, not the current holder. It has to be on the card. We wanna do is we want to double-click this controller, the cart controller and the animator window is going to pop up. Or we can see two states. These are the two animations we created beforehand. Also, we do have a layers which we don't need at this point and parameters. We want to add a new parameter, in this case, a Boolean. If something is open, like card is closed or open, we can name it so that the card is currently flipped open or not. Let's name it, flipped. Flipped open. So if that is true, then a card should show its front. And so we see the actual card. If it's not, we should see the backside of the card. In our case, since we do not know where we want to start and so on and so forth. We need an idle state. For example, if we combine it to whatever state we want to, then the problem is that car probably doesn't animation first, since we do have only a flip card close and the Flipkart open. But we don't have a state where just the current lays on the ground. This is what we need to create first. So whenever the current is at the very start is going to be flipped close and we wanna go and sunlight, or meanwhile this Boolean to returns true. Then we want to go into this animation and play it until we are done. Once we are saying on a or no, this is flipped closed and we go into the flip close animation and return back to our idle state, which we haven't created yet. So let's create this. We go to card. And in here we do have our animator or ready. We go select the card again and open the animation window. Once again, we create a new clip. And we name this just idle or flip card idle or just card idle. The name of that is not really important over here. With card idle selected, we want to add a new transform position property, and that's it. Now we do have this one in our Animator window. We have the animation connected to it, and we have a tag and so on. We don't need to do anything of that. So everything is good to go. What we now wanna do is we want to select the card idea was right mouse button and say this is our set default layer state. So whenever we press Play, it just stays in this little, yeah, Actually in this animation. Now we right-click this one again and say make transition to Flipkart open. And now we have a little arrow. This arrow says, whenever something happens, we wanna go from this animation to this animation. So we need to set the trigger. The trigger is going to be the condition of here, so we hit the little plus. So if flipped open is true, we want to flip open the card or we also want to set as the Has Exit Time disabled because we don't want any extra time on this. The exit time means just wherever this animation is. We don't want to react to the actual exit time. We want to go into this transition at any point of the animation. That's why Has Exit Time is going to be false. Now again, this one now will go from this point we can see a little preview at the very bottom of the window is open. So the animation stays there. Then it does d flip open animation, and then it repeats. But that's what we don't want. We don't want the flip carton card animation or card open animation to be repetitive. In that case, we go to our animations project window. We select Flip card open and deactivate and Luke time, same for Flipkart close. We don't want to have a loop bubble animation, so we deactivate loop time here as well. Once our animation now is going to be completed, so the current is flipped open. We want to wait for this Boolean to check or actually change. So we now lead an, a transition to the Flipkart close. And this transition now has to have extra time on. Yes. And we want our actual Flipkart open condition should be now false. So that means if that animation has been ended for me and our flipped open is resetting to force we go into this animation. Once we are in this animation, we make another transition back to card idle and we just keep Has Exit Time over there. Means whenever we fill up, close the card, we go automatically into the idle state. Again. This is the actual transition which is going to happen. So we don't really need to touch that at this particular point, since we are at the bottom already, whenever we transition into card idle. Once again, in card idle, we're going to stay there until the actual flipped open becomes true by a mouse-click, for example. So we animate open this one, then we wait until it's closing by code or whatever. And actually we do this by code. Now when we play this animation and go back to the idle state, once everything has been completed, literally like the time has run out or the animations have been ended. We can go into the next phase of playing a card. As an example. That's everything we need to do now. So now we can also test this out before you do so you can go to C and you locate your camera so you can see how the animation is going to look. Then select the main camera and go to GameObject. Align With view. Now the camera and the game view has been changed. So the camera actually positioned to the screen view we currently have in the scene view actually. Now whenever I open the animator window and I hit play, nothing should happen, but the blue line should run through here. As you can see, this is a repeating animation. Now it keeps on inside or k keeps on being inside the ILO. And once I now hit this ball in, card flips open and it now place until this point. Now the animation has been played as not looping. Otherwise it would keep on going and going and going. And now it waits for us to flip the cloze card again. So we close down, we hit the ball in out. And once that is happening, we flip down the card and get back into the idle state. So we can test this one out. Flip open, flip close. Pretty good. And now the card is literally done, actually Wizards animations. Of course, you can implement also some particle fats, but we're going to take a look into this way later on, I guess, because that is not part or not necessary for the actual parts at this point. 9. #9 Player Input 1: Welcome back to the course. In this part we want to work on the card, but more so we can actually touch the card and play the animation whenever we have touched it. So, but before we do so, we want to go and create a card holder prefab. So we get rid of this card prefab literally because we don't really need this anymore. And our card is going to return actually read of here. So I take the card holder now and bring this inside the prefabs folder. You can see this is not actually read anymore because it's no, again, part of a prefab. If we want to change something inside the card holder, we always have to open the prefab by pressing open here, or just double-click the prefab itself. So for example, when we double-click that, we're going to see the full hierarchy of the card. Or you can also see it's all know read. But again, that is not really important since again, this prefab is just not existing anymore. What we can do is we can right-click on that. We can say prefab unpack. So this brief AB is now not existing anymore. We have unpacked it and it has no prefab overall, no template anymore at this point. So nothing of them is red anymore. The cardholder still is going to be here. So the actual cards itself, as well as all the corresponding parts over here, are now only responsible for our card holder or child objects for the card holder. Now, let's test our animation pretty quick. The cool thing is, no matter when we place the card holder, the animation has been made locally, really like relative to the card holder. So the animation will play wherever we place our card holder. So the next thing is, whenever we want to touch this little card, we want to make it so that it's playing the animation to flip open. We have multiple possibilities to do that. For example, we can shoot a ray down. And like a ray cast, we should this ranked castes from the camera position on to the next hitting object and try to find a script which is actually being able to trigger the animation. We can also just directly look for an animator component and say, Hey, I animate this because we were hitting this. To do that, we need to have a script. We go to our assets folder, right-click, create a new folder and name this one scripts. We don't want like scripts, so we are inside and say right-click, Create C Sharp script and give it a name. For example, you can name this one player input and double-click to open and MonoDevelop Visual Studio or whatever you please don't like. Once the script has been loaded, we can fill in literally anything we want to. And depending on how we want to handle the actual input, we can store all this information over there. We can send them data and so on and so forth. So since we want to actually do a button clicked, Like for example in leftmost click and we want to suit and you recast in that we need to do this inside the update loop. Inputs are the only things you should put inside the update loop because the update loop runs 60 times a second. So inputs are the only things we need to take care of. So first off, we want to see if we hit something when we click the mouse. So first off, we want to write the mouse input. In that case we request the left mouse button. So if input dot get mouse button down. So whenever we click one mouse button, open, close parentheses, and we're going to put a argument 0 inside, which is representing the leftmost key. If we are clicking that, we want to shoot a ray. In that case we need two components, the array itself and array cast. Actually a rank cast it. So first off, we create a ranking instead, limited, and that's everything we need to do at the moment. The next thing is we need to have a re, a new RI, we can give it a name Ray. And we need to define where we want to assume this ray from and to. We want to suit the ray from the main camera inside the scene into the world space. The screen. To do that, we need to say we want to create a new array. And now we have two possibilities where you're going to have the possibility to pack in an origin in, as a vector as well as interaction. But we also have another possibility, instead of creating a new array, we can also say camera, dot, domain, dot screen point to Ray. And as you can see, this is part of mono behavior. When we can put in is a vector two position. The position or in this case a vector strain. The position we want to shoot a ray 2 is our input dot mouse position. So our current mouse position on the screen. So we shoot from the camera to the point where the current mouse position is converted into the 3D space and shoot this ray. Now we want to check if we hit something with this one ray we have suited and if we have hit something. So we can say another if statement over here. We go for physics. Don't re-cast. You want a pseudo re-cast from with our currently created rain out hit. So and we save literally whatever we hit inside this re-cast it. We could also go and put in some other arguments over here, but we don't need to at this particular point. Since as an example we can say which layer we want to check, as well as how long the array we want to show just going to be. But since everybody probably has a different scenario, a different camera distance, this ray lengths should be or would be different. All we now wanna do is we want to see what we hit. So in that case, we can get this in return. So for example, we can debug that. We can say debug dot log, open, close parentheses. And then here we can say something like hit dot transform, dot GameObject. In this case it will return whatever we had. The transform and the name literally off the game object we were heading, which is going to happen constantly whenever we click the left mouse button. Don't forget to save the script Control S for quick save. And most of any, or in Apple probably Command S and that the compiler run and see if there are any coding issues. If they are coding issues, you probably see something directly inside the console. Now we need to pick or put the player input script into our scene. For that purpose, I usually create a new empty game object inside the hierarchy panel and nameless one game manager. As an example, it's just a name of an empty game object. If you want to, you can reset it to any position. You can place this wherever you want to. You can even go, give it a little. Let's say I can, so you find that easy and can select it easier if you want to. Work more inside the scene view. Now we take the plan, put script, and drag it on top. Now we've plus play and see what's going to happen. So whenever the game runs and we click over here, we should see, Oh, we were hitting a card. Why it doesn't it actually returned a card holder. Well, the issue is that there is no actual collider on top of the card holder. But the card itself does have a box collider on component on it. So the box collider component going to be seen. If I click anywhere else inside the scene, Let's say here, nothing is coming into the actual kernel console. You can add any time clear the console. Try round click everywhere I want as well as click on the card. Now since we know that we are actually talking to this object, we can just simply talk, for example, to the animator component to do the actual animation. But before we do that, we want to have some more, let's say logic because we want to know, was it the first thing we were hitting as well as was it the second thing. But for testing purposes, we can also say something like head. So whatever we had, don't know. It could go and say transform.py gets component, but get components should or might not be available. We'll see that in a sec, Get component is available. We want to get the animator component over here. That's what we want to talk to. And what we can tell that one particular code now is we can set a bull at this point. And you probably remember the ball. We now need to figure or put in the name of the bool, however, we named it inside the animator. So when we go into the animator tab, we named it or I named it flipped open. Make sure Does this case zen the tariff so you can copy the complete name over here, control C, double-click to change that thing. Control C. And now we need to put the same name as an argument over here in quotes. Then we need to tell this one, hey, is the value or no, positive or negative? Is it false or true? We can now say, okay, we want to test if we can flip open the card whenever we touch it. Don't forget to save that the compiler run. And once it's done, press play. And we should see whenever we now hit the card was our mouth. The card flips open. If we do the same, it doesn't react to it because we only send a true inside and not a false. 10. #10 Card Script 1: Welcome back to the course. In this part, we want to take a look into a card script, since we want to define what type of card this is going to be, as well as which components are we need to change actually whenever we create a car prefab. So we need to talk to, for example, the bottom side or in this case the flip side on the bottom over here. So we can put in any kind of image or sprite to represent our actual card. To do that, we first off go into our scripts folder and create, right-click, create a new C-sharp script and just name this one card. You can also name this whatever you please and the like. Once the compiler is done running, we want to drag the current script directly onto the card holder. Like that. And of course you want to open this one in our actual IDE. So MonoDevelop or Visual Studio as you please. And like once the card script is open, we get rid of starting update at least for the moment because we don't really need them at this point. Now, what we want to know is axial several things. The first thing is, what is the actual ID of the card? We can create an ID system. We can use an enum methyl 1, 2, but an idea is probably the easiest. So first off, we make it a public one so we can set it. We can also say it's not a public, so we don't really access it from outside by mistake as an example. So maybe we keep it private. So you can type private in front of the variable or you just don't because he knows everything which is not private. Actors are not public athlete is going to be private. So in that case we say int card ID. We're going to set the card I delayed on whenever we instantiate a car it for that we're going to create a public actual function, which is going to set the current ID by, let's say a loop we are going to create later on. So the next thing is we want to know the card front. So what is going to be the front of the card? In this case, this one piece, especially we need to talk laid on to the sprite renderer component. And of course, the corresponding sprite. In our case, we want to make so that we talk or create a sprite renderer. We can name this as P renderer. Sprite renderer. However you please. And like probably I'm going to name this sprite renderer as whatever it is. Well, we can also say is this is going to be the sprite front or the front of a card or just Card Front, whatever you please. Unlike again, probably cold front is not a bad idea at this point. So we want to lead on talk to the sprite inside the sprite renderer and sending the corresponding spray to the card front. So whenever we call the corresponding function, the next thing is we want to connect the animator. The animator is going to be in the child object, so we need to grab it laid on so we can talk to it and animate the actual card whenever we touch it, to animate the actual card. So in that case, the issue is going to happen that we of course want to animate, note that the card holder on which the current is going to be, but a child object of that. That's why we are laid on a need to create a different, let's say, scenario for our collision object. But that's going to be rather simple. We're going to see that once we're at this point. And that is basically for the moment, at least everything we need. Now we want to create the access point for the current whenever we create a new card. In that case, we're going to say public void. And whenever we create the card, we want to grab all the necessary components of this particular card, wherever they are. And we want to make them so that the animator knows where the animator as. Then we need to know whether card front of the card is going to be, as well as the card ID. And of course, what the sprite in the card front is. The downside is this way, we need to make sure that probably the sprite renderer can go and be public as well as the animator. So we can just drag them in inside the prefab. So we just need to update the sprites as well as we don't really need to talk to the animator except we want to animate or talk to it. Bye, open the card or close the card as being a function. So in that case, we want to set the card up. So first thing is we want to know what is the going to be our corresponding input ID. And then we want to know what the sprite is. We want to set into our card front based on the ID we have selected. We don't need to do anything to the animator component. Now we want to make it so that whenever we call set card, we can also name this one create card, but it's not really a creation method. We want to put in the card ID being this one ID first. So card ID is equal to ID. So the ID which is currently coming into this function. And now we want to set the card front dots sprite to be equal to the incoming sprite. Like that. If you are not 100% sure of that is the correct one because you have an ugly naming convention. You can put a, let's say an underscore in front of it so you want to present, we know that these are corresponding to each other or they are just the ones we are talking to. So now we have, whenever we create a new card, like we instantiate a card, we want to call set card up. We want to know the ID as well as the sprite and set the sprite renderer sprite to be the sprite we send in as well as the ID. We need the ID later on to compare, which is this first selected card, who was the second son acted card and compare if the match or not. So we don't match sprites, we do match IDs, which is actually easier for us to understand and for you to reproduce actually. 11. #11 Card Script 2: Welcome back to the course. In this part, we want to continue working on the card as well as the current script to make it a bit more useful for us. First off, when you select the card holder and we created those two slots, as you can see for the card front as well as for the animator component. You can now drive the card directly inside the animator component and you take the card front and posters. And the sprite renderer now can be updated, so both can be talked to pretty good. Now what we wanna do is we'll take the box collider from the card itself and put it into to the card holder object. Let's try that out. We're going to say we copy the component and you go to card holder. And we now go to the three little dots and say Paste Component. As New. As you can see the boxes a bit bigger, but that's okay. The box collider on the cart can be destroyed or removed. So we go on to the little three dots and say remove components. Now the card holders, the one who is responsible for the inputs of our re-cast. We now want to do, since we know the size of the actual card is going to be 0.1. We can also say scale is equal to 0.1. But as you can see, that is the wrong one. We want to make sure that we only do this inside the box collider. So we're going to put in 0.1 of we can't see or you can't see the box collider itself. You can deactivate the card for a second, like using an eye symbol here in the front. So in that case, we can go and activate or deactivate on drinks, but not directly. It's just a visual for our scene view. As you can see, the game view is not involved. It's just for us helping out to see what we have actually changed or if everything is correct at the correct position. In the game manager or in this case in the player input script, the card is not accessible for us anymore because the next object we are going to hit over here does not contain an animator component. Means in player input, this is not actually possible anymore. Well, we would need to get, is now the current, because the current is the one who's responsible later on for the animator component to flip open. Let's try that out. First off, in card, we need to have another public void. And we're going to put in a function called flip open. And we can, for example, say true or false as being a Boolean input. So we can say on or flipped. In that case, we can say if flipped is basically true. We want to call the animators component animation. So we say and'm dot, set, Bool, open, close parentheses. And then here we now say flipped open. Don't forget this is the naming for the actual animator Boolean, which we have set inside the animator component. And then we say whatever flipped us. So in that case, we don't even need to use this if statement because we can directly take input of land. So we just say whatever this is going to give us. If we say flip this one open, then the animation will be sad. If we later on say flip open as equal to false, then of course the animator will automatically be responsible for that. Hit Control S to save. And now in our player input, we can say we want to get the card components. So hit dot transform dot gets component of type card. And then here open, close parentheses dot. And here we have our flip open function. And in that case we can say true since it requests a true or false. Of course later on, the same thing is going to happen whenever we want to close all these cards. This is just again for testing purposes. Later on we're going to do a bit of a different construct since we don't know how much has been opened yet. Don't forget to let the compiler run. And it now tells us in currency as we have an little arrow over here, meaning it is requesting a semicolon in this end, don't forget to save and let's go back. So if you have any compiler errors, you're going to see this instantly inside the console. This is important because, or in this case the code, it is important that the console is constantly open to see any mistakes you have done beforehand. Don't forget to save the scene as well at anytime. And now let's try if we can open still the card by even if we have changed all the code. Now whenever I hit this card, you're going to see the card holder as the one we were no hitting because the box collider has been sent to be on top of the card holder. The card itself is reading the animator component or acid or CARTO that talks to the animator component by using the little card script, which we called in here to flip open whenever we send in another argument like a force, Let's look closest to cart if it is not flipped closed already. And later on when we create a game fields like our complete life, you'd, no matter how high and how much we want to implement over there, we can go and use this set card function for this one. Also, again, we later on can flip close this one. We can use the same function. Just go and put in a false argument, as I explained again. Once again, the animator now knows it. We can also give it by hand and then put over here to flip close. And if I touch that again, I can do the same thing. Pretty good. Now, our card is literally set up to be useful for our memory game. 12. #12 Updating Card Prefab: Welcome back to the course. In this part, we want to update the actual prefab since we have done several changes code wise as well as your concept or component wise. To update the prefab, we have the possibility to select a card holder prefab itself. And then we see an override it over here. As you can see it, we have the term changes onto. We added the component box collider, and Saturdays on up, we added a script component and then the card, we got rid of the box collider. We want to say apply all. Now everything should be updated correctly inside the prefab itself. We can see now the prefab has no the box collider. When we double-click to open, we can also check that the card has still its animator component. The card holder has no the script as well as all the corresponding animator and the sprite renderer for the Card Front connected to it. When we now go and duplicate this card, for example, multiple times. Basically, it doesn't matter how many we're going to put in here. We can press Play and test out if all the cards are going to react separately. For example, I select the one in the back. You're going to see it's popping open. I can do this for any of them. Pretty good. So now we have an input system and we're flipping cards in which we can do a check. 13. #13 The Card Manager 1: Welcome back to the course. In this part, we want to start to create our card, manage them. So whenever the game is going to start, we're going to call the card manager who is going to create a play field for us. Also, it is going to be responsible for actually managing, checking the Paris as well as all the other ones over here as well. Also, it going to be making sure that the sprite on the cards are going to be set correctly. So let's start with that. First off, we go to our scripts folder and create a new C-sharp script called card manager. You can name this again however you please. And like, I just like the name card manager. Once the compilers done running, we double-click to open this one. And MonoDevelop or Visual Studio. Once the card manager has been loaded, we're going to get rid of this, the update loop because we currently don't need us. We only need to go over laid on and use the start method or start function. So first and foremost, we want to know about all the sprites which we can use. Also, we want to have a number, how many parents we want to lay out on the playfield. So in that case, we can give some numbers out. Also, we can define the pairs if we want to, not by number, but probably will buy this bright amount we are going to use. Both of them are possible solutions for this. What I want to go for is I want to create a public int amount. So the paramount is going to be the center or the possible amount to place cards into the playfield. The next one is, we need to know which sprites we are able to pick from. In our case, we're going to create a public list or an array Bose is going to work. Probably we're going to go for Sprite array, which is handling or probably had to be handled easier. An array is declared by square parentheses behind the actual type. Then we can give it a name, something like sprite list or sprite array, or just sprites. Once again, you can name this whatever you want to name it too. So now we have a paramount and a sprite list. In the sprite list we're going to lay it on, put all the sprites like all the card fronts into this list or array, which can be picked from whenever we start to create the play field. Now what we wanna do is we want to have an extra value of a here, which is of type float. I'm going to make it public, or actually we don't need to do this public. Let's make it private. It's going to be just a float and I name this one offset. This offset is going to be for creating the play field for us. You can differentiate between the x and y offset. In our case, it's going to be the accents as that offset, or we just use one single offset. The offset is representing the distance between the first tile as well as to on the, to the second tile, or in this case card to be created in a row or in a column. So that is going to be necessary for creating our actual play field. Once again, if you don't know what things are going to be for all, you probably are able to forget them. You can commend things out by taking two slashes on this case backslashes. So hit Shift and actually create one of them. Feels when you press the seven on the keyboard. So you can, for example, put in a, just an argument over here or just any note about this particular actual variable if you want to offset between the cards. Again, we don't really need to do this. We can also use a vector to, as an example of a 12 or vectors radio anything other thing which can hold floats in a particular manner. So what we wanna do is we want to create the playfield with all these components. In that case, we want to make sure that we instantiate cards. And to do so, we also need the card prefab. So we say public Game Object Card prefab. We're going to drag this one in a later on. That means we're going to drag the car prefab and we're going to instantiate this one from a prefab of which again is going to be a template. Then we fill in all the corresponding numbers, like the current ID, as well as a corresponding sprite. So later on we're going to pick this by using maybe some numbers or whatever and probably randomized that as well to pick from. And then we're going to create the scar prefab and send in the sprite into the card front of the sprite renderer as we already created over here. So what we just do is we call the oral creators and down we call this set cart function, pass over the corresponding ID as well as the corresponding sprite. And that's basically everything we need to do later on for creating the actual play field. But that's what we're going to start with in the next video. 14. #14 The Card Manager 2: Welcome back to the course. In this part we're gonna go and create our playfield. So please open a PR D card manager script. First off, I wanted to create a function for the art because it's easier to handle and probability we need to let say, reshuffled things here and there. So we want to make use of that. So in that case, we first need to put in all these cards, actually shuffle the list later on or shuffled all the cards. But we can also do this like on the Rotten, like whenever we want to. We can also shuffle that. First off, like that, we're going to create the cards first. We shuffled the sprites in between the tiles we have, actually, we had choose from. But let's start at the very beginning. We create a type void function, which is going to be our creates playfield function. Create playfield, trying to name your functions, however, on whatever they do. So you never lose track or again, Command things out, like putting some extras may be in front or in the bottom, or maybe it directly in between or behind, wherever you place in like to commend things out. Now, what we can do is we actually want to take the paramount as being our first parameter, which is going to be our, um, actual amount, how often we want to loop through something to get things from. So in that case, we're going to create a four or a for each loop. In my case, I would use a for loop since we can control the loops better than with a for each loop. Also, a foreach loop does not contain any integer parameter like the paramount we need. So in Max we're going to pass it in the pair amount. How often do we want to loop through? Now move on to pink as actually one of the sprites. In our case, we can just go top to bottom, like as we start at element 0 over here and use that. So I represent just element 0 in our case. What does it mean now? I can also be our ID for the card and the same for the sprite list over here. Again, we can also randomize stuff later on, but let's start with creating the playfield at the very beginning. So we're going to count I up until we hit the pair amount minus1. That truly is since we do not go and check for the same amount, since we are starting at 0, we could also start at one or at any other number, doesn't really matter. But for the moment, let's start, let's start over here at element 0. So now per each loop, what we wanna do is we wanna create a new card on the play field and we give it a position on the playfield. And depending on the paramount, we probably also want to reorganize or rearrange these cards directly on the playfield. That means, for example, if we are talking about a pair amount of 4, we probably want to create a playfield eight by two, since four are going to land in the first place and four are going to be in the second place. We can also do this like any other way. Like if there is a four-by-four field, we know how many cards we're going to have on the Playford playfield directly. How do we do that? At first? First, we're going to say we create a vector, a vector three in this case, which is going to represent the position where we want to start to create that complete stuff. So we create a new vector 3, I name it p for position is going to be a new vector 3. And then when we want to pass in over here, is the x coordinate is going to be our eye times. And now we can differentiate between things and we can also open to other Bros., but that's what we're going to take care of it later on. So we say i times and I again is going to be the current number over here. Then we can say in the world specs airspace access, we can start at 0. We can also use the position of the cart manager or any other game object as being the base position x value. So let's start at 0 in the y axis, which is going to be the upward axis. We want to stay at 0, and then we have the z axis for the data exists. We can do again some different calculations over here, but we're going to go for, let's say, always 0. So everyone will be no lined up. Well, we haven't done yet is the actual offset. So in our case, we're going to take the I and we can multiply the i by the offset. So I, if I is a 0, then we take the 0. If I is one, we take 1 times of cent. So the offset is going to hop to the right. In this particular case on the x-axis. Again later on we can also do this for the zed axis. We'll get there. Now since we do have this position, we can instantiate our object. So we can say Game Object, new card. We can name this literally whatever we wanted to instantiate. And now we can pass in first, what do we want to instantiate? We want to want instantiate a car Prefab. The next one is going to be the position of the object. So we can say pos, which is the new position we have calculated beforehand. And now we're gonna go for the rotation. In our case, quaternion dot identity. Quaternion dot identity means it's taking the rotation of the prefab. Well, it should. Now since we have done that, we now need to talk to the new card and give it all it's new parameters. So we can say new card dot gets component. And you probably guessed it right. We wanna take the card component directly on top of it. Now we can pass in all the parameters by calling set card, the function which we have already created over here. So now we need to pass in the ID as well as this bright. So that means we can now go four and say, okay, the ID is going to be I, which is the current index. And then we can pass over any sprite from the list. In our case, we can say sprite list in square brackets. I. So that means we just take whatever the current indexes and recreate the playfield. But now you see probably the problem. We do not create two of the same card. We only create one of the same card. So in that case, per each iteration over here, creating those two cards, because we are creating them per patient per amount. We need to do this twice. In that case, we create another for loop directly in here. Use the letter J and just put a two in here. We start at 0, so we go from 01, but we never touch two. In that case, we're going to do all the things twice. What we now have is another issue. All the pairs of cards will land automatically, again on top of each other. So we need to recalculate the offset over here, or in this case the ACS position. But let's test this one out just so we get a feeling or you get a feeling, what we really do over here. In the start method, we call Create Point field, open-close parentheses, and close the line with the semicolon. And don't forget to hit save control S however you please. And like what I do now is I get rid of my card holder directly from the scene after the compiler is done running. Because we don't need this anymore in the scene. And we're gonna take our game manager object and put the card manager on top of it. What you now can see is that we can set, let's say, a paramount of four. And we can put a now a list of sprites directly into the US. To do so, we can go to our Textures folder and pick all of them cards from one to 14. In my case, for an easier handling, we can make use of this little lock symbol. So we locked the inspector and we don't lose track whenever we select one of them images you can see we just lose track. So we take the lock symbol, we lock the actual spectrum. We select all the water or underwater set tiles and drag them directly on top of the name of the sprite list. And all of them will be just inside. As you can see, it has a size of 10 and starts at element 0 and ends at element nine. This is totally usual for actually lists and arrays. Now the last thing is what we need is the prefab of the card holder, which we have to pass in at the very bottom over here. Just drag it in. Don't forget to save the scene if something is weirdly happening over there, you want to be prepared and wanted to have everything you have done so far being saved. Control S again, is a quick Save. If I now press play, I should see four stacks of cards next to each other from left to right. Why don't I see the force text next to each other. You ask, well, we haven't said the card offset. We just kept it at 0. But as you can see now, each of these cards now have different visuals. So the first one is the star, the second one is the star. The third one is going to be any other one, whichever is next in the sprite list. In this case, it's the sea horse. And the next one should be the another seahorse. Then we're going to have a ray. And we should have the next one should be also a ray. And these two should be the clown fissures. So as you can see, all of these cards are now created two times because of the second for loop. And God created all on top of each other. To avoid putting them all on top of each other, we're going to give the offset a little number. We should say something like 1, let's say 2. One is the distance between the two pivot points in the center of the card holder. And point 2 is going to be like 20 centimeters between the two cards. Let's try that out right now. We should end up again now, or finally, with a stack of four cards above each other, which are containing or holding all the Paris above each other. So as you can see, these are going to be the ones which are actually available. I can now take every second card in the hierarchy panel, drag them up. And as you can see, all of them are now on top of each other. What we wanna do is we want to put them like code-wise, let's say above or below. So we can laid on also shuffled them so the users don't have a too easy to play it again later on. 15. #15 The Card Manager 3: Welcome back to the course. In this part, we want to continue working on our creation of the playfield. In our case, we want to do it maybe a bit different than we just saw the actual code working only kind of, in our case, we want to implement a shuffle method. And after shuffling, then we want to bring the cards onto the playfield. So let's take a look into it. First off, we need to create a list of objects which is going to hold all our new created cards so we can shuffle them around by its index. So in that case, we create a list. A list is a dynamic array, I would say, which we can sort by any means and at any time we want to, the type is going to be written in those triangle brackets. And in this case it's a game object. So all our new cards are going to land into this list of type gameObject. This is going to be, let's say our card deck, if you wanted to name it like that. And we instead we initialize that already with being a new list of type gameObject, open, close parentheses, and close the line with a semicolon. If you want to, you can make this one public so you can see the actual effect of the last shuffle. But at the moment we just don't. We can also light on DBA that at any time we want. Now, when we go and create our play feel that the first place we create her actual paramount goal by two, and then we position them. Let's go through the actual positioning. In that case, I just comment this stuff out of here or baby, we just don't fit anymore. In that case, we can say our position should be always at one specific physician. For example, a vector three, don't 0, so is 0, this one out in the world space OT, at the point 0, 0, 000. From that point, we later on have them all on 1. What we can do now is we can add the instantiated card. I mean, we have the ID for this card set already by the parameter I. And we gave it any sprite, at least not a random, but we gave it as right. Or we have the final step in this second for loop is we want to add it to the card deck. So we can say card deck dot add and then open, close parentheses. We're going to pass over the new card. Now we have that, this card deck, or we now can do as a final step, we can go and shuffle the card deck because beforehand it is going to be assorted DAG. Now we need to go and shuffle our actual card deck. Otherwise, it's going to be sorted in the way we were creating all the cards. And that case, we create another card or a for loop over here. We put it in an argument above it. So we can say we're going to shuffle this new list over here. We can again use letter I here. It doesn't really matter since this loop is already completed at the point where we close the parentheses. Now, max should be card deck amount, so card deck dot count. Now we're going to loop through that and randomize the actual index from the currently picked item to any temporary pecked index. So per each iteration we create a new random index is equal to random dot range between two numbers. The first number is 0, the second one is the length of the list, so we cannot under or overdo it. And that case, that means we take, again card deck dot count. The count is usually higher than the last element in the list. Botulinum dot range reduces full numbers by one at the second parameter over here. So it will never reach the maximum length of the card deck. If that would happen, we would need to negate this number since the last element in that list will be, well, one number lower than the actual amount in the list. Same for arrays, by the way. Now, we created a new random n Next, and now we can take our current looped item and put this in to any of the other indexes to literally shuffled that around. And then when we take the other one and store this in a temporary way actually or wherever we want and however we want to handle that. So what we need to do now is we need to say the item on our current and nice, We're just going to be index I. So we say a card deck in square brackets I is now going to be the position of the index. So it can say cardiac in square brackets, index, but in our case it needs to be the opposite. So the card deck in length is going to become the card in our current actual slot over here. So we can shuffle the deck based on that. We only do this by the current card deck amount. We could also define any lag, actually any kind of randomized number of here by implementing another extra for loop inside of this one. But that is a super-simple shuffle. So each college probably lens onto another position. And the last thing we wanna do is we want to pass out or actual cards on the field. So they are all selectable or actually, yeah, returnable by this means. 16. #16 The Card Manager 4: Welcome back to the course and this part we want to lay out our actual cards onto the playfield. We have multiple possibilities to lay it out automatically. We can also define the size of the grid we want to see. To define the sign is we need to create two integers. We can also use vector 2, but integer probably makes it a bit easier over here. So in that case, we create a new public int of the width of the playfield, which is going to be phone numbers. Like for example, we want to have the full size on the phone numbers at all. We can also say it's only one. We can also define a public int, height of the playfield, which can be any number. Literally. All we want to know on what we wanna do actually is that all the cardiac or in this case the paramount is going to match either the width and the height or both of them. Since this needs to be doubled by two. So this number's actually need to be this times that should fit the pair amount or at least should be higher. So we probably cannot check this directly, but what we can do as Meanwhile, doing this one as an input, we can give out an error message that width times height is not or is actually higher or high enough, higher than PMA are paramount times 2. Otherwise it would be returned false or something like that. We probably give out an error message. But let's keep it as is to pass out the cards right now, we can do multiple things. We can do this directly and place them onto a position directly after creating the playfield. First off, we want to know how high or how our biggest apply fields. So we take the width of the playfield that the first place. Then we want to do the same for the y-axis or the z-axis in our case. So that is going to be in our case, the height of the playfield. If you want to rename eye of a here, you can easily do this. So you can say this is Acts, does this acts and does a sac. So this is like from left to right. And the height over here is going to be this height. I just said a typo. So height is going to be over that axis. So the forward axis acts as left and right way based on the world axis. So each time we hit one or the other, we want to first of going first, literally row or in this case column on AKS. And then we iterate through all of the ones into the height. If you want to start with the height first and then take the width, that should work as well. So we just go and put the height FOR loop inside the, actually the width follow-up inside the height follow-up. But none of that, it doesn't really matter. What we wanna do now is we want to go off and create over pairs of our cards directly on the playfield shuffled beforehand. So what we wanna do is we just place them at a position by taking the actual vector offset based on widths and heights. So we were creating a physician before handle, we just screwed it because we didn't use the direct deal of the day. Next case we're going to create a new vector 3 us for physician is going to be equal to a new vector 3. Now we need to define where we want to apply this. So the first one, the first one item is going to be on position x times the offset. Then and why we don't change anything. And then we wanna take the zed value, so z times height, or actually not height, but the actual offset. So this is going to be our positioning. So if Ax is 0, 0 times something is always returning 0. So we start at position 0. We can put in any other vector and from the vet like the position of any object. And then we add the accent, something like that to it as an example, same for the zed value of that is 00 times offset as a returning 0. If it is one, it's one times offset, and so on. Now we want to loop through our all. We want to take our actual card and place this directly over here. We're going to implement an integer number. So in num is starting at index 0. So this is going to be the number in our garden next, well, we're now going to do is we can take our actual card deck in square brackets, num and not 0, but num. Of course we don't need to go and implement number by one. So we can say here num plus plus. So we iterate through each of them. Well, hopefully. And then we're going to say we want to change the transform of this object. So we say transponder position as equal to 0 s. Now we increment num and in the next iteration, num is not 0 anymore, it's going to be one. So the card and next one inside our card, this literally is going to get the next position, which is going to be ax1, that the row times the offset. Don't forget to save. And let's take a look how that is going to look. First things first, we need to make sure that the compiler is no issues and no errors in our coding behavior. We will now take a look into width and height. So again, if we have a paramount for our size of the width and the height is probably too. Then because two-by-two is going to represent four. But since we have a pair of mound, 4 by 2 is going to be a ight. So in that case we want to take four by two as being playfield. Let's hit Play and see what's happening. As you can see, the field is kinda created once something is really went wrong. So what we do have now is the iteration of a width which is 0, the height is going to be two, but the waste is actually four. So at the first place was started correctly at this point, but the other ones are kind of missing. Let's see how much do we have over here? We can count them 12345, and as you can see, there are two above each other. So there's one hidden over here and probably one hidden over the since we going to have a little issue where we are not performing the dank positioning correctly, we need to get back one step into the shuffle since stat is going to be a bit wrong at this point. So first off, what we did is we just placed our current Indian banks and number and replace it with AI, which in general would be correct. But what would happen at the same time was I well, we don't know. And since that is the issue, we're going to rewrite the code a bit. So first off, instead of Kardon, next, we're going to pass in a new variable and just name this one temp. In temp, we store whatever the current index i card ism which we are currently add. Then once we have stored this information, we update I, since we have stored whatever currently is at i. So it's a card deck. I is going to be equal to cardiac. And now we're going to pass over the rolled index. So the N9 see random number, the random value of a here. And since we did this, the index currently is empty. So we need to say a car decks in square brackets, n dx. And now we update this one, which whatever has been performed, it I, in this case, it's going to be temp. So temp again is our temporary data over here. Don't forget to save and let's get back into the game energy. And I do two settings or changes things changes because it was debugging that and trying to find our actual issue at this point. So we're going to pass a no, I'm going to pass in a foreign the two, since 4 times 4, 2 times 4 is actually eight. Let's see what's happening and our plane is over here. As you can see now, I will play field is four by two and its size. And when we look from the bottom in our scenario, you can see our playfield is shuffled. We can repeat this estab Hawaiians again and see if the playfield is going to change. So what you can also do is that any time you can do a little screenshot using your favorite screenshot tool. Going to put this onto the side. And once I hit Shuffle again or actually want to create a new play field over here, I want to see then we have shuffled field. And as you can tell, each of the cards which have been picked before are still the same, but they are on different positions. Pretty good. So now placing them with some numbers is going to be working in our little playfield. 17. #17 Error Checking Playfield: Welcome back to the course. And this one we want to actually do a little arrow on chunking in which we are going to calculate the height times the width and see if paramount times 2 is going to be higher or lower. To do that, we create a new void on draw gizmos function. This is just a helper for us to see if we have done any weird or wrong numbers. Instead of using editor scripting directly to tank or let say update this number, we just want to go and use on drug is most just to show an error message. In that case, we can say is pair amounts times two is bigger than width times height. We want to pass out a little debug line. So we can say debug dot log. And then we can put in some war warning with some color-coding and something like that. We can say arrow width times height should be pair. Amount times two. Forget to close the line with a semicolon. Also, clean it up as much as you want. Don't forget to hit Save. And let's see what's happening in the console. So that the compiler run and see if something is happening in the console. But as you can see, well, we don't get any console arrows bond. Once I change this number to be a string, you're going to see error width times height should be paramount times 2. So that means if that is going to be five over here and I clear the console, 5 is not going to trigger. So in that case, we can still create the playfield five times two. That case it would be an uneven number. So in that case, we probably should go and see if there are 100%. Otherwise we would have, as you can see, an argument out of range exception. So in that case we're going to say something like if that is not equal, that, so we're going to say if paramount times 2 is not equal to width times height, you're going to see the error message at this point. So we don't get any weird argument out of range. Exception arose later on. So it tells us now this is wrong, but if I take 8 times 1, clear the console, you can see everything is good. Since eight times one is 88 times or four times two is also aid if height would be 0 at this point, so a times 0 is 0. So that wouldn't create a game field for us or just a weird stack on top of each other or even nothing. So for all, the force would be the result, or four times two should be the result of the width times the height. So we only have 4 times 2 or 1 times 8 to fend the paramount for. Don't forget to save. And we're good to go with some little error checking at this point. 18. #18 Camera Setting: Welcome to the course. In this part I want to add one more arrow tank and then we're going to start to create the gaming mechanics. So first of all, we do is once again is not the same, then we get a debug log error over here. And what we also want to check if our actual paramount times 2, or actually paramount is bigger than the actual sprite amount. So in that case, if that paramount is bigger than our sprite list dot count on this case, since it is an array, going to call the cold the length of the array. So the paramount is bigger than a stride length array. We know we cannot do this because you don't have enough sprites. And the last so we can say is right list or in this case a direct line first. So it's a debug log. Too much pairs or something like that. Since this sprite list again, only covers a specific number. So what does it mean is when ever we are going back and to the game or into a war. Game manager or senior manager. When you select the Game Manager and let's say we pick a live 11, you're going to see too much pairs over here as well as of course, the secondary era, which is going to be about the width. So that in total means we have too much parents because that doesn't match or less if we pick an aid, this is good. We can clear the console. We still get some areas which are going to be representing by this one. So 4 times 4 is going to be equal to the eight over here. So 4 times 4 should be 16, and 8 by 2 is going to be 16 as well. When we clear the console, we don't see any arrow, and we should also see IE6 or an eight by eight field somewhere over here as you can see, four by four and my case Of course, So eight and top eight and the bottom, and we're going to go downwards. We can see this resin mixed playfield. So the players can now literally go and select all of them cards over here and literally opened up by clicking. But that's not really what we want. So what I want to want to do is first I want to manage the camera. So meaning that the camera is kind of in the center and NADH as we are rotated as it currently is. So in that case, we going to take a look into the camera itself. It's for me, kind of weird. So if I want to say look from this perspective onto the game view, I can take the camera once again, I'm currently in play mode. Don't forget this. I'm going to say move to view. No, I do Align With View. So now I can see the camera kind of the angle I want it to be. Of course, I need to do some changes. Once we leave the playfield, we would leave or we lose the camera setting at the current place. So what we can do is we can go to this transform and say, copy all the components of that. So we want to copy the complete component. Once we now select the main camera again, we can say Paste Component Values. Now we should have the same view as we had when we were in play mode. So meaning, whenever we are in play mode and go back, we lose everything we have done as the changes over here. So again, now we can refund around. We can set this one to be more like, as I say, he probably in the center of most of the leftmost right away, however you please like. And if you don't like this where you can also go in the top view or a slide to view and so on and so forth. Try to center it in a way you want to light on. There will be some issues with the camera since the fields can have different sizes, of course. So, but for the moment I again copy the component. Hit stamp, select the main camera, and paste the component values. Pressing clay against should give me wherever my scene view has been. Well, whenever I have copied that. So now the players should be able to open all the carriers and see also the car fronts being rotated in the correct way in the player direction. Now, we need to enter or create the gaming mechanics and which we compare the first input with the second input. And if they match, we keep them open. Do play some effects if we want to, and we keep them open all we destroy them from the playfield. There are multiple possibilities to do that, but that's what we're going to stay or start work with in the next video. 19. #19 Choose only 2 Cards: Welcome back to the course. In this part, we want to go a bit further into our game. What we wanna do is we want to now see which are the sunlight ID cards. And meanwhile we do have one onto selected that we do not allow input, as well as see how we can manage to check against each other. So first off, let's go and open our little card Manager script, which currently is not big. So I collapse these things because we are now creating new stuff. So I make a little command over here. So this is going to be game mechanics or game mechanic parts. If you don't like to do this in a card manager, you literally can do this where ever you want. You can create a new, complete, new, complete new game script as an example. So we don't need to manage averaging of this point over here. You know what, why don't we do this? So in that case, I go and create a new script. And maybe we call this game manager. So create a new C subscript and call this manager. Since that is going to manage the game if we want, if we lose and we can also can handle this probably a bit easier. So we are not crowded was a lot of code and probably that is it for us later on to handle all the rest of that. Double-click to open the game manager and MonoDevelop of Visual Studio or whatever you're working with. In-game energy for the moment we get rid of start and update. All we need is actually two things. The first thing is we need to know which cards do we have selected. So we create a new list as a big L of type card. So we know which card 3.5 actually packed. So we can say picked cards. And of course in internationalized that to be a new list of type card open, close parentheses, and close the line with the semicolon. So whenever we pick a card, we want to add the picked cars to the game manager. To do that, we need to have an instant access to the game manager. So let's create this 1 first. We need to do is we need to create something called a singleton. Singleton is going to be a public static game manager instance we need to define first. So now we need to make sure that this instance is the only game manager instance and the game. So we can simply do this by putting this one into the awake function. Awake is going to be the unity provided function which happens before the start function in that order. And awake, we just say incidence is equal to this. We just need to make sure that we don't have a second game manager script inside our scene later on. So whenever we want to talk to the game manager, we need to call the game manager dot instance. And then we can talk any public parameters as well as public scripts or even functions. So now we want to add to the pig cards list and then Keynes, we create a new public void, add card to picked, picked list and close parentheses. And then here we take the card as being our card. So we're going to take this. What we wanna do is we say he picked card or pick the card stock to add. And what do we want to enter the SD card? We're going to pass into this function Pretty good ones. Or whenever we have added this one over here, we can do a check. We can check how beggars dad and how much can we put in. Also, we can say we have chosen or picked a card or two already. So we cannot do any furthermore inputs by selecting other cards on the playfield. So for that purpose, we can create a little ball. We're just just a private bot. The bot only returns true or false. And we say something like pink. So this represents we can put an argument or any description behind it. Tanks or actually set this true if we have two chords selected or actually packed. So, and whenever we try to pick a card, we can request again Manager first by doing this input like the mouse clank first and see if we have picked enough already. So now k is we create another helper function which is a type of return bool. So we actually just return whatever bull is. So we say get or read picked. We just want to return packed in this case. So we can say return picked. So any function which is requesting respect or get panicked, or we'll name it whatever you want, we'll return whatever the state is. So if the card amount in our picked cards list is going to be actually two, then we can return true at this point, at the next, try to actually do an input. So what we can say now is as picked or actually if the actual picked cards dot counts is equal to two. We can do this things we can set picked to be equal to true. So we know we have picked and off courts. Also that is the case. We can do. Start our actual chunk, chunk if we have a match over here. So whenever we now do and flip open a card by doing our actual input inside the player input. We first of 10 see if we are pressing the mouse button, end. The game manager dot instance, dot, read picked as false. So we need to negate us and put a exclamation mark in front of that if we have not read packed. Or let's rename this function because it's actually kind of kind of wrong. Has picked. So if we are doing our input and we say, if we had pegged as not true, but it is going to be false them we are able to turn around one of the next cards. So the next step, we just need to go to our game manager object over here. We can put as many scripts as we want to on top of it. We can also separate them totally up to you. If you by the way, I forgot to take away the little lock symbol, you better shirt. Now I take the game manager script over here and put it on top of it. Let's try out if we can only switch around two of them cards, I'm going to pick one. I'm going to pick two. And now I tried to pick a second or third one bond, as you can see, doesn't really return what it should do. Probably I haven't saved the actual function. Why don't we see any of that is we do not call add card to pick list. So in that case, we need to go again into our player input. And once we are shooting the rain and actually flip open the card, we also need to update the game manager so he's a game and legitimate instance, not add card to the pick list, open, close parentheses, and then we pass in the current card we have actually selected. In that case, we're going to take hit Transform, don't actually this component of type card. Since we now need to do two things to this card, it's better to catch it. So we can say a card, current card is equal to, and now we take this complete part hits to transform.com dot card and cut it out Control X, Control V to put in. So we grab it first. Now we can say current card dot flip open. And we want to add the current card to be added to our game manager list. Let's try again. Don't forget to save everything. Let the compiler run, see if there are any issues and what's happening. Let's press play and see what's happening after we select the smart card. So first guards second card. And the third one is not pickle anymore because picked is no actually being true predicate. That's what we wanted. So we are one step further into our complete game. 20. #20 Checking for a Match: Welcome back to the course. In this point, we want to chunk if we found a match or not. But we also need to give ourself a bit of a time before we do the check, before the actual animation or flipping the card open is actually done. So in that case, we can make use of a co-routine. So we go and open our game manager script. And in here we want to start a co-routine to check if we have a match. If we actually found two cards, I'm going to close this little ball in and close the other ones so we see better what we're actually doing. Probably I'm going to put the slide in between where this has picked is going to be. It doesn't really matter at this point. So a coroutine is created by creating an IEE numerator. And it's basically a time-based function. So we have 2 or we can give it a wait until time has happened, whatever, or wait for another, let's say co-routine. Before we go forward. In our case, we want to actually check the result or tag match. Do we have met or not? Before we continue, we want to see why this arrow comes. This arrow means we don't pass back UNI, or any of the code passes don't back, don't pass back any kind of a result. To pass back any type of result, we need to use the yield statement. So then we're going to go and say yield, return new. Wait four seconds. If you have typos, everything is going to blink red and green, stuff like that. So try to be as precise as possible. So as you can see, we wait four seconds and in my case, I, my animation to open or flip open the card is about 1 second, so I give it a bit more and maybe 1.5 off before I do the axle check. So 1.5 is a second. So 1.5 seconds that we're going to start to do an actual check. So what do we actually want to jack is rather simple. We want to take all the cards picked one and pick two and compare the IDs of them. So we can literally say is pick guards in square brackets 0, which is the zeros element in the list, don't ID. And now we have an issue. We don't know what the idea of the card is going to be because the current ID is not accessible for us. So in that case, in the current script, we're going to add a little helper for that. We could also set up a getter and setter of the, but I just want to return it by using the function. So the function of type int, since the card ID we want to return is also of type int, we can say get card ID, open, close parentheses, open close curly brace. And what we wanna do is we want to return the actual current ID of the script. Don't forget to save the card script and let's head back to the game manager. Now, we want to grab the gas card ID from this little car, from the first card in this lattice is going to be 0. And we want to get this one as its size. The gift card ID is not going to be a bull since we want to compare this with something. So in that case, we can say if our first item is equal to our second item inside the list, we can do the same here, but we need to make sure that this one is going to be a one over here, the first element, so the zeros element and the first element, these are the two we want to compare. So the first pig card and the second card. If that is true, then we know we have a match. I'm going to comment this one out. So I say we have a match. If we don't have a match, we wanna do different things which are going to come afterwards. So if we have a match, we wanna get points. We want to play a firework we want to do, I don't know, an applause. We want to get score all of that, and so on and so forth. We probably also want to get rid of the cards. All of that is now going to happen at this point. Also, whatever comes be like after this one should not be computed at this point, since probably it's not needed. On that case, what we can do is we can put an else if statement if they don't match or just an else statement and then it will be skipped. And then at the very, very last, we're going to clean up everything. Kinda make another command over here. We can say clean up. So clean up just means a different thing, two different scenarios. So in our case we can say picked is equal to false, so we can pick new. But also we want to like flip back if they are the wrong cards, but they are coming over here. Like the cleanup for the moment as paint to be false so we can reset it to no mother cards at this point. For now, seeing what does the actual manage. We don't want to touch these cards anymore, but what we wanna do is we want to clear the list. And since clearing the list is also part of the cleanup, we don't want to do this in here or even in here, but we want to do this also in the clean up. So we can say picked cards, top clear. So we empty this one out and we can put a new cards whenever we pick them. If we do have a match, we don't care about them again, we just can count up some score and so on and so forth. Also, we probably 12 cent the cards to be not packable anymore, so send back something to the cards. Once again, we can also disable them cards. So in that case we can say pick cards to 0, 1 or 0 and 1 dot gameObject dot, actually set active to be false. Let's try that. Pick cards in square bracket 0. We could also look through them. I don't know what's faster, but in that case we can say gameObject dot set active to be false. And we also want to do this for the second one, I guess copy this line and put this over here. So we go and deactivate the zeros element, the first element, then we sent picked to be false and clear the pig cards list. Now, whenever we are not having a match, we want to flip all of them back. So again, we can talk to them directly in here. But in that case, we need to set the animators component to actually, to flip open and setters wanted to be false. Since we have prepared this one already, we can put this into the game manager here as well. So we can literally copy this piece over here again. So we say pick card, Don't flip open. And then we pass in a false. So we can close this one card. I'm again do the same for the second card as well. Once everything has been ended, we want to wait until these flip cards are really flipped. So we wanna make sure that we yield another wait four seconds of here in between before we can do the next input. So thanks at least three seconds in total to clear or check for the complete match. The final step is we want to actually start this co-routine wherever we want to pick this after adding the card. But again, we only wanna do is whenever we have two inside the pig cards list. So what we can now do is we can say start coroutine, open close parentheses, and then we can say Check, patch, open, close parentheses again and close the line with a semicolon. Now, don't forget to save again. See if any of the other ones are needing any save. And let's see if the console has any issues for us, which we probably built in by mistake. No mistakes. Popping up pretty good. If you have any mistake, start to debug or rollback, of course, in tight code, Let's try to pick two open. And I can see they're both our closing again automatically. If I have two sharks, they disappear. You can see we just selling them deactivated so they're still inside the scene, but we cannot touch them anymore, which is good. So now we can go for the other ones. Meanwhile, they are opening of a here we cannot do anything. Also, there's a little delay I would say in between, like whenever we have a match that after this one particular time, we do not have a possibility to input like after they got like this directly deactivated of here. We don't see any or we cannot do any input. We need to wait until the timer has really done over day. So probably we find a way to optimize that a bit. We can now try to check all of these. And pretty good so far. 21. #21 Checking for Win: Welcome back to the course. In this part, we want to clean up a bit or actually salt on things out and probably also reduce the flood back to close time or actually give the player even further access to the next term. So what we wanna do is we want to take the yield return statement of a here and put this into the Flip back or flip open. Why do we wanna do this? I just copied an empty line now, no problem. Why do we wanna do this in here, but not in here, is, well, whenever we deactivate them, we do not wait or need to wait 1.5 seconds to flip. Close them actually. So they do not have to appear over here, but we only weighed whenever we close the app. So cards because we didn't add i corresponding match, the rest is going to stay the same and everything is good to go. The next one is we want to know, have we one already? So we want to check for when I create the new void. Check for when I'm close parentheses and open close curly brace. How do we know if we have actually won the game? Well, the first and foremost thing is whenever we clear a match, we get cleared match. So we can count these up. In the card manager. We know how much pairs we do have. So in that case, we can compare actually the paramount times the already, unlike times 2 or probably not even to just against the paramount inside the actual card manager. So, but what we need to do is we need to grab this number to get it anyhow into the game manager. What we can do is we can flush the data on GameStart directly from the paramount in to the game manager. Since that has an accessible instance for us. So, meaning first, we're going to create a new end over here. I'll just name it one pairs. And we create a public accessor for that, like this boolean over here. But in that case we do not return of all, we just want to grab information. And that case we want to set pairs, open, close parentheses. And what we want to put in here has an actual integer. So the integer of the current pair amount like that. Well, we want to set this now this pairs to be the incoming paramount. We say pairs is equal to Paramount. Don't forget to save. Let's go back to the card manager and then start like before or after. Doesn't really matter. Let's say before we create the playfield, we sent the game manager the information about the playfield. So again say playfield dot instance dot set pairs. And then we pass over the pairs amount. On this case paramount. Now we have the information inside the game manager, and now we need to have a counter. I'm going to create another end. We can name it maybe pair counter. So we can increase the parent counter anytime and then check for a win like is this matches that we know that we have won the game. So whenever we have a match, we want to say pair counter plus plus. So we started at 0 and if we say plus, plus, we increment this by one. And then we want to call the check for when function open, close parentheses and close the line with a semicolon. In check for when we compare if pairs is equal to our counted pairs or pairs counter, we know we have one. And that case we can play fireworks, we can play music, we can show score time, whatever to actually show them the game. Or maybe you give a UI interface, pop open or something like that. So we can visualize how you have one, you get the, I don't know, got this and that amount of time and so on and so forth. So let's try that out. We have now everything implemented for that, I suppose. So I press Play after the compiler is done running fully. So as a four-by-four Tom, yeah, playfield over here. I can now should be able to pick them. I should be able to see if I can actually get some matches. As you can tell now I get instant access as we already passed over. So we get the shark and I clear the console. And we should now have two matching numbers. To see these numbers, we can go over here to the top right corner, to the three dots and change to debug mode. As you can see now, pears and PR counter equal. That is actually good. I go back to normal mode of the air, so don't do you don't need this always because it will confuse you more than he helps you sometimes at least. So what we now say, we can do a direct line over here, which I could have done beforehand. And then we say, yay, we want turn. So we have something and console to see if that actually is going to trigger. Don't forget to say once again that the compiler runs see if everything is fine. And I reduce the size of my apply field to, let's say two by two. So we have a counter or Paramount of two and foreign this case. We could also go one-by-two. So it would be even, even fancy over here. So we have those two and those two bond our counters actually wrong. Why is that? So it tells us that the paramount, because it's times two. Now it should be correct. So to two-by-twos 4 and 2 by actually to know we should be correct over here. And then we get the debug line. We a one, we have a rule per game. Pretty good. So all the necessary mechanics for an absolute matching game are done for now. So now we just go into furthermore stamps to add score per, let's say iteration can put a timer, maybe every verse timer, which can go downwards. And if you do not clear the field and like, I don't know, 30 or 60 seconds, then we lose the game probably automatically, it will say something like, Hey, try again, something like that and make it even more interesting. But all of that is going to be up to you if you want to implement this or even not. 22. #22 Hide or Show Matches: Welcome back to the course. In this part we want to take a look. We do not disable the objects bond, just let them visible on the screen like so the cards are staying open so we don't deactivate the game objects, but we wanna make them so that they are not interactable by our mouse clicks anymore. To do so, we're going to go and open the game manager script. And where are we currently deactivated the actual objects? We want to do it a bit different. So at the first place, I commend these two lines out because probably you want to do one or the other settings as an example later on. So we can give a setting like use or keep them active or keep them visible or probably not. So for the moment I just comment them out. Well, we wanna do is we gonna copy if one of them lines over here. So we say Control C for copy, control V for paste. What I wanna do is we want to grab the actual collide on the object. So we know that Picard has an object. We're just going to have a box collider on it so we can tell gets component up close parentheses are this triangle brackets. Then we pass in the type Box Collider, open, close parentheses dot. And now we can set enabled so we can send unable to be equal to false. So that means that the card is going to stay visible, but at the same time we deactivate into the box collider. So the collision with our re-cast is not possible anymore. I'm going to copy this complete line and paste us for the second card, which is going to have the actual index of one. Don't forget to save this grid and let's get back and see if that works. So in that case, we first off let the compiler run. And once it has run, we press Play and see the result. So I did press maximize on play inside the playfield so we can see a bit more of the actual playful so we can test out. So first I'm, I going to open them, but they're going to close because I haven't had a match. Kind of do the same for the other way. No match at all. Still no match. Which is okay. I haven't had this one before. So I'm gonna take the star. So now the star is going to stay open as you can see. And if I hit pause, I can check the star card. So the card holder of the object does contain a one box collider, but as you can now see, this box collider got deactivated. So this little checkmark got disabled by us for the code. What that means is I cannot click them again, so I don't prove for any matches anymore because the actual re-cast does not hit any collider onClick. So we can put in any other cards, but not the ones we have opened already. Pretty good. So in that case, we can now optimize and why we have optimized the field. So these tiles are going to stay open right now and we can keep on continuous searching for the other ones. So in that case, you can give yourself or create yourself some, let's say, Bolden inside the objects or inside the game manager to choose between one or the other setting. How do we do this? We create a new public boolean. We can put this literally wherever we want to as an example over here, public bool. And then we can say or can name this boolean, something like hide matters. When we now implement the request for that, whenever we check for a match, we can say is hide matters. Then we want to go and actually deactivate the object. So I cut out our setting over here. I get rid of the command lines. Then we say else. So if we have picked, uh, do not disabled or hide the ones, like the setting is false, then we just disable the box collider. Objects. Don't forget to save and let's head back to Unity. Once the compiler has done running, once again, we can check the game and agenda, as you can see you now we have a serving of here called high matches. For the moment again, the height matters is disabled so we do not do not hide the matches after we have a match like that, but we deactivate the box colliders. If we now do hide the matters by our single setting of the day, which is absolutely possible at anytime. We're gonna try to find a match, trust. No luck at the moment, but there we go, and now we hide the match. So in that case we deactivate the two found objects over here and everything is good to go. 23. #23 Editor Script 1: Welcome back to the course. In this part, we want to implement some simplification for the paramount calculation. To do so, we need to do some editing scripting in which we just pass in the width and the height as well as the paramount that the current state. Then we do the calculation directly in here. And of course we keep on the debugging for if something is too big or too small still inside. Also, we can visualize that a bit better by putting a box around it so we can see what we can touch them would not. Then we do the settings of the end, the paramount we'll calculate on its own. So based on the width and the height of the actual yeah, settings we do over there. And also of course, it will tell us that the sprite list is going to be too huge to smaller whatsoever. So we can even put a little help box inside, like an arrow box that for example, we don't have enough pairs or we don't have enough sprites at this point. To do that, we need to do some specific things. First off, in our scripts folder or wherever inside the assets folder, we need to create a folder called editor. The editor folder is absolutely necessary. Every single enzyme will be handled at the different than usual scripts. In that case, it's only for editing purposes. So whenever we go in there, we want to create a script which actually overrides a bit of the card manager script over here. So what we can do is we can say we create a new C subscript and m, this one card manager editor. You can also give it any other name. And once the compiler is done running, we're going to open this one in our IDE. One's ID has been loaded, we get rid of stored and not agents. We don't need those. We want to do is first off, we're going to get a connection to our card manager. This is the one we want to read our content from. Also, we don't want to inherit mono behavior, we want to inherit editor. The problem is, editor is not currently in our namespaces over here. So to get rid of this editor or a red underline over there, we need to implement using Unity engine, or in this case Unity Editor. So now you can see it turns blue. Once again, if your ID is not set up correctly and this stays white or has any other weird issues, just make sure you set up your IDE correctly. So with that now set, we need to make sure that we customize one specific script. And then Keynes, we put a pair of square brackets above the class. And we named this one custom editor. All custom editor is going to be just what we want to call. Then we do have I inspected type. So we want to inspect some specific type literally. And we can tell in our case what type it is. In our case we say type of open, close parentheses. And then here we can pass in our card manager. This is actually the manager we want to get information from and what we want to override for the downside on my ID Currently it's red underlined, which probably is not happening on your IDE. And that's totally fine. So I just can ignore this for you. You should make sure that no issues are going to happen later on when we get back to Unity. So again, you, for me or for my screen over here, you can ignore this because the code will still run. The next thing is we want to get all the necessary information about the card manager. So we create a function which is called on Enable. So this needs to be typed 100% correct. The O and the need to be uppercase letters. What we wanna do is in order to enable we want to serialize hour or 12, create a new serialized object based on the target we want to have. In our case, the target is going to be the card manager. To do so we first off create a new serialized object and call this one whatever, maybe manager. To access everything which is inside manager, which is later on we're going to be relative to card manager. We want to set manager to be equal to a new serialized object, open, close parentheses. And then we'll put in target. Target is a specific keyword in this case, which targets automatically to the target and the custom editor at the very top over there. Don't forget the underlying was a semicolon. And now we need to add more content to it. We want to read the paramount. We want to read the width and the height of our card manager. So to not get confused, they're going to create the variables in here with an underscore in front of it. So we say pair amount. We're going to set this one to be equal to manager, don't. And now what we wanna do is we want to find the property, a property which sits directly in card manager in our target. So in quotes, we need to tell 10 percent the correct name of the. Actual variable we want to talk or read from top to or read from. So in that case, in our current manager, we do have the paramount, so we need to be 12 percent be sure that we type this as is over here. Also needs to be in quotes. Otherwise that doesn't work. We haven't declared what type paramount is going to be, so we need to create it over here on the top. In that case, it's a serialized property. We can of course copy the name from here since we created this ready and put this over there. Now we do the same for the other ones we need. So we need another serialized property, underscore width. And we need to have another serialize property of a day underscore height. And there's one another serialized property. Again, we're just going to be our sprite list. I put, again an underscore in front of it so I don't confuse myself and we know when exactly is the stuff we need. Also, we need some internal variables which are going to be of type integer. Actually just one, which is going to be just a counter for the amount of content inside the sprite list. So I can say something like Sprite amount of a here. It doesn't have to need to have the underscore since we read the amount directly out of these brightest. And we need to have two floats, in this case, W and an H. You can actually also name them width and height because they are responding or they are taking care of the width and the height over here. We don't need them to be a flow to calculate some stuff. So on ownable, we also want to grab the, all the other properties of, uh, here. In that case, we're going to need the height, the width, and the sprite list. Let's do that. So I just copy this line multiple times. At least four times is needed over there. So now I take the US over here, copy that, and paste this over there. Also paste it over here, but the Get rid of the underscore and the front. Now I take the heights copy, pasted over here, over here, and get rid of the underscore. Last one is the sprite list. We do the same over the mixture sprite list again is the same. Yeah, naming convention of here, which is going to be this one. Again, here we do have the height and the width. What's necessary, of course, that all of them are going to be public, I would say. So just keep that in mind. So now in order to enable we get all of that, but we want to do is we want to read these bright amount that the very first place. So in that case, we want to say a sprite amount is equal to. And now we take underscores, right? List and say dot array size. Don't emphasize, just gives back a number. And so we can compare later on despite amount redone from the sprite list on how much content we just passed on over into that. That's pretty good so far. In the next part, we're going to create a new function inside of here. We're just going to be able to override our inspector window. For the moment. You can go back to Unity and see if you have any compilation errors so far. And even with my red underlying card manager, I don't get any arrow here. So make sure you don't get one as well. 24. #24 Editor Script 2: Welcome back to the course. In this part we continue or actually finish our own inspector Gy. That means we want to make sure that we see or actually can manipulate numbers like the width and the height inside the card manager directly from our editor script. And so we don't have to touch the paramount in that case. So it's getting old medically calculated based on that. And also we get some feedback from the actual editor. So let's open up our card manager editor script over there. Go down over here that and now we create a new function. The function has to be public. It is return type void, but it needs to be an override method because we want to override the inspector GUI. So we pass in the special keyword Override void. And now we need to tell us or call it on inspector GUI. As you can see, I get this already over there. So I just take it and it will pass over a base dot on inspector GUI. We don't need us, so we can delete it. What we need is I draw default and specter over there, open, close parentheses and close the line with a semicolon. Draw default and spectrum means it overwrites with the original content, the content we were creating. Otherwise we wouldn't see the sprite list or anything else because it would get overwritten. I can show you that pretty quick by commenting this one out. I can go back to Unity and you're going to see nothing in a minute or second inside the card manager, since we are overriding the actual card manager script directly, or in this case just the inspector. So withdraw default inspector enabled. We're going to see our original content once we are going back to unity again. As you can see, everything is back to normal. We now want to do is before or after. We want to create some content over here. First one is we want to, and this is absolutely necessary at anytime we are going for editor scripting, we want to update the manager. So we say update or manager, update on those parentheses and close the line with a semicolon. Afterwards, Mike, whenever we are done with everything, there is another necessary content or unnecessary call we need to do. In that case, we need to say manager dot, apply modified properties of me, close parentheses and close the line with a semicolon. Now in between those two calls, the apply modify properties and the update, we can do any change to the editor. What I wanna do is I want to create a little box. So for our content, in that case, I can say Editor GUI layout. And now we want to begin a vertical. But this is basically vertigo group in which we can put a skin or a box or anything or just our content. Never seen what we put in scientists vertical before we close or end, this vertical is going to be highlighted there. I want to add in a DOI dot, skin don't box. So we put a box around the content at the very end. Of course, once again, we want to do the same. We want to say Editor, Gy, layout, dot end, vertical. So we know here is our end. We don't want to draw this box skin again over there. You can always get back to Unity and C of you have seen, or if you currently see any major changes already, which probably you shouldn't. There's nothing inside, no new content, so we don't even see the box. So let's put in content over there. First off, I want to see my very own property field for the pair amount. So for our card pair. So we can just easily say Editor GUI layout, dot property field, open, close parentheses. And now we can pass in our actual property. We want to see in our case the pair amount. Don't forget to have all open and closed parentheses of the here. And now when we go back again to unity, we should see a light gray or darker gray box with the paramount as an extra. As you can see, it's above the actual script of the day. And that's okay, That's no issue because this group stuff of this only connected or only visible after, on this case, after we do the draw default and spectrum, we can put the draw default inspect or also in the top before we actually do any update of the day. That's again totally up to you. Why don't we wanna make sure is that I cannot change this amount. I wanted to see this, but I don't want to be able to change this by hand only by a calculation later on. So I can tell something like GUI dot enabled is equal to false. Also after this one, I want to earn enable the Dui back again to be unable to. I can change things which are going to be after that. So we say to you, I don't own it to be true. So this property field of Paramount is not accessible for us. We're going to see this one status compiling that does like grayed out. And we cannot touch that. If I change this number here, you're going to see the number over there is changing wizard. Pretty good. So now we know that it's updating correctly this number whenever we change any other number. Now we want to see the other two Editor GUI fields or property fueled the width and the height. So I'm going to put two fields here again. Now I copy the name underscore width and put this over here. Copy that name of the property field was the underscore height over the and we should see the two fields over here as well. Again, you can always go back and check if that is the case. If in our gray field over there, we're going to see all our needed changes or needed properties, which we do. Now we want to do some calculation because we want to set the paramount based on the width and the height we are doing as a saddling inside our inspector window. To do that, we first need to do some calculation. I create just a float, which is a temporary flowed in which we just take our width, our actual underscore whiz. Don't int value. The int value just means that this is going to be an integer or handled as an integer, because usually the width over here, as you can see, it's a serialized property and it cannot be handled as an int, usually on an integer, which is, in general it is an integer. But now we just say, okay, we're gonna take this one as or handled this one as an integer. Now we're going to multiply that. We're going to multiply that by our height dot. And now we're going to say again int value. And at the very end we want to multiply. We want to divide this by two. So this result divide it by two. The problem is that these are two integer values. These are heaven, not any common number. So we need to typecast one of them values into a float. So open, close parentheses as an example in front of the height value and make this a float. So this is me and meant to be typecasting an integer into a float value. So in the end we get a common number, because if we say 5 or 5 times 6 is probably 11, which is good. But if we divide 11 by 2, we don't get the correct number. As a result, it would usually be five divided by or whatever, a 10 divided by 2. As an example, we're going to 11 divided by 2. We're going to have a five-point five in that case, but we don't have an 525, so it would round it up or down, probably in the wrong direction. And to avoid that, we're going to use the float over there. And after this, we're going to round up the actual number. So in that case we know precalculate or recalculate the paramount over here. And in that case again, the int value of it, the end value, is a value we now need to bring back to be an integer again. So we typecast float into a value of an integer type. To do this, we need to do system dot math, dot ceiling. This is rounding up numbers. Whereas from a float to the highest integer, and we're going to pass in temp tempers the one we were just creating beforehand. We typecast this into an integer. So we have Up movement of why we do typecast that because mass after ceiling or mastered ceiling gives back or returns a double and we cannot put a double to an int value. So we need to typecast us this double into an integer. So the paramount dot n value is going to be an int at the end as well. Now we know this calculation, so we now calculate the paramount automatically whenever we do a change, Let's try that. Now this calculation will start. So what does it mean? Three times six is going to be 18, and 18 divided by 2 is 9. So you can see now the paramount is nine. Ever do any change over there? So for example, to buy sex is 12 and 12 divided by 6 is 2. But sometimes you may have some weird numbers going on. Maybe something like a 11 times 2 is going to be 22. But maybe we can also say 11 times 5, for example. Then we may have some weird results in the end, we want to avoid that four by five is 20 divided by 2 is 10. So we want to make 1% issue that any result of the is not giving us back a weird or uneven number. So that is working so far so we can change all the values. We were also able to change the bottom volumes of here just by dragging him here around or they're around, you can see the update automatically. Well, we now want to check is of our, if our, our pair amount value is actually bigger than the accessing sprite amount. In that case, we just put in a little extra check of the day. We can say if our Paramount is bigger than our sprite amount. Now we want to give out a little help box. But of course, paramount needs to have the in value over here. Otherwise we cannot compare those two because this is an integer type and now this is an integer type as well. And what we do is at the final step, we're going to say Editor, GUI, layout, dot Help box. And what we want to pass over or out here is something like we have too much pairs or too much card pairs setup, too much card hairs. So we need to reduce the actual width and height of the play field. And we can also pass out a message type. And our case, we can give out a warning or probably an error. Totally up to us. Don't forget to save the script. And let's go back over here. And we should get a little arrow box over there because we have too much pairs, because our sprite list only contains 10, but we would have a paramount of 20, which we don't want to have. So as you can see now, too much card pairs of there. So we need to reduce the grid until this box is not available like five-by-five or five by six, for example, would be too much card pairs. So 15 is not available current variable because this bright lists only contains 10. But if we take a five-by-five doesn't work either. So five by four would be my maximum currently with size own grid size of the. So we get the warning in here. And we would also see this one inside our own draw gizmo of a day. So on the other hand, these arrows over here can be deleted and the end, and we're going to clean up the code on this side as well. And also probably pass out some, let's say ghost tiles of ghost field. So we see in which direction our play field would be in same as we can see this later on inside the camera view. 25. #25 Visualize Playfield: Welcome back to the course in this fund, we wanna make sure that our game manager cannot undergo and the negative numbers with d width and the height are actually the current manager. To do so we open on a card manager editor script once again, and we just pass in some easy tags. The first one is you want to check if along with or in this case, underscore with don't int value is smaller than 0, then undoes the case. We just want to make sure that the underscore width is going to stay 0. So we say underscore with DOD int value is equal to 0. So we cannot under do it or do any negative numbers inside the editor. I'm going to copy the complete function of the input and know the height here as well. Because, well, we don't want the height to be an aside and negative values as well. Don't forget to save the script and get back to Unity and see if that is actually happening. So whenever the compilers and running and we try to go under 0, I drag to the left, or I just pass on a negative 10, for example, and pops back automatically to 0. Pretty good. So editor script is kind of ready for action. What I want now to do is I want to hide the actual paramount over here so I can pass on a hide and inspector argument or attribute in front of it. Same for the width of the year and same for the height over there. Don't forget to save again, and that's her back. So we don't have these width and height values of here as well as we don't have the paramount over there. So now we just have the setting for height and width of the playfield. We're going to have our little arrow are happening or error coding stuff inside. As well as we still have our sprite list, our preferred for the card holder, the actual card deck later on whenever we have created again. Now, since we don't know really where the cards could be and how it could look in the end. We can also create some little script for that to visualize the playfield before it even gets created. In that case, we can create some little, let's say, help a boxes or something similar, or any circles. So we can see what would the layout B, where would our play field would be whenever we are creating the game based on the current settings. We can do this directly inside the card manager as well. We go down once again and 21 on drug is most function. When we do have our error coding, we can get rid of that since we don't need this anymore. And if you want to extend later on the Help box over here for specific reasons, you can do so as well by just going back into the card manager editor and add some more IF statements and probably put out some other help box messages if needed. In onDraw gizmos, we now want to see what would our playfield look like whenever we are creating our actual game. So what we currently do is over here and playfield creationists, we are just iterating through how much parents we're going to go and create and put them into a DAG. And we shuffle the deck and then we put them onto the screen. Putting them onto the screen is actually just two for loops with a position calculation. So what we can do is we can take this for each loop or for loops over here, the nested for loops and bring them inside the onDraw gizmos function. So we are taking the width and the height of the playfield and we calculate the position. We don't want to add something into the card deck and stuff like that. But what we can do is we can put Pep populate or actually draw the actual grid of the game if we want to. How can we do this is rather simple. We're going to need to use the function called gizmos. And we can say we want to draw something. For example, we can draw a cube or a wire cube or spheres or anything else. Let's take a look. Draw wire cube. We have to put in several arguments. First off the center, second one, a vector, A3 size of the actual card or a card, let's say ghost. How do we do this is rather simple. Again, we're going to pass on POS because we have pre-calculated that one already. And now we just need to define a new vector two and vector three in that case, to pass in the size of our, let's say a wire or ghost cube. I'm going to put a one comma, then a 0.1. We need to pass in an f of a here since it is going to be a float variable and another one on the zed axis, not a 100. And dad, don't forget to close the line with a semicolon and K. Let's go back into our scene and see what's happening over the day. What you can now see as the actual game cubes or the grid where the ghost or when the field is going to be created later on. We can also visualize that when sunlight gizmos here and our game view, we can see exactly if the camera would see our actual content of the game. Whenever we say go out with the camera and go closer, go in a different angle and all the other good stuff. And then now change my grid size to be wrong. A three by four, or three by three or four by four, you can see that the gizmos are automatically created and we can absolutely 100 percent see how much we're going to match inside our camera view without always have to go in and to the play mode. And you actually try to play again. Once we know press Play, we should see exactly the same layout here. You can also see when gizmos is still on and we are maximize on play or even not, doesn't really matter. We can see that they fit exactly where they should be. So pretty good. And now we know where our playfield is going to be created at which position. And if we want to put this to somewhere else, because our user interface, for example, is on one specific position or another. And we can just say, okay, we take the camera a bit away, moving it, for example, to the left or to the right based on the size of the playfield. So as you can see, I can now drag it over x. And I can see exactly at this point of the, if we are still in the camera view with our current playfield. And if I want to change that, I can absolutely do this as well, change the camera and still see where our actual playfield is going to be. Same for any higher sizes, let's say a five and the West, you can see the field would not be inside the game. So what we can do is we can bring back the actual camera over there. We click on hierarchy panel, move it over x until it fits the screen. And if the playfield is huge, we can also get away a bit from the playfield was the camera over z axis. And then bring it to the side to fit our actual laid on UI design or whatever we have in mind here. Again, we can also check if we do a rotation on that, where whenever we would rotate the camera, where would the tile be at the point of a here? Would it go outside of the game screen or not? So with additive scripting and with onDraw gizmos function, we can visualize things before they even happen, which is absolutely fantastic once we understood how all that stuff is going to work. And also we did automatic The Paramount setting over there. We don't have to take care of that anymore because we precalculated that directly when we do the settings. This is one added. A scripting is absolutely fantastic for. 26. #26 Timer: Welcome back to the course. In this part, I want to implement a time script or a timer which probably runs for model when bank wants. Well, that was actually and totally lied own up to you. But I would say, I'm going to create some kind of pressure to the player. So he probably only gets like, let's say 60 seconds to solve the complete memory field over here before he gets a high your game over message or something similar on the inside the playfield. Also, I want to implement some scoring system. And whenever a score or whenever you have solved the game as an example, you can keep the score somewhere in the temporary file. You can save it, you can load it, you can do whatever you want to do the wisdom to increment your score for one specific level as an example. To do so v, First off, create a new C-sharp script, of course, which is going to be our score manager. And once that has been compiled and the compilers don't running nothing fancy overall, we store those in our IDE. Once the score manager has been loaded, we get rid of starting out data at least for the moment, probably later on we're going to reimplement them. What I wanna do is I want to create a unlimited accessor for all our possible inputs and all the other stuff. In that case, we do the same thing as we did to the game manager. So we create a public instance or stand against. And so we have direct access from anywhere in the game to the game manager to updated accordingly. We want to have is probably something like a public variable in which we can pass over a time in case of seconds, for example. So this is something like a time left or time for level function oil. In this case variable time for level 2 complaint is going to be settable buyer by us. Whenever we want to pass and over that, we can already said, uh, something like 60 seconds and that if we want to, we can also go low or later onset it by any time. What we wanna do is we want to create and another co-routine which is counting downwards until this time is actually zeroed out. So in that case, we create an IEE numerator. Once again, you already know the eye numerator. We were using that one beforehand. We were using that for checking and matching the cards against each other. We're going to say, this is going to be our timer. Open-close parentheses, open close curly brace once again. And I numerator needs to yield a state before it can go continue. So whenever we are going to yield, return a new weight, four seconds, we are absolutely able to do stuff. So in that case, we can wait for a specific amount. In that case the time for Level complete. So this coroutine now first off runs forward and their case, so it starts at 0 and then it tells us, okay, go whenever this V is reached, we can say, okay, no problem, we're going to have to reduce that. Or we going to have to send a message to the game manager and say, Hey, the game is over, your time is over, and so on. Well, we can also do is we can construct it the other way around, like negating this one number over here by a number, a temporary number literally. That would be like the opposite. We're going to store the time or yeah, just take a temp time over here inside the co-routine, we declare it and having the time to Level complete time at the very start. Every once in a while we going to pass down some number. But instead of yielding like upwards, we can also pass over a while loop. And here, while loop runs until the specific, Yeah, actual argument is going to not be possible, let's say or is matching. This is literally like an if statement. You gonna request if something has happened or has not happened or is true or false, then we go forward or actually do whatever is inside the if statement in a while loop, it is a bit different. It runs. Meanwhile this argument or this expression is happening or even not happening, or is changing or is whatever we wanted. We can also say it has to run unlimited. And our case, we want to say, while the actual temp time is bigger than 0, that is the case. We want to reduce temp time by one. So we can say something like temp time minus-minus. We want to reduce the temporary time, whichever currently starts, it's 660 by one. We could also type in. Minus equal one. Basically the same stuff is going to happen. So ten time minus-minus what we wanna do afterwards, synthesis running Reza quick, we want to wait now for exactly 1 second. So each second, even if that is not absolutely accurate over here, we can tell every second we reduce term time by one, and we could do this. Meanwhile, the time, time is higher than 0. Once that happened, we're going to say, Okay, we're done here. Then we can talk to the game manager and can say something like game over. So, or time is out. In our game manager, we can create a super small function as we did for check for when we basically create a public lost game or Game Over function. Because the time has probably ran out. And that case we're going to create a public void game over open, close parentheses. And then here we can say some debug line. Also we can show interface. You can like UI. And now we can say something like, whoops, we lost. Once again, this is only for us. We debug lines. The players will not see that later on as well as we are going to clean this up. But we want to check if these are going to be triggered. In score manager. We now call the game manager over here, the instance of the game manager. And we're going to say, hey, we are game over. So please run this request or run this function. So in that case, we now have an actual timer running. But as you can tell, the coroutine gotten ever started to do so, we can say void, big ass, star, and close parentheses, open, close curly brace, start co-routine, open-close parentheses, timer. So we want to start the timer over here. But since we probably want to stop the timer sooner or later, we can also call a coroutine with the function name in quotes that gives us the possibility to stop the timer at any place, meaning whenever we want to stop the scores managers. Yeah. Runtime thing like this, particular time over there. So it doesn't continuously running if we have lost or one already. Actually, only if we have one ready. So now we start a co-routine. We're going to store whatever the with the settings are. We going to pass in inside the Inspector, then we run. Meanwhile, the temporary time is bigger than 0, we reduce it. Everyone's a second and stay inside the while loop until this argument is actually returning 0. We go out and then we get again over here. Don't forget to save the script and let's get back into our scene. And once the compiler is done running and we don't have any issues in the console. We can select the game and Johnson example and add the score manager to the game manager object. Now you can see we have the time for level 2 complete 60, and now we should be able to wait until this happening. So in my case, I'm going to reduce the time now to, let's say five seconds so we can see the debug line popping up. So we let the coroutine stored, we counted backwards to five. And after five seconds, we're going to get the, whoops. We lost. Fantastic. 27. #27 Timer Graphics: Welcome back to the course. In this part, I want to visualize the time for the players. To do so. We need some graphics. You can create your own graphics or you can use the ones I provide in this lesson. So please put in the UI Atlas PNG inside the textures folder by just dragging it into it. We want to make sure that we can go over here and change the tax or time whenever we select the UI taxes to be stride two Dui also change the sprite mode to be multiple and then apply the changes and the bottom. Also go to the Sprite Editor since we have to count and prepare some things. As you can see, I have just created some simple symbols over here, which I want to order slice now. So I go to slice automatic, center, delete existing and slice. So this one should be one thing. This is one, this is one and all the other ones are all separated. There's one thing I want to prepare. Two is I don't want to have these little tips of the buildings to be separated. So I get rid of this one and this one, and I take this one and drag it up a bit as well as a bit outside. So I have the full house on the left side and on the right side. If later on are two huge or too small, we can always change them accordingly. We're going to see this in the previous whenever we use this building as an example. So what did I provide actually is some kind of buttons or probably placeholders for different things in any color. And here we have a grayscale in here. I have attended one, same for this one. This is not tinted at this point or actually is red and my case. So we're going to use that once again, if you want to create your own, you're absolutely free to do so. I'm going to use one of them graphics, this is going to be our timers, which is going to sit inside this axle bar over there. And then we have some creatable buttons and probably some other UI elements. We can take a look into. What I also wanna do is I want to prepare them. Buttons actually are going to use the red ones. You can decide which ones you want to use over here. The gray ones are literally turned trouble in any color. What I want to make sure that I take this little green dots which are on the sides of a here of one of these graphics, not the blue one, but the green line and drag it inwards over here. What I can do is I can drag them literally to the center from the left to the right. So averaging in the corners will not be really scaled. We can also do the same for the other ones over there. So in that case, thank the bottom. You can also put this or do this over there. We're going to drag up the bottom, maybe up to 51, the top 250 one as well, or maybe 50. Again, this is totally something up to you. We just take a look into possibilities over here. Why a 50? Because I don't want while stretching the correct sizes later on, I don't want to affect the actual round corners of the object. We could even go further into the middle. So we would have like just a unskilled middle of the day. I'm going to go with 50 and 50 from top and bottom over here. And I'm pretty happy so far for this one. If you want to use these already created ones, feel free to do so. So when and while I'm doing that, I have the possibility to resize that one night own and make it as beautiful as possible. I don't need to do this over here or even there because we're going to use them a bit different. Once you are done with your settings, hit Apply in the top right corner and close the Sprite Editor window. Now, I can create some UI directly in my game scene. I create right-click and hierarchy and create a new UI canvas. We can name this Canvas, maybe like UI canvas or just keep it as Canvas. We know what is this about? At the same time and event system is going to be created, which is going to listen to inputs on UI devices or UI options. For example, if we are creating buttons, the, the event system is notifying the actual button clicks. Also, when you zoom out a bit, you're going to see this is our actual canvas inside the scene. It is way bigger than the actual game, as you can see. First things first, we want to ascend the Canvas app. So it has not constant pixel size, but scale with screen size does, is absolutely important. And you want to, you can choose a reference resolution that's a nine to 1920 by 1080 as an example. So it always tries to match graphics based on this actual references solution. But probably you need to scale up or down the actual graphics. You can also keep this as reference by 800 to 600 of day. Also, the random mode of the canvas should be screen space overlay in our case. Now what we can do is we can pass in component, components which are going to represent our timer. So I go and create a new UI image. As you can see, it's a rather small image in the game view, we can see this idea activate the gizmos for the moment. So we only see that part. Now, we can go to 2D view and a top left corner over here of the scene view. So we see everything razor flat and we don't care about the rest at the moment. We can now take this image and bring this into any screen as or any size or anywhere we want to. I want to represent my size on my time over using the one graphic I just showed before, the one on the top left corner is going to be in the one on the top left corner over here as well. I don't want it to pink, but I want to see how that is going to look. Usually when I create some UI elements, I use placeholders so I can actually put things together. That means if I now take those placeholder and move it around, every child object is going to listen to it and we'll resize all repositioning accordingly went setup, correct. So in that case, I'm going to create another UI image. Inside this image, we can tint this for the current time and see how big this is going to be. Now, we're going to choose a sprite for this. In my case, it's UI Atlas 0. I also want to make sure that this is no ray casting target. So I deactivate re-cast target. And I want to make sure that I hit preserve aspect ratio. Now, we can resize that to our needs by just pulling it left and right, up and down to the size we want to. We can place that this one side of the head does not do anything. And we can just position this one, let's say over there. If you want to make it bigger, you can also go but diagonal, I would say. So it can make it as big and as small as you need. Unlike inside the view, don't forget, you move the children inside this chill or in this parent image object. Now what you can do is you can scale this one object with this one object like this first image, with the second image. How does that work? Is we are using anchors. For example, I can take this UI background over here. I can name this UI BG taxed or time. And I can use these anchors. The anchors are these little triangles over here, so we drag them to the sides or to the actual, yeah, big size of a day. Like how big our image is going to be if you cannot see them or barely see them, take the images color over there, make it any other color so I can see where you are. What's now happening. These little triangles are looking to the right and to the top inside the actual parent object and see if they fit. Fit means if they have, they tried to hold the distance of its current position to the scalable position. So if I would go and scale this one graphic now down as an example, you can see the rest is going to follow. If I, let's say move this one left and right, It's going to scale and tries to fit inside our actual placeholder image. So we can play around with these and see what could be a good size and resolution for our actual graphic. Now, I want another image which is going to be inside our bar over day. So this is all actual time bar. I want this to have another graphic which is going to be this UI Atlas one. I want to keep aspect ratio over here. And I want to scale this and position this as long as it fits the blank bar in the border and the background. As you can see, this fits Reza good everyone, and make it a bit smaller so you can literally see a little border around it later on you can do so. So go a bit smaller, see that you kind of faded still in its correct size onto all of these axes. But as you can see, this will probably not work. So instead of having a preserve aspect ratio, you want to maybe get rid of preserved and tried to fill it this way a bit better. So I can put a little border around, again, totally up to you. If you don't like the color, you can overcome. Kind of adjust a bit, let's say over the existing color by using the color pellet over the I keep mine at wide so I don't over to my yellow color over there. Also, I want the anchors to be sad at the outside where the actual graphic should fit to the possessions. So I'm going to drag them to the corners of the actual graphic over here. I want to make sure it is rather precise, doesn't have to be 100%, but rather close actually to be as precise as possible. We can make this one image. Two, we to be a specific image, in our case, filled image. We choose the method horizontal and the origin should be on the left. If we now take the fill amount of a year and slides it or slider to the left, you're going to see that the time is running literally on the fill amount is going to represent a number between 0 and 1. That means whenever time is out relative to a number between 0100 or 01, we're going to do a little calculation and set the fill amount of this time above by code whenever the time runs out or reduces itself. But that's what we're gonna do in the next one. 28. #28 Coding the Timer Bar: Welcome back to the course. In this one, we're going to continue on the timer bar as well as probably put a text field over here, which also represents the seconds which are left before the time or the game is over. Also, you can put in a lump level number in this bubble or anything else you like to. Before we continue, I want to take the main image, like the one which is actually holding everything about our time and take the anchor points to its corresponding actual corners. In that case, I'm going to bring them over here, zoom in so I see stuff better. And try to be again as precise as possible evidence like not 100%, as you can see over here. The actual graphic is just in between one pixel. So you shouldn't care too much about it. With that anchor SAT. So with the main anchor sad, the normal anchor sad, as well as the scale or the fill time bar image set. We can literally choose any, let's say, aspect ratio of our game and it should all stay in the same position. Let's try out in the actual mobile view for example. But as you can see, it's not always working. So something is probably wrong with our setting over there. In that case, we go back to 16 by nine aspect ratio and see what the issue could actually be. Probably. And sometimes free aspect can help. Like whenever we reduce the cameras size of a here we're going to see what is really actually happening. So what holds the information left to right? But it makes this actual graphic of a here not relative to our other graphic at this point. So I go and switch back to 16 by nine aspect ratio. And now we try to fit or fix the actual issue over here about this one graphic. And since there are some troublesome issues of here, I just take the UI big time image outside of the, or actually outside of the image of here. Since I have the issue that I cannot preserve the aspect ratio of my actual object. So I use Aspect Ratio or preserve aspect ratio on the outside of a here. And I want to make sure that I create or take my actual anchor points and point them or bring them now at all to the corresponding image of the mike onto the corners. Once again, just in case to see if it can keep my aspect ratio, not taking care of the other ones at the moment going to free aspect. And now we have at least the bottom one is going to be correct. So if we go nine by 16, we still have that in the aspect ratio. As we have created this one over here in the relative like 3% or 1 third of the screen size to the left and to the right. We're going to this over DE. Now we want to make sure that this one is also going to follow. And, but the issue is with this one is a preserved aspect ratio. We need to make sure that this one is a preserved aspect ratio, probably as well. So we can resize that we do whatever we want to and try again and Free Aspect Ratio. And as you can see, it still has a pretty much a lot of issues over here as well. So we need to Thanks, dad. Still this one issue of here, there are probably a bunch of issues. Bunch of things we can take a look into. First off, I would go and reset the actual anchor point and see if that does any change to my UI. Gonna make this one up and down, as you can see, that doesn't affect it. But if I go now with three aspect, now without incurring this one to a fixed position, but keep a child of my time. You can see now it scales wizard, but it should not be overdo it too much of this, or it can go only up until a specific, let's say screen size, resolution. So we go nine by 16, everything is in place. My 16 hours in his play is in place. 16 by 9, 16 by 10. All of them are okay with that since this actual master or yeah. Mom object or whatever you call it or parent object is going to fit in the screen as best as it can. So I'm going to choose bank or go back to nine by 16 or 16 by 9 over here, in my case, we don't see the border now because it seems that the gray color and the background or the rim of a here is going to have this same one. At this point. Again, I gonna go filled of there. I just changed it for testing purposes. Wanna make sure that it goes left to right. And that the actual pivot point is going to be in the center. Since we did or can put this one before and to the left side, you hold on old and shift again and select the center point over here. So the pivot point will be at, will pop a bit because it is child of the parent object of the UI times frame. And then I just put my actual graphic back where I took it from. Just position that once again go free aspect if you want to and test out if the tile, this part is going to stay Reza, where it has to be, again, overdoing. It will actually be our reposition, this one, false aspect. So there are things we can later on take a look into a prolly have to fix them. But for the moment, let's keep it as is. Now we want to talk to the fill amount of this one image. So I'm going to rename this once again since I had to reproduce some things. So I can go ahead, hit F2 on the actual keyboard. If you are sitting on a PC, on a Mac, you probably don't have an F2, then you just go over here inside the inspector and Daniel scientists is our time bar. Next one is we need a connection inside our actual score manager script, which takes care of the time. So we can calculate the lengths or the fill amount over into this one. So a bit of mismanaged calculations. First of all, want to have a connection to our actual image of their own game image. But as you can see, an image is not available for us. And that case, we need to create a namespace or use the namespace. Unity engine dot UI. Ui contains the image component and now we can actually talk to the image, give it a name, for example, time in edge. And then we need to make sure that we of course, put this one to be public so we can drag it inside this time image or image slot. Now, whenever we want to take the current time, the term time and kept precalculated time over there. We're going to be able to set the time of bias simple calculation. First off, we create a temporary float, which is going to be our present age or percent of the fill amount. We can also probably use fill amount as being a parameter or just a name. What we wanna do is we want to calculate the maximum time and down we want to take the current time and calculate them so that we get a number between 0 and 1. For example, if we take 60 seconds of our level maximum time and we divide this by, let's say 30, which is currently the rest of the time, we should get a number between 01. So the calculation taking the maximum and by, divided by the minimum or the current one is wrong. So we need to do the opposite. If we have 30 seconds left and our initial time was 60, we get back is 0.1 over here. So we now need to know what the actual current time is, as well as we know the current time to complete to calculate the distance. In that case, we're going to take now temp time, which is the current time, and we divide this by our time to complete. But as you can see, the temporary time as well as the time for Level complete, both are integers so we don't get offload bank. So we need to convert one of them to be afloat, which one shouldn't actually matter at all. And the final step is we want to attack or change the fill amount inside the time image to be the film mount we calculated. So we say time image dot fill amount is equal to our full amount we calculated beforehand. We can also safe one step without using this one, we can directly do the calculation to put it in here. So it is a one-liner. So I take this copy, put this one over here, and now we can get rid of this one line. Basically, it should be the same. So now I go back into Unity and wait a second or two, wait until everything has senior and we see the image component we can connect to time image. Take the time bar and put this into this field. And surplus want to be, let's say 20 seconds. So we have something to take a look at. I hit play and see what's going on. Now you can see every time the time got or gets reduced over here, this fill amount gets pre-calc or gets calculated by its time. And once it hits 0, we get a in the debug line very much in the bottom of here. Whenever that is going to happen, we know that we have lost. The time is not pre-calculus or calculating anymore because the actual loop is done over here at this point. So now we have a time slider, which on time image, which uses the fill amount of a here, took, calculate and show the time. And we can do the same thing basically too little. Let's say, Yeah, that a textbox or something like that to see what the current time is, probably a numbers. We can also put the time in numbers on top of this image. Once again, totally up to you. 29. #29 Timer Text: Welcome back to the course in this part, I want to finish the time bar by adding a little textbooks about the current runtime over there. To do so, I'm gonna take my big your UI big time image and create a new UI text text Mesh Pro. As you can see, it now opens dTMP importer. So to make use of text must Pro, you need to import the TMP Essentials. That is going to happen rather quick. And once you're done was done, we can play around was done and put our time and to the top left. Can also do is you can put your normal or normal texts of the day. Now once it has been imported, I'll just close this. I drag my text wherever I want to see this can make it as huge as a 12 pairs in any number. I want to see. For example, 60. I want to make sure that it is centered overall and resizing itself. So it's called order size. So we want to do auto size over here, so it's based on the actual selection. And I'm going to make it so that is always centered like from the left to the right and inside the center over here in the middle that journey. So it's going to, well, hopefully whenever we go back to a free aspect, is going to stay at the same position as it should be exempt. As you can see, this bottom image here is going away from its current position. This is happening by overstretching at this particular point. If we don't want to see this actual overstretching, we probably wanna just keep it in the current size it is at the moment, again, there are a bunch of reasons for this resizing issues. We should be able so to bring this on like or anchor this one over here. But again, the issue is that whenever this edit, this image of a hair stretches, that it's staying in the center of the actual stretched image. That's when we actually would need to try to avoid at this point. But we'll get there. I guess. What I now want to do is I want to update this taxed element with the current time left. In that case, we first need to add for connection to it. We want to see attacks most pro. So please open your score and manager once again. And we want to end part i public TMP protests. But as you can see, the TMP Pro isn't needed to put a namespace about JMP Pro. So we're going to pull it in using TMP Pro over here. Otherwise we have no access to TMP pro text elements. So now we can type and again, TMP pro text with an underscore in between. And we can say this is our time text. And start, we can update the time tags of a variable value to be whatever the time is going to be over here. So because we are waiting a second before we actually do an update on this one. We can also do this directly whenever we start that. So we updated ones whenever the timer literally starts, those are going to work. And then case we can say timed text. The text is equal to time for Level complete dot ToString, we need to convert it to a string. Otherwise, we get an error. Some text requires a string and or is of type string and an integer is not a string. So that's why we add dot two string. And whenever we change the time in the next iteration that really like after we were filling the image, we also want to update the time taxed at this particular point. Don't forget to save the script and let's go back to the game manager. The game manager object took now inside our score manager script should have dTMP pro TextField. We just take this one over here. We can also rename it over there if you want to. We're just going to be now our time text. And we can also feel unsure if you want to keep the same naming convention. You can also put a open close parentheses and put an TMP Pro if you think that is going to help you later on. So you know what yeah, what part? There's going to be once again, this is totally up to you how you name that. So meaning whenever we start the game now, we should see a 20 somewhere. And we should see reduction of this one. Why all of that is no off is because I have three aspect on which I don't want to see at all. That's why we always want to work in 16 by 9 or 16 by 10 actually inside that. But as you can see, we don't really update the text over there. And the question is, why is that so? Well, because we are not updating the correct time. We want to take Tim time instead of time for level to complete, to be inside our actual updated field. So we copy this one over there. Just let the compiler runs see if there are any issues. And now we should see a timer going downwards with the actual time of bar at the same time. So, and whenever the bar is and we should see a 0 here, nothing should go down once from this point on. So the actual variables are counting down correctly. 10 we can again, so any user interface of the, something like a game over screen. And then we are good to go. 30. #30 Scoring System: Welcome back to the course. In this part we are going to implement some scoring system also, since the scaling of our UI background for the timer always has some issues with resizing. I going to anchor the actual object to the top left of the screen. So I go here, hold old key on the keyboard and select the top left corner. Now I can just drag it away from the corner. So the distance will be held between the actual frame as well as to the, all the actual corners. Over here. We now go into freeze back aspect ratio. We can drag up and down, left and right resize and so on and so forth. So for the moment everything stays wherever it currently is and scales was to grow in size to us through the aspect ratio preservation. This is going to be causing the actual trouble in the most cases. Now let's implement some scoring system. So first off, I want to create maybe a place holder where we're going to put our actual text field inside, which is going to hold or actual score. How high the score later on is going to be per match. Totally again, up to you. So what we're gonna do is we create another new image over here. And we can literally place that wherever we want to. We can even put this one as being a child object of the actual current I for the background timer. So I'm going to put this over here as being a child object. I reduce its size and probably put it somewhere here. I can also snap this to the left, can make it bigger or smaller. However, I want to. I can also center this one in between, like let's say over maybe here. For the moment I don't touch this scale or anything. But what I want to implement is the actual sprite. I can now choose maybe one of the brighter ones or one of the darker ones. If I select this, you're going to see that as a weird color matching happening over there. This is happening because of the slicing we were doing beforehand. As you can see, the image type of the set to the sliced. We can also set this one to be tiled. But for the moment, let me take a look into what slice is due so you can see and understand what's happening. As you can now see. However I now go and raise high is the actual area of hair. The gradient in the center is going to try to stay the same. But also the corners of the actual graphic are trying to stay in the position where they are so they don't stretch no matter what we do and reciting this actual graphic. If we put the staff closer together at a specific point, the gradient is just flowing inside the top of the android creates automatically a hard edge. To avoid that and also get rid of this, a bigger frame of a here we have multiple possibilities. For my case, I would go with the scaling possibility. I hit just the archae to scale or use the scale tool and just scale the graphic down until I think the border is actually fitting my needs. You can see also that the border or the actual scale is now around 0.2. Now again, move this one on to any position aligned with the correct size on which probably fits my design. Then I go back to the actual Rec tool and stretch the current part as much as necessary until it fits my actual design. I can try to put it onto the side of a here, but probably it does not match because of this actual scale. Now I can, again put it to any position I want. I can center that. And that's good so far. Next one is I want to create a time or actually a score field, the text field, again, we are using text Mesh Pro for this. I just position this one in the center or somewhere where my object is. I scaled around wherever I think I'm going to put this. Also, I can center this one in the center of the actual text field selection, as well as probably put this onto the right of the screen, in the center of the screen, and so on and so forth. I can reduce size overall. And then I should be good to go. Again, if I go to free aspect, I should not see any weird scaling are actually happening over there. So everything is should be and place later on they're going to be some numbers in here, so we can see what the actual score in our game is going to be. If we get a score of, let's say, a 100 or 50 or a 32 or whatever number is going to become an soil over here. We are absolutely able to visualize that. I just rename this one to be your score text. So we know later on what we actually have in there and putting this one end to the correct spot. The image of a here is just our score background. So I name this one score BG. So I don't have too much images since naming convention is king. So whenever you are looking for something, whatever it is going to be, make sure it fits your naming convention. Now, inside our score manager, we want to add the corresponding content code-wise. We just open no score script or score manager script and we add our new text Mesh pro taxed. So we say public text, in this case T and P tags. And saying score text. Whenever we now get score, we need to create a little function which is going to add to this corresponding score. So basically just paints the actual score. But we can also add a score into our integer or in one integer which holds the score completely. So in creating new int score, now, we just need to have an access point. We can say something like public void add score. Whenever we add score to our score system, we want to update the actual text UI. So open, close curly brace. And now we can say something like score plus. And now we need to know what do we want to put into. So we need to have an integer argument about the score to add. So let me just name it score to add. And now we say score plus equal score to add. So we update our existing score. If it starts at 0, then our next score gets added by that one. Now, we just need to update the text component about the Score Text. So we can say score text dot txt is equal to. And now we just say our score dot two string. Or we can also do is, since we don't know how long a number can be, we can actually convert or format our tags by using quotes or single quotes. For putting a normal quote, we can say something like a d, nine or eight. So we will see always eight decimal numbers in the score text field. So it can count them pretty easily. So currently, I have created a 16 zeros over here into the text field. And later on when we need to update this one, which we can easily do also on start, we can just say, okay, we count how much decimals are going to be there. So let's start As an example. We can call add score, add a 0 in it. So we don't add anything literally at start. So we can call the function at the very start of the game. Once the compiler is done running, we can just say we press Play and we should see eight zeros over there. But we get a null reference exception. That means we forgot to add our text Mesh PRO component over here into our script. So we take the score tax TMP and drag it into the corresponding piece or slot. Don't forget to save, often. Hit play again. And now we should be able to count eight zeros. Pretty good. Our score, that really works. 31. #31 Adding Score: Welcome back to the course. In this part we want to implement the actual score add system. So meaning whenever we have a match, we want to get score for the match. Also, we probably want to count turns, which we can also visualize over in our score manager. But let's add the score first. We want to do is whenever we check for a match, which we currently do in our actual game manager, when ever we are tracking a match, we want to do two things. First off, when we know that we do have a match like we, I'm actually know what the current Mencius have been at this point. Like we were setting all of them active or inactive or whatsoever. So we know in this particular case and this particular IF statement that we found a match, we can now talk to our game, or in this case, score manager. So we can say score manager dot instance, dot add score. But since I don't have created an instance for the actual score manager, we need to do this first. So in that case, we say public static score manager instance. And we need again to create the void a wave function. So void awake was a big a in the beginning. Open, close parentheses, open close curly brace. And inside we say instance is equal to this. Now, we can go back to the game manager. Don't forget to size the skirt. And then the game manager, we should be able now to pass over the instance of score manager. And we can, as you can see at the very top, add a score. Now we can literally do multiple things. First off, we can set a specific value as being a public value over here inside the game managers. So we have something to set. Or on the other hand, we can just pick one for free, meaning we pick the one whichever suits at this particular point. So what we do is we create a public variable, for example, of type integer. And then we say score per match. This is going to be probably something like a any weird number, something like is equal to 73. You can also go with phone numbers like 100 or something similar up to you. You can set these ones later on inside the inspector. What we want to add over here and our function is the actual score per match. So we're going to pass in score per match. Don't forget to save. And whenever we now do a head, we're going to call add score and update the corresponding text field. Let's try that out. We wait until the compiler is done running. We're going to press play and try to find a match. Maybe I'm not as quick as the actual game. Lets me play that since the timer startup and a rather small amount. But now you can see we were actually gotten a match here. Adequacy also, I got a score of 73. Pretty good. So now they will count up until the game is over. So in here, we have now the public setting for it. You can pass in again any number you please. And like. 32. #32 Turn System: Welcome back to the course. In this part we're going to take a look into counting turns. So how many terms that we have made beforehand? I go into the Canvas again and create a new image. Kinda protests anywhere where I think I'm going to put my graphic actually, so I can take a look at it at anytime. You can literally place it wherever you want. You could even go and put those like, as I say, in a center probably of the scene. Do you want to make sure that you don't let say hide something behind it or below it. So I'm going to put mine over here. I make a maybe a yellow one, but the yellow one doesn't really fit my needs of the, so I probably go and use the red one as well. Or you can also do, by the way, is taking the gray one and tinted if you want to, for example, you pick any color of your liking like a green. And so it looks more or less like a button. But, well, this is again totally up to you. You can pick literally any number or any setting over here. Well, or any color or feel liking. I don't use them, but you have the freedom to do so. I'm going to take now this one. We're going to see that this one is again my slice one. So I go and scale this down again to point to an all three axes. Just in case the trolley. And now I use them, resize the actual geographic up, again, make it as much prominent as I need to. And maybe I can also create or you can also go in and create other graphics of liking. Since my background over here is a bit darker, since I changed that to a grayer color, I light it up again so I can see this also better now and everything should fit. I also take my score texts and the actual corresponding score background over here and move them a bit downwards so there's a little gap in between. Again, if you don't like that or if you don't probably like the counter or for the time being over there, you can also put the terms inside that. So how many turns you have made or the player has made, meanwhile, playing your game. The final thing is, of course I've renamed this one to be my actual, say turns image or turns background. And of course we're going to add another, one, another text Mesh Pro and the middle over here. And you can see it's scaled down with the actual image. So we need to make sure that we create a tax much pro beforehand. And so whenever we added to it, it doesn't take the scale of the actual current scale over here. So we take the canvas, say UI, text most prone. You're going to see that this one is no way bigger than the other one to four. We can literally place that wherever we want to resize to whatever size we want to can center this one to the corresponding or the current image over. They're going to put in some numbers, make sure everything is centered. And probably taking auto size. So this is going to show how many of the terms we have taken or used or whatever, which columns automatically out per turn, then we can make a child of the terms background. Now you can see the terms background still has its scale and this one just added to the current scale from one to five because well, one divided by five is 0.2. In this case, completely logic, I would say, Oh, it just rename this one to be our turns text. And the final step is we just need to implement this into one actual score manager or whichever manager you prefer. I like this common job for that. So let's put it in. The easiest way is again, to go into the score Manager. Over here, we create a new public text most pro or TMP txt name it turns text. And whenever we add a turn, we need to create an access for that. No problem overall, first off, we probably want to store this information about the terms over here. So we start with 0 turns, and we literally do the same as we do over here. I copy the complete function and just change it. So we want to say Add turn. We wanna say the term to add, or actually we don't need to have any arguments since we just call it ones. Are we now and done? And here we say turns. And we don't need this argument here as well, or this variable, so we say turns plus, plus. And the final thing is we want to update the terms text dot txt with all current turns dot toString. And then here we're going to have something like a decimal too. Don't forget to save and go back. Game Manager. So once and whenever we are checking for a match, we know that we did a turn at the very end, no matter if we have one, a turn or gotta turn or actually not, by flipping back at the very end. We always want to tell our score manager that a term has happened. So we say score manager, dot instance, dot add, turn, open, close parentheses, and close the line with a semicolon. That's everything we need to count. Turns. Don't forget to save all the scripts and go back to the game manager over here and the game manager object and take the turnstile next and bring this over here into the turns text part. Now press play and see if that works. Now the flip turns back and we noticed, aha, okay, We did a turn and we completed this one turn. This is happening whenever the turn gets back or whenever we made an actual term. So the final step is later on for you just go in and check for corresponding or for the correct numbers. For example, gives you a player's something like 60 seconds to solve a big field, and so on and so forth. The next one things won't be implementing a bit more buttons, like a button back to the actual game menu for example. And probably also some menu which pops up whenever you lose or win to also get back to the option or to the actual menu over there. But the other stuff for another video, of course. 33. #33 Game Over Setting: Welcome back to the course. In this part, we want to do a bit more on this area as well as I want to show you what's going to happen if the time is over. So first off, I want to make sure that this one is when I go to Free Aspect ratio, you can see that it is moving literally freely because we haven't anchor this one. Yeah, tile or this one part of a here. So going back to 16 by 9, 10, I wanna make sure that I also anchor this into the top-left corner. Again, reposition that when I go to free aspect for the moment, at least it should stay at the corresponding position relative to the top left corner. That's good. Now we have another issue. We have the issue that whenever our time is over Iran and put this one on to ten seconds. And let the time, of course run down. No matter if one doing a match or not. Whenever it tells us, hey, we usually get Diablo game over. We are doing, are able to do this. We are still able to move tiles, which is actually not correct. And all the other code is still running even if we are literally GameOver. To avoid that, we need to go into our actual game manager. Well, we are talking or actually setting that we are currently GameOver when that is. So we wanna make sure that we have a bool or any other point of possibility to get rid of that. In that case, I want to make sure that we create, and let's say private Boolean, so it cannot touch that just a bool lname, this one GameOver. If that is true, then we want to avoid any type of inputs. What does it mean is if we are GameOver, which we are not in the beginning, we got to check against that. Or in this case, we just set game over to be equal to true whenever we call this one function. Now, we want to read that. We want to read that from our actual input manager. So n here we do have, have, we not have pegged, but also if we are not game over, then we only then we want to actually do the ray casting. So in that case, I just create a new little helper function to read GameOver. What we want to return is basically the same as we do with has picked. In our case, we're going to say ball game over or is game over, something like that. And we want to return game over, over there. But as you can see, we do have now two different functions which are literally doing the same. So I just rename this one to be as game over or game is over is probably a bit better. So we request game over when we call game is over. Don't forget to save the game manager and go back into the input from the player. So what we want to say is we put another end operator over here in between and say Game Manager dot instance, dot game is over. And our case we want to say is not, is games or game is over. So if we are not game over, only, then we want to actually give our players the input for this particular re-cast functionality. Let's try that out. Don't forget to save all the scripts. Latin compiler run, clear the console, see if everything fits and works. And now let's test out if after the TEN seconds we are still able to rotate a card. So I'll wait now for the count on coming up. And now I tried to press on the cards, but I'm not allowed to because we actually lost the game. The game is over. Pretty good. 34. #34 Particle Confetti: Welcome back to the course. In this part, I want to create a small particle fact, which is actually playing once we found a match. So the matched cards are going to create our actual particle fact on this case just activated and afterwards of course deactivated because it's not necessary at this point anymore and we just flush it out ones. How do we do this is rather simple. First off, I would create a particle fact directly on an object so we can place it. Or the second one could be we just take our card holder object and make it part of it. So I drag that card holder and set the scene, see where it is. Also, we can see directly how the effect is going to look probably laid on. What we wanna do is we want to create the particle fact as being child object of the card holder. So we can again activate and deactivate whenever we want to. To do so, we right-click the card holder, we see that there's still one stretch over here on the y-axis. So we're going to actually create it first without selecting the cardholder, we go to Effects particle system. We can now rename this if we want to, something like F X confetti or whatever, you name this as up to you. Now since I don't have a strategy anymore or anyhow on the scale axis over here, I just can parent it to the card holder. So they ethics confetti is not going to be affected by any scale of the card holder itself. Now what we can do is we gonna put some little facts onto it. So let's go to our throat. The first effect we want to talk about, I want to have a flush in fact, where there are like 30 particles popping out of the center or wherever the confetti effect is going to be in a random size, rotated a bit and then fade out. Also, I want to confetti to be having all their own colors so we can vary age. We have a random variation between colors of each particle tile over here. So first off, I want to limit the effect of the maximum particles shouldn't be higher than 100, even if we are going to burst out a bit less later on anyways, I want to reduce the effect of the duration probably to 1 second. Same for the lifetime of the particles shouldn't be higher than 1 second as well. So you can see they reduce themselves over runtime. The next thing is the speed can for the moment stay as is. But what I want to add is the gravity modifier. In this case, I want to pass an A1. So the particles are automatically flying downwards. And after emitted, we can lift up the particle confetti on its own later on, so it pops out of bursts out a bit higher. The next one is I want to do some parts to the subtotal render itself. The first thing is I want to change the material so i little HIPAA, little dots and just use Sprites Default. So we're going to have some squares coming out of here. The next one is since the particles are bit too huge, I want to reduce them. So first off, I'm gonna go to start size and choose random between two constants, gonna make it a rather small number since the effect just should appear for a short amount of time and also not as huge, it should be visible so the user notifies high, there's something What I'm a maid or the player actually, but I don't want to overdo it. So I put a starting number of, let's say 0.05 over here. And maybe the maximum number should be somewhere around 0.1. So we're going to see some little sparkly up popping effect over here. The next one, as you want to take a look into the shape, the shape is currently a rather huge cone of a here. So we may be reduced the size and also lift up the cone as well. The cone again is actually starting, or should start, where the current position of the effect is going to be. Let's position this one onto zeros 0000. So it lifts up a bit higher. Also, the cone is a bit too huge over here, so we reduce the radius, something like maybe this so it fits kind of the shape. The card itself. The length of the cone is not important in our case, so we can let it be s is. So the next thing is, I want to rotate this and place those particles being in a 3D space. So we go to 3D, start rotation, I activate this. And then we can also randomize the 3D start rotation by going again to this little arrow here and say random between two constants. In our case, we're going to start with somewhere between 0 and 360 on x. We can also use 180, shouldn't be more than enough. 180, 180. And 180 on each of them three axis, I can see they look like, well, actually different every time a new particle comes out. To fulfill the rotation of fact, we can go rotate over lifetime or rotation of a lifetime activators. And we want to separate all of them axis and also purchase something random between two constants. So in that case, we can do something like a 360, 360 and 360 or the second one, and the first one could be 000. Now we can see they're rotating over lifetime, randomized into one or the other direction. Now, we can color tin or our particles. So we go again into the Start area where we're going to have the start color. In here. We want to choose random color. As you can see, nothing happens to random color. So we need to go and select the color field of here. Now what we can do is we can create our own colors. I have a preset over here, which you probably have already as well. But let's create one our own. So you know, what is this going to do? If you want to have a blending between colors, you can do so, or you can use fixed colors. So be always in between. Or we can now do is we can create flags on the point we are clicking. So let's create some flags over here on the bottom. On, I don't know how many you want. And then we select the flag and we pick a color over there. For example, we can start with red. So you can see some of them particles are somewhere between RAD and let's say yep, like rules or whatever color of a day. Now we can choose another color over here. Let's go around in a circle and that's take purple as an example. So the colors can be between purple and that. If you don't like full colors, you don't need to go fully into the corner. You can also do something like that. So they are like half toned colors. Literally. Let me go full color so we see the effect. Next one, I go forward inside the circle and choose to blue. And then go forward again through this circle and choose some, let's say bright blue. Maybe. I can go into the green area with this one. The next one could be a yellow color, and the last one is probably some orange color. Now I have literally any color I think I can produce over here. And you can see the effect already happening inside the scene. If you don't like, again, does blending in-between colors. So there could be also a middle tone taken from here or from anywhere in between. You can also go to fixed. So it will always take four colors, as you can see over here, in-between them colors. If you want to arrange them, you can drag these flags or can get rid of flanks, or just create even more flags. So multiple different colors are able to be taken. So now we are picking a fixed color from a gradient literally On a randomized way. So random color from a gradient, pretty good. Now we want to have like a one-shot burst. So only once it's popping up. And then we could say we reduce the size, we can give it some more be for something like Dad, we can make it slower over runtime and so on. But I don't go there. I just want to have a pop up animation to pop it up. I gonna go to the Emission tab I closed shape of, then go to Image. And currently we have a rate of a 100, or in this case over ten maximum particles of 100. Now, I want you to reduce this one to 0, so nothing is appearing. But instead I want to go with burst. I add a new burst. And now you can see the particles just burst out of the center, slide down and hardly disappear. To get rid of the hard disappeared appearance, we can also create a color over lifetime. Click on that activated, and now we click on the color again. Now I want to have a fade-out color. So the top flags over here are representing the alpha of the truth of the particles. As an example, we can go over here with this last flank and reduce alpha to 0 over runtime. If we want to hold the effect of that later on, we can take the first flag as an example and only fade out at the very end. Depending on the length of the effect of the particles themselves, oil, the amount of particles over here, we're going to see more or less of the effect. As an example, if we say the lifetime of the particles or even the duration is higher than the effect now takes two seconds and the lifetime. And when we put this onto a two of them as well, they fall down longer so we can see the effect lay and longer. But I want to stay with 11 and the duration as well as, and the lifetime. If you want to see more particles in the fact, you can say, Okay, I want to have a maximum amount or count of 50 or even a 100. So we have a bit more over our lifetime over there. There's one extra coming out as you can see. So count of a 99 would probably be better since the maximum particles is going to be kept by us to be 100. So taking 99 over there in a burst should actually fit the actual results of a here. The interval, maybe it should be 0. I don't know why they are sometimes less than more coming out, but I guess it's because the lifetime is over going the actual duration time. So if the duration is something like two, we should see all the 1990s coming out. And there we go. Because again, the maximum particles on screen are set to be 100. So we can put out a 100 day. If you don't like the amount I Reza prefer but less over here, probably somewhere between 30 and 50. We are good to go. Again, the duration can also be set to one. And we are absolutely good to go at this point. So the last thing is we don't want the animation to be blue bubble, so we deactivate looping over here. So it only pops once or only plays ones whenever we think we need to play this one. And the next part we're going to go and implement the liability of this effect. 35. #35 Activate Confetti: Welcome back to the course. In this part we're going to activate the effect whenever we do have a match. We do want to actually play the confetti when the effect is necessary, meaning whenever we do have a match, the easiest way to do this as we start with a deactivated affects confetti effect. Well, we want to have on is the option play on awake. Whenever we activators object, we want to be Play on awake already happening, but we don't want to lose the effect. So I disabled the object and if I go and enable it, it would start play. That's what we want. So deactivate that by hitting this little check box over here. So it's grayed out. Also makes sure that you hit override and apply all. So the actual particle fact is now part of our card holder. Now we can also check this. If that is true, we can go chunk here inside the particle or inside the cardholder prefab, we see affix confetti is already there. Now inside the current script, we want to actually activate or deactivate the ethics confetti whenever necessary. So let's take a look into that. First off, I go out of here and open the card script. You can double-click the card script directly here and that rain name area next to it. Or you could just go to scripts and double-click the card to open MonoDevelop or Visual Studio. Once the stock risk, once the card script has been opened, we want to add a new game object as being part of the actual card. So we create a public GameObject and this is going to be our f x I'm going to name it affects underscore confetti or just FX confetti. Like that. What we wanna do is we want to talk to the card by looping through it. Meanwhile, like everything is gone and open and so on and so forth. And we have literary found a match. We're going to say something like sound match, a fact. That's what we want to avoid. Actually activate if you want to have like popping up scores and showing up things. You can also do that directly on the card if you want to. For me, I just want to activate the actual Fx confetti over here. So we can name this or name the function activate confetti. You can name this also something like activated fact or pop card open note, whatever. What I want to do is I want to say is f x dot confetti, dots selective to be true. Don't forget to save the script. And now we want to go whenever we are actually update the actual cards or whenever we found a match that we activate the confetti per each card directly where we actually check for the match. And we check for the match inside the game manager. So let's open this one up in the cheque match function or in the cheque match co-routine. We know. And now note here that we do have a match. We're going to handle the cards content over here. But what we can also do at the same time, we can activate the actual particle facts. We can do this wherever we want to. Literally all of them is rather fast, so we don't need to really do anything too much. What do we wanna do is we just take literally the game objects or a part of the actual card script and activate content. So in that case, what we wanna do is we want to say he picked cards 0 and we want to do activate confetti, open, close parentheses and close the line with a semicolon. We want to do the same for the other one. For the second card, we do have an hour match. We can also command things out, something like active, I need the facts. And also you can command or anything else. And don't forget to save the script. So for now, we want to get rid of the card holder. But before we do that, we want to drag in our activate, our object of a confetti object inside the card holder slot. So we drag it directly in here. It's now bolt, meaning it's not presented inside the prefab. So we need to go override and say Apply all know it's not bold anymore. And now we can get rid of the card holder from the scene. Don't forget to save the scene if you have done any necessary changes and tried to figure out an actual pair of day and see how the effect is going to look. So I tried to find a match. And there we have it. As you have seen, the renderer actually was rendering the particles behind the actual 3D objects. That's what we need to avoid now by changing something inside the renderer, let's say order. To create this effect, we need to do two things. First off, we need to create a second camera, which is going to be the easiest variation or possibility for us here. So first off, we select our main camera and create a new camera. We can name this one f x camera, FX cam or whatever you please 9 or just for particles, does this actual cameras should only do one thing, render our effects. So in that case, we can go to clear facts of the second camera and change it to be deaf. Only. Next thing is we want to take a look into the culling mask. We want to see only one specific layer and not all. In that case, we can also tell the camera and not to see everything but the ones we want to see. First off, we need to take our card holder again and bring this for a second into the scene and open the FX confetti again. Over here we do have a layer system. We want to create a new layer. We want to name this one particles or affects. Probably affects is going to be a better one, at least for us at the moment. Now we want to make sure that affix confetti as part of our new effects layer. So we make it so that it is currently highlighted. Select the card holder again and override the effect, apply all. Now we go back to the effects chem, and we now go to culling mask and select nothing first. And then we only want to see a facts. Literally what we wanna do is we also want to deactivate the effects from being part of the main camera. So we literally deactivate the facts. We do have a mixed one, but the main camera should not render the effects because that is not necessary. Now we should see that the effects only rendering the actual Here are the actual particles over here. The effects can, does not need to be part of the main camera, but it's easier to rotate and scale stuff around the main camera than just like Bose second separately. So for the moment, we don't see any effect, of course. And of course we want to get rid of a card holder once we were doing our overwrites, completely isolated. And from affix cam, I want to get rid of the audio listener. Since the Unity engine tells us we have two in the scene that we don't want this actually not on the main camera. So I do remove the component from the affix camera, so we get rid of the weird messaging system. Now, let's test out if we find a match and see what the particles are going to look. I also try to be quick with pausing the game. Now you can see over here in the actual scene, you can see that the particles are rendered above the actual image component. That's what we want. We wanted to make sure that the particles are visible everywhere. Also, as you can see now, the effect works, weren't permanently correct as However it should do. So you can now try out everything. You can try to clean up the space and try to fiddle around with the particle facts. You can see that they are rendered above the actual main camera. Probably that has also something to do with the rendering deaths. So if you have any issues, the main camera is set to be death minus1 and the affix cam is said to be a death of one. These two are going to be these staff are going to be the ones we want to set. If we go with a minus two on the actual depth of the FX camera, we should see a different effect. The effect should be somewhere in like lying below the actual particles or the actual 3D objects to be rendered. Let's try that out. I'm going to pause. And I can actually not see anything. They are here. But you can see there are just not visible for the camera. In GameScene. Ethics cam is going to render this. You can see this whenever you have selected that. But as you can tell, the depths of the camera is just too low and it's not rendered correctly in our scene. That's why the affix cam needs to be on it, have a higher number than the main camera over here. Just keep that in mind. Don't forget to save the scene of everything works so far. And we are good to go for the next part. 36. #36 Stopping Timer on Win: Welcome back to the course. In this part, we wanna do one more optimization step to our game. Meaning whenever all the matches have been done and we literally haven't won. Because well, currently when the time is over, we go into game over. But if we are able to solve it inside the timeframe, then we want to stop the time at the point where ever currently it is. Also I added a small text field over here, both the terms, so just a normal text Mesh pro text about the terms, just pass it in. It has nothing to do with coding and stuff. Just make it a bit more visible. Again, you can also use this one and take this one as a time or again up to you. To actually do the change, we need to talk to our timer. The timer is sitting in the score manager. So we need to have access to the score manager and tell the score manager to stop the time whenever we have actually won the game. And my case, I've set this one to 120 seconds, so it's easy to solve a five by four field. To do so, we now go into the score manager script and we need to have a stop function over here to actually stop the game or the time. To do that, we need to have a public accessor for that of type void since it doesn't return anything. But what we can say is we can say stop, timer, open close parentheses, and open close curly brace. What we want to do is we want to stop the timer co-routine. As you can see over here, we were starting the time a coroutine whenever the game starts. So currently whenever we pop into the game, it instantly starts. So there's literally no countdown or anything involved at the moment. Well, we can do is we can actually stop the timer coroutine by using the call stop co-routine. And now all we can say which co-routine we want to stop. And that case in quotes, we want to say we want to stop the timer co-routine. Thus, only works if we are starting the timer, using the timer in a string parameter. That does work, actually all know, there is another way to do this is we can store the coroutine inside the score manager of here and then talk to it directly. The way it would look is basically we just say co-routine of a here and just give it a timer name or something like that. Whenever we start a coroutine, we set timer to be equal to start coroutine timer. So in that case, we don't really need to tell who the timer is or in quotes. We can also say timer like that. So we can call the time of this way or the other way. The easier way is the string way. But if we need to pass in any arguments, this is the way to go. And that case, we can also say stop coroutine. And now, and we pass in timer in here. Timer again is now the stores coroutine at this particular case. So we can set it over here by starting it. And we can stop it by directly talking to it. Don't forget to save. And now we just need to call stop timer whenever we have won the game, the game manager knows about it since the game is over, as well as the actual yeah, whenever we have won or lost. So if we have one in this case we need to say score manager, dot instance, dot, stop the timer, open, close parentheses and close the line with a semicolon. Now we can copy this one over here. And we can do the same literally on GameOver. Game over is called by the co-routine timer anyways, so we don't need to really take a look into that. Again, the score manager calls game over whenever the timer is actually running out. Don't forget to save everything. Don't forget to save the game manager. And let's go back to Unity and test it out. For the moment I going to choose a smaller play field so it's easier for me to test out, let's say a one by four, or in this case a two by four. So I have applied field of two-by-four of here, so it's easier to solve. Also, I changed a bit on the code, meaning two is the smallest number on each of them. So let's try out to find our actual solution for the spline field. And let's see if the time I was able to ask you run out. So I can do this one. I can do this one. And now we have one. We took or we used eight turns. Can see the timer has stopped. The timer is not updating its length over here. And we can now go into any other game scene. We can go back to the menu of a 102. We can pop up a screen to show that we have one, the actual game or so what we can put in some elements to the scene now since the game literary is over, so we are done with programming at the current stage. Also, we can take the current score and store this wherever we want to. 37. #37 Picking Random Sprites: Welcome back to the course. In this part, I want to do some additional tweaking on picking of the cards. Currently, whenever I have a two-by-two playfield and I press play, I generate a card playfield. But as you can see, it's taking a seahorse and the star. If I now press Play once again, I'm going to have still the sea horse and the star. So what I want to introduce or implement now is that the game manager or the card manager actually is picking from the sprite list randomly. There are multiple things we can do with data, but we want to make sure that, for example, is one day it's going to pick a top shark and another day it's going to use a squared. So basically all of that is content where we can let say, yeah, use multiple different card decks, literally and not going top to bottom. As you can see, the top one over here which is underwater set 14 sprite is going to be, I believe so the actual star. And the second one in the list, which is going to be again seen inside the game manager. The underwater starts at 1, is going to be the seahorse. This is the order at the moment where the sprites are going to be picked from. What I want to do again is I want to pick randomly from that list. So we can do randomly picking inside our creation of the playfield. To do that, we need to go and open the card manager script and see where the create playfield is going to be. First of all, we're going to do at the moment is before we do the shuffle and before we actually pass out the cards to any position randomly, what we do is we're going to pick from the sprite card depending on wherever I at the moment is. Since the sprite list is sorted in this case, we don't have a shuffle for the sprite list, which would be one way we could shuffle the sprite list at any time. So in that case the indexes go, we are going to pick from our Reza different. But probably shuffling the deck is too much in that case. But what we can do is we can create another for loop in here. And beforehand we copy the sprite list and then we pick randomly which card we want to pick beforehand and fill in a corresponding list. And in that case we also, whenever we, we pick any index randomly from the card list lines, that probably is a bit easier and in this case a bit more fun. Also, we want to avoid doubles, so the same index cannot be picked twice. In that case, per each iteration, we need to clean up the actual picked list. So how do we do this? First of, we do have our sprites list, and that case it's not a list, it is an array which is bad. So for the moment, we're gonna go and take the sprites now. And I make this one not an array but an actual list. So we say public list of type sprite. The handling is almost the same later on. But what we now need to do is we need to make sure that we create the sprite list is equal to a new list of types. Bright, open, close parentheses, close the line with a semicolon. So as you can see currently we are still picking from the same list. We just made it not an ALS button or not an area about the list. Now we can easily copy that oneness and manipulate the copy per each iteration. So in that case, we're not picking our cards later on from the sprite list. We are picking it from a temporary list. So I create a new sprite list and here, which is going to be of course of types bright. Then we give it a name, chimp sprite list, all term sprites. And we need to initialize that to be a new list of types. Bright up close parentheses, close the line with a semicolon. Now we want to fill term sprites since currently the term sprites list is empty. So we can say Tom strides toward add range. Now we want to add the range of the sprites list we do have. So we literally copy over and add the complete range of the size of the current sprite list into the temp sprites. Now what we wanna do is we don't want to pick from a sprite list I over here. But we want to literally take a specific randomized in next to pick from it. Well, at least for the moment. So to do that, we need to add in a bit more code inside this range parameters of the day. So first of all, we want to create a random sprite index. So we is going to be of integer. So we say rand. Stride in x is equal to. And now we're going to put in any random number again between the 0 and the maximum size of the actual term sprites size lines. So we pick random dot range. Now the range is going to be between 0, the zeros index of the list until maximum length of the list minus one. In this case, temp sprites dot count. The reduction of one is gone through the random.randrange automatically. So when the sprites list size is actually 10, it reduces as automatically element nine. So it reduces this by one. Keep that in mind. Now we have this random sprite index, and now we want to choose here wherever we actually get or set the actual card to be the temp sprites in square brackets. And now we don't want to pick I, we want to pick the random sprite NX. Once we have taken this one from here and we have added the car to the bank, or let's say, before we add to the current DAG, we want to remove the actual sprite from the term sprites list. So in the next iteration, we don't have the same possibilities. So we say terms Bright's don't remove at, at, remove ads. We're going to pass in the end next, which card we want to remove, in this case, the random sprite in next. So in each iteration through the secondary for loop, we create a new random. And next, depending on how huge the size of the actual term sprites list is going to be. Then we set the card to take from that by using this calculated random index and then we remove it so we can take it, or we cannot take this one in the next iteration. So the temp sprites list reduces itself and we do not touch the actual sprites list in. Again, don't forget to save a card manager and let's get back into it and see how it works. We want to take care of that the actual sprites list with all its a set parameters is not getting touched or even resized. So keep this ten size of a here mind. So we don't want the term sprites less to actually take the problem. So what we now can see as another issue, of course it's taking now random cards but are not the correct stage. So what we want to do now is we need to do this calculation, not an each part of their per each card Literally, we want to need to do the complete calculation like over here. In the first iteration. We first off take this index and we want to remove that one whenever we are literally done with the two cards creation of a here. So probably directly at the end of the creation of the card. So let's try that one out. So we go into the first part pair. So in this case the pair amount per each iteration through the paramount, we calculate a new index based on the index. We calculate the second for loop after one of the iterations of the for loops is done, we remove it from the sprite list, go back into the next one. So let's try that one out right now. Also again, we don't want to see any touch on the sprites list or re-sizing on the sprites list. Now, as you can see, it has taken to sharks and it has taken two of these are extra creatures here. So the spiky ones. We also want to make sure that the actual ID of the corresponding card holders are going to be 100% Lee correctly sad. So I go over the n to the three dots and select debug. The card ID over here is now Id 0. This one should also be 0, and the card ID and the sharks should automatically be ID1. When I now press Play once again, I should see any other cards randomly picked, picked, or taken. Well, that's what I hope. And there we go. So now we're going to take these two. We're going to take these two. And so it's now randomized. And a total manner. Of course, the positioning and stuff has not been touched at this point. And how the playfield is created is what we currently don't know. So again, we copy the current sprite list, pink, any random numbers and values. And in the end we should see some yellow mixed creatures over there with any other creatures and picked automatically and picked randomly. Same should happen if we are going out of debug mode again to normal mode. So we don't get confused in the end. We should also, when we have a bigger play field, like a four-by-two or four by three, probably, we should see different texts popping up here as well. I press Play and now we can make a screenshot. We see, okay, we have to raise two stars and so on. And in the other way, we probably don't have race and stars and stuff like that. Now you can see we don't have any ray, but we have all the other ones of the also we don't see any doubles, which is the most important thing. Whenever we do such a copy and paste content, since we removed the latest pair we have picked. And we can do this testing for quite some time. And 1%, it makes sure that none of the actual cards have four in total over here. 38. #38 Game Over Panel: Welcome back to the course. In this point, I want to start to create a game over screen as well as the winnings screens, two screens literally. So we basically copy overlaid on the content of them. So what we wanna do first is inside our Canvas, since it's a scale of screen size, we want to create an image which stretches over the complete screen. So we go to UI image. So what we can name this one is, let say Game Over panel. In this panel, all our objects, all our buttons are going to be inside. So what I want to do is I want to stretch this over the complete surface or the medical aid. In that case, I hold on Alt and then select the anchor or the Anchor Preset of uniform stretch like this. Since I want us to be laid over everything, I need to make sure that this was one is hierarchically under all the other ones as well. Also, what you want to do is you want to earn able recast target, so we cannot touch anything which is behind this object or this extra user interface. Now I go and change this one to full black and reduce the alpha at least just a bit. Only see crisp content of the day and the other part on the other content and the background is still visible. But again, we want to see a new screen there. With that said, I want to create another panel which is actually just representing our game over, let's say input in which we're gonna put our buttons and all the other good stuff. If you want to have cleaner or better input, you can also make use of different layered grips. But for the moment, let's just lay out our game over screen. What I would like to see as probably some header and the top, as well as the field in the center, which probably tells us about the terms we have taken or use what our final scores, as well as what the actual time is left, as well as probably something like a game overs yeah. Visual for that. In cases of design, you are totally on your own with dad has since your game may not match at the end to the design we were choosing beforehand. So what we can do is we can take this image over here and anchor it onto its current position based on the actual panel below it. We're going to use these anchors again and set them over here. Just tried to be as precise as possible wisdom, don't rotate them if you cannot reach points or circle or content at all or one of them. Yeah, little triangles. Just go closer by scrolling in and see where you are. Make sure that you only do this whenever you are done with the rest of the settings. Or you can also do is you can duplicate the actual image of a here and bring it above it. Maybe it was a little space. Again, you can also use a vertical layout group for that. And here this is going to be literally the tax box in which I want to pass over the information like, Hey, you are Game over 4 Design cases. I first go and center the actual objects. Anchors, or just use the existing anchors, which has been copied all over. Later on, you can also go into that stuff and create your own set anchors automatically coding, for example, but that needs a lot of work. So whenever we now go into any aspect ratio again and we tweak and switch and do squeeze around all our content over here, we should see now a visual above it as well as we should see now that the interface stretches so far correctly. Going back to 16 by 19 and further doing with our design, I have created a little background image over here, which you can also create on your own if you'd like to. In that case, the image I offer is just fitting the design of the rest of the game in our textures. You're going to pop in my background image if you want to, or use your own or use none. Totally. Again, up to you. In my case, this image is going to be a sliced image. So we need to go into the Sprite Editor for sulfite changes one again to Sprite 2D UI keyboard signal, but open Sprite Editor, after applying the change, it has a size of 512 by 512. So it looks a bit pictorially over here, but that's totally fine. Now I want these anchors to be in the center, as you can see, at the point of 0.56 over there. And got to copy this 5.6 and put this into the top to the right and top to the bottom. So the sliced area will be somewhere in the center. Everything else will stay on to untouched like all these corners over there. Play around with these. If you are unhappy, apply the changes and go back. Once we own this one image or that one image, I want to implement this background graphic to him. So what I can do is I, first of dragon, the sprites into the image. And so currently as you can see, it's sprite sliced. We could also go for tile, but that doesn't make sense. But as you can also see, the scale is actually huge for that small image of here. I wanted these corner pieces just more like a highlight at all. In that case, I go scale down my image over here quite a bit and then resize it back to where I want this to be. So on x I try 0.5 and same on y, 0.5. If I'm happy with that, I just go up again and put it where my anchors are. So as you can see, the center is area of content. If you like it the way it looks. Well, you can do the same for the upper one if you want to. You can also play around with the corners over there or you can even make them one even smaller in the long run. So as you can also see, the scale is now smaller than the actual initial own game over panels. So slumped, do this like internally as an extra. Maybe I also try out the points three over here, and x and y, which probably looks a bit MOOC good. But again, this is something we need to take a look onto our own. It's something we don't know whenever we haven't used the ad. When I go in and maximize on play and play over here my game, I want to see how the result is going to look in the end. Looks kinda crisp, BAD. Well, maybe 0.5 is a bit better in this case. So I probably change my mind later on. Again, this is something you can play around with on your own. So I bring back the size to its size where the anchors are. They are is like a snapping happening to this little dashed line. You can see the original dashed line on the outside. I cannot touch that, but it was like here. That is what the original size of the image would be. Once again, you can do the same for the other one over here if you want to. Just put it in and see how it looks, scale it down to probably 0.2.2 or maybe you keep it and why on one? So it looks quite nice on this part here as well. So we do have this fitting pieces of the again, if you don't like the look, just change it to whatever your needs are. Now, we can enter a little yeah, texts intuitive, but since status no scaled over x, I want to make sure that I create that on top of that. So inside the game manager, which has no scale, values are so weird scaling at all. So I go to UI text, text much pro, put this one in wherever I want us to be and pass in my text, the text I want to see, for example, game over. I want to make sure that this one is of course going to be centered of the text field. So I can play around with the size overall laid on as well. Also, I'm going to set this one to auto size. I can scale up a bit here and there and bring this to the corresponding spot. What you can do with that as you can make that one child already of the current image of a hill like by just dragging it under it. But as you can tell, the scale could be wrong, as well as the actual visual could be gone at this point. Let's try that out again. Now it's part of this image actually. So I want this top bar to be the factor for this. But as you can see, it's hard to fit it over to the correct one. So now it's going to be here. I want to rename this one to be the top bar. So I know what it is about. This is like the bottom bar on bottom box. Like that. The final step is something like, Hey, I want to try again a text. So then you have the possibility to try this round again because this is like the game over screen. So we can create a new UI text much pro panel. Pass in any, any naming, try again text, something like this. Then it can pass in. Try again, question mark. Try to avoid any typos, and then position and rescale and so on. So again, I go with auto size, I go with center and center. Then I put this one in the center of the card. Or if the bottom box and hook it up to it so I can center this one based on the current box like that. And the last part is putting into buttons or maybe just one like a retry button button, another one to actually leave the game or go back to the menu. In that case, I select the Game Over panel again, go to UI. And now I can make use of a button, or in our case, a button with the text Mesh PRO component on it. It's more crisp and the end, we can make this one a huge and small and put this wherever we want to. We want to try to set it to a height of about 70 probably. And also make sure that the taxpayers PRO component is set to be auto size. And then we can pass in something like back to menu. No typos. You can also pull in any other graphics and good stuff around it. Now we duplicate the button, bring this onto the other side of a here. And this one is something like, well, retry. When we go, go with auto size, you're going to see there could be some issues with the sizes over here inside the text elements. So maybe you want to fiddle around with the maximum size. If you're using order size as an example, I can try to use one specific number on the text fields. Like if I earn able order size, I can say I don't want this to be higher than 40 or maybe 35. So what you can do with the other side here, you can also make it so that it is never going over as 35 over here as well. So probably the sizes are going to fit now, the other sizes. Now, you can also color code or color tint these buttons. You could even animate on mouseover. But again, this is content you can do on your own. I give mine probably a green touch over here, maybe a lime green, as well as I can make this one a, another color, probably a blue tint. But as you can see, the blue doesn't really look good of here. So maybe I make this one kinda matching my design. Or what you can also make use of, again, is the actual sprite from the background. But also also here. It is hard to see and hard to tell what is water, what is where. And we can also squeeze down the actual button over here, but the image needs to be a sliced image. But as you can see, kinda looks kind of bad actually or wrong. So probably we need to scale around here a bit to fit the actual scale of the button we want this to look like. So probably somewhere like a point to on the button could be good. Since a 0.1 doesn't look that good. Point too doesn't look good either. So there should be some number in between 0.51.5 probably skirt. Well, we need to do is of course you need to rescale the actual gather menu texts in the center in its corresponding size, of course, and bring back the actual part of the day. So squeeze around with that. I also give it a white tents and status. A bit simpler to see are easier to see probably. Also the button looks a bit darkish over here of this one button since there's this orange tint above it. So I gonna make it bright again. So again, it's going to fit my actual needs. And if you are not so happy or even happy, you can also do something like I. You can duplicate this button right now, Control D for duplicate. Bring this onto the other side of the screen. Kind of like a same distance to the center over here. And now we can just say this text here is going to be a retry button. And everything should now look kind the same in our complete design. 39. #39 Fixing Game Over Panel: Welcome back to the course. In this part, we want to take a closer look again to the design, since D3 aspect is actually now starting to come onto our ruin, our actual visuals, as you can see, the buttons to move. The try again, kind of stays in the center of the game, overstates in the center, but the buttons to move. So go back to 16 by nine, so everything is in place. We want to make sure that the buttons are part of the bottom panel first. So the bottom box actually, so we take them too, Bring them or make them child of the bottom box. Now I try free aspect again. But as you can see, they still move. This is actually not what we want. That case, we're going to take them buttons again and to use these little anchors, position them where they're supposed to be. So to keep the correct distance. If you don't see them correctly, just zoom in. Don't rotate by mistake. Going to take the other ones from the center right now. Zoom in to see if they kinda match. Again, don't rotate by mistake. And now let's try again. They are still moving quiet around. So I go again back to 16 by 9. I'm going to move them a bit up. And I want to again make sure that they are part of bottom box. So now the bottom box has another different scale, the hair, but the buttons should now be calculated based on that. So it try again and fit the actual anchors. Let's try out the free aspect again. I can't see the buttons stay where they supposed to be. Even if we go up and down, they so they stay there and they scale down. Pretty good. Lee. So the next one is we want to make sure that the actual game over panels stays where it is. And that case, I just create another panel which is going to sitting under the actual panel. So I go create new UI image. And now I drag this until I hit this orange line, as well as the other orange lines as possible, that doesn't work. Just take them and roughly bring them into the corresponding sizes. So this is going to be my placeholder for the actual images below. So first of I is try to snap my eye pieces here. My little anchor points to the corners where our images. This is going to be kind of a holder. I don't know a name for that at the moment. And now I want to take the top box and the bottom box and make them part of the holder. So top bar goes to holder, bottom box goes to hold as well. We see a little bit of a see-through over there so we can now manage everything over here. And also now you can see the actual anchors are a bit different now, so we bring them into the corresponding sizes and try to match them correctly. Same for the bottom box. The bottom box is now a bit off of a hair, so we snap it to the side. Try to be a bit precise wisdom. Same for the other side, for the big box. Bring it over here. The bottom and the corners here as well. Snap them and now use the anchors and position the anchors and to the corresponding areas. I'm currently doing this unfreeze by aspect ratio, which you probably should not do. It probably is better to do this directly and 16 by 9. So you have a better feeling and no weird things going to happen. Now we have a little gap over there which is good. But the actual holder image is now trying to hold its position and takes all its child objects wizard. So let's try that out. As you can see, the box, the bottom box is stretching, but the actual holder of the game object is going left to right and right to left. So when we go in 16 by nine, every scene should look okay and kind of correct. So we may need to go and rearrange some items in here. Make sure everything fits. And don't forget to save at the first place. To make this whole stretchable or let's say more stretchable. So it also is able to fit the actual free aspect ratio. We need to do some different settings on it. To do that, we first off, and this is probably the easiest. We do a separated copy out of here just in case like if you would ruin anything on the original holder, that wouldn't be a problem. So we could go back at any time over here. What I want to introduce now is several different components. We need to set all of that stuff up. The first thing on the top bar over here is we need to do several different things. First off, I want to get rid of the scale first, since that is runing the upcoming system. So first off, I type in a one and everything will be super stretched. So I'm going to go back and bring this to where it has been before. I don't touch the tax yet. I just want to touch the actual bottom. Also, we can now take the tax then scale is one to one here as well. And bring this like over the complete field. Just do automatic stretch, which is going to hold and right flank which is uniform stretch where to wherever the top bar is. Now we do have this squeezed square or the excretes corners, which you want to fit by tricking the pixels per unit multiplier. I just bring this one a bit down until they start to resize themselves. So somewhere around 5.5 is probably a good number for the game over one. Next one is the bottom one over here. I wanted to the same before I do anything else, I want to make sure that this one looks like it does before or like it is currently doing. So we do the same. We first off get rid of the scale to 11. Of course the other pieces will come with it. Then we go back to the snap diarrhea. Make sure again that you are in the correct aspect ratio. The buttons will disappear in a moment, but that's okay. We're going to fix them later here as well. Now we see that the corners are two huge as well as the text in the center. So we go and reduce the pixels multiplier to kind of fit how it looked before. If you're unsure, you can just use this little eye symbol, hide the one, and then enable the other one and over touch or see who has what size and the past. So this one here had a bit smaller corners. So again, this is something you want to check out on your own as well as it has a gap over there. We take a look into the cap and a moment afterwards. So a de-activate your other ones. So I don't see this and activate the bottom, the copied border again. So I'm going to go and select the actual bottom box and go far away or bit more lower, probably around two in the pixels per unit multiplier. Now the texts in the center of the actual, of the actual bottom box is going to be too huge here as well. So we can literally scale this one down. So it fits and looks a bit better. And then we reposition this one, maybe in the center or somewhere. And now we need to take a look into the buttons as well. Since the button should do the same, we need to get rid of a scale first. Let's start with the first button. I put a 1, 1, 1 on this button. Now I can see the corners are hard to catch though. I tried to bring it up a bit. And now I can resize that the tax is acting weird, but that's fine. We're going to touch that in a moment as well. I bring this so that the actual corner pieces are here matching again. So I drag it as, as long as it fits. So for the button text over here, we're going to do the same. We get rid of the actual weird scale. And now we do have a cross in the center, means it is rendered from the wrong side. So I drag it over to the other side. And then I use uniform stretch like that. And the final part is I want to reduce the pixels per unit, per unit multiplier. I want to bring it smaller until they start to scale down. So I know I'm at the correct spot. If you don't like the size again of the button, you can always go and make this one a bit bigger. Which is not a bad idea. I guess. We just need to make sure that we take the actual corners or the actual anchors wizard. But as you can see, the button was a bit more to the side, so I need to re arrange data bit. Since currently the button is part of the whole the object. For the retry button, I just do the same thing. Or in this case I just get rid of the old button, Duplicate the current button and bring this over here to the other side. I tried to fit or see where the other lines are going to be. And now I just changed the text inside it. So I just typed and retry again. Was a big R or not. Again, totally up to you. Maybe you're also going to put an exclamation mark. So now we just need to anchor the retry button to the correct spot. Same for the other side, just so that it is taking place. So with that other one deactivated, we can also rarely go and try free aspect. And as you can see, it's still kind of stretches, but it doesn't do it, correct. I mean, it is close to where we want it to be, but it still is not 1%. 2. To get this one working, I want to add a vertical layout group. First off, I go back to 16 by nine aspect ratio. And the first thing I wanna do is before I do anything else, I want to take the top bar and the bottom box and add of a layout element to them and select preferred height. Now with that said, we should be able to put on the holder of vertical land group. So type in perch for vertical layer group. As you can see, it doesn't really fit and everything is now gone literally because the bars on the top as well as on the box, they don't have any wastes, they have a negative with. So what we want to send me the holder actually, first two, child control the width of the object and the height of the objects. Now, as you can see, it doesn't really want to permanently work as a church. So we now get rid of this button on the child widths because it's going to scale automatically afterwards. Well, that's what we hope. Now we want to check why is the top bar taking half the side oil size than the, as the other element is going to do. This is because of the split and the center. The vertical layer group is trying to arrange that. Also, if you want to, you can put a small spacing in between those objects by using this little spacing of, let's say, five to 10 just for the moment. And you can also see the other textboxes and so on are not really affected, not at all. So the final step, as we now want to make sure that the top bar has the size, we give it two. In that case, we do use D layout element for that. We can, for example, say we want to have a smaller preferred hide on the toolbar. Currently they do as the same thing. So let's try. We take a look and reduce the number of the actual top bar over here until it hits or fits our actual design as we want. As you can see, somewhere around 90 seems to be a good number for the preferred hide, the bottom box. And it's actually also taking care of another element or another, or its own size literally. But before we actually can set the bottom box correctly, I deactivate the preferred height and just want to make so that the top is really 10 percent HLA matching. So in that case, probably but smaller than I thought that might be. Now we can activate preferred Heidi again. And as you can see, they're squeezing away each other. So I just try again. Try to find a sweet spot between the preferred height of the bottom and the top box. We don't need to take care of the left and to the right. Just make sure that the child control size of the height is going to be driven by the vertical layer group. So these should be your settings at the first place. Now with Dad sat where you want to save. And we want to go back to a free aspect and see what's going to happen. Now I can see everything stretches left to right and up two down. Of course this height is now not want percent the matching, which is okay for now. But later on you can take a look, a bit closer look actually to the actual fitting parameters for your needs. And the normal aspect, everything looks good. In any other aspect that should look good as well. Probably want to take the text over here from the GameOver text and make this one aligning to the center of the text-box. So whenever it scales down, even in free aspect, the game over tries to stay and fit in the top over there. Although you can't see the buttons do look good and correct as their current positions are driven by the box as well. And the triangle and field is trying to stay real relative to its center. So if we would put it down or up, it tries to stay there. For example, we can put it like here. And it's trying to stay in the center of the box. Now we can get rid of the other holder by just deleting it. And we're good to go. Again. If you don't feel that is going to be correct, change it until you like it. I guess we are fine with that. If you are going in portrait mode, of course, choose a different design or just as different setting or basically the same setting. Again, warm presently up to you. 40. #40 Win Panel: Welcome back to the course. In this part, we want to create a second panel which says, Hey, you win. As well as putting probably some more graphics if you want to in a central like a, I don't know, a golden star or something. Again, this is part on your own. You can define the actual game over and the wind screens on your own. And you can also pass on again, how long did you apply it? How long did it take? How much turns that you got? And even showed the score if you want to. And you can save it somewhere if you want to as well, you can implement literally anything you want to do. So we can simply duplicate this GameOver panel and nameless 1 when panel in the wind panel, we can now rename the components, taxed elements. So in that case, GameOver would be something like you win or congratulations or something like that. You can also do congratulation here as well. And probably you can again also introduce another image was a graphic, something where whatever you please and like make it, make it so that people know other players do know, hey, I'm good, I'm, I'm the best. I don't know. So they feel good. Probably, maybe you're going to implement some graphics from any type of design for this one as well. Instead of retry, we can also say something like play another round or next round. So basically we do the same we just laid on redo or we go back to the main menu. I'm jumping something like that. And that's basically everything for the wind panel owner. Well, that's not nothing more needed, but later on just we need to connect all the same things over the like, all the code to load the next scene or a reload the current scene or go back to the menu tissues, maybe another game or something like that. Now some things we probably want to introduce into the congratulation screen, probably in the background, which is going to be also some confetti effect may be. So whenever we have one, we can make use of that and create a bunch of confetti over to the complete screen. There are different possibilities to do that. We can actually place them directly on the playfield wherever we have cleared everything and just let shoot it. We can probably also connected directly to an object on the actual Canvas or any other game objects in the scene to make it so that the confetti comes maybe from all four corners or normal game screen. So they would probably sit down to tear down and I don't know, fire in the center. It's like you can also implement any kind of a firework if you want to. But that's what we're gonna do in the next video. 41. #41 Win Screen Confetti: Welcome back to the course. In this part, I want to create the confetti effect, which hopefully appears later on whenever we have won the game. Or we can do is we can copy the confetti of fact, we just created with the card holder and probably give it a bit more beef. So I opened a prefab of the card holder and take the affix confetti over here. And I tried to copy that by Control C hitting. Now I get back into the scene and try to create an empty game object. I just don't name it at, at the moment. I don't want to try if I can copy the confetti wheatgrass created or paste it over here by hitting Control V, which absolutely works. I want to earn able affix confetti over here. I want to make it part of the object. So now we can place the actual object wherever we want in the scene or based on the actual Canvas, our scene as rather small, so we need to get out of here and see where confetti currently is going to be. So I reset this 12 zeros 0000 at the very first place. The actual transform of this object, double-clicking the object will bring us to the position where it is. As an example, we can create this confetti light on starting here on the side of the playfield. We can produce any kind of a confederate field. We can also can create this out of the center or anywhere in the scene. So it can be a much more or much less confetti. That depends again, up to us. We probably want to set this one to be looping, but also give it a bit more duration in between. So it takes a minute. I don't know, three to five seconds maybe or maybe every two seconds we should. New Year, new thing about the confetti, although we want to reset this TO, it's going to be in the center of the game screen. So we can reposition the actual fact. Also, we can take a look, okay, whereas the rotation or the actual shapers in which direction, as you can see, you just rotated by 90. So we're going to first off, bring this one upwards. So it looks hopefully correct. And now we can also bring this more into the center. So probably do a rotation over 10 to 20 degrees, so it shoots inside the direction of our game field. Can also duplicate this one. We can try to apply that so we see how it would look. And we want to set this one again, two looping. And we probably see something going on here in the game scene. Is the fact that is not as nice as you think it's going to be because while the camera itself is going to be rotated, we probably want to, I don't know, switch that view a bit. I don't know. But that is something you can take a look into on your own. I going to create another copy of that. And another copy of that here. And again, we can put this directly over there. We can also let it go down next to the camera, something like that. All depends on the rotation of the camera and the look of that is going to be based on that. You can also lift it up so it's probably looking a bit better, whatever and bigger. I'm going to duplicate those three object or this one object with the confetti on and put this onto the other side here as well. But in that case, I go with a rotation over x by the opposite to be something like negative 74 or something. So if we would go and be maximize on play the screw. And I want to see how the effect is going to look whenever this two objects are going to be active. So they're playing all at the same time as you can see. So we probably can offset them a bit as well. So for off-setting it, we can go to the Emission tab and we can say something like this should start at, I don't know, 0.1. This, so to start at 0 and this can start at 0.2 or something. So the way it is 0.2 before it actually starts to emit. Again, we can do this other thing over here as well. We take the actual time here and put this on lepers be at 0. And we take this one and put this onto a 0.1. And this one on a point to in the Emission tab. Let's try that out and see how high the offset is going to be. It is okay. Maybe you want to introduce or put in a bit more to the lifetime of the effects. So I select them all three. And I tried to increase the lifetime of the particles to 0.5 something, though they fly but slower and fill the screen a bit more. Even a point a is probably a good one. Let's try again and see how that looks. Actually not too shabby. Again, you can put a bunch of particle facts into the scene however you please in like these three over here seem to be rotated. One too much, so I tried to select them all again. Ashley, they have been rotated to let us know they are a bit too much. But yeah, that's basically what we can do with DOM if we want to. Now we can combine them and name this object. So this going to be our main object. The other one is still over here. I just made a child of it affects confetti when we're just going to be the object we want to apply whenever the round is over. Again, if you do, if you're not happy with the positions or something like that, you can always get into. I go to global so they have a different axis. I can let say take this over the x axis and fill the screen a bit more with our confetti effect. Also, we can lift this complete object of it up so it's closer to the camera. The things, the actual confetti look probably a bit better and closer to the camera. So we might also be able to bring them anywhere. We could even go and resize them a bit. So they are more like present inside the scene. Currently, we don't see them much because there are two when penalties over each other. So maybe we can set the start size over here to be point 2. So we have something like a 0.1.2. So you can tell the confetti is no way bigger than it has been before. So pretty long. It looks pretty good so far, as I would say. 42. #42 Show Hide Panels: Welcome back to the course. In this part, we want to take care of the wind panel, the game over panel, as well as still when confetti. What we wanna do is we want to activate confetti by code. We want to activate when panel by code, whenever we have one round and if we lose, we just want to see the game over panel beforehand. We want to deactivate literally everything just in case and probably taking the confetti and make this one at the very start already disabled might be a good choice of a year. Otherwise, we may see some particles fly at the game start, even if we don't want to see that. We can do the same with the game over and the wind panel. We can set them to be disabled on start. We can also do this by code. That's up to us. All we wanna do is we first one to go into the game manager because the game manager knows that the game is over. So for the moment we don't have any connection to any of them. So what we wanna do is we want to create three objects over here and three game objects. The first one, it's going to be our wind tunnel. Second one also needs to Republic game objects, the loose panel. And then we have the effect. And it's also the game objects. When a fact, something like that. You can name them again however you want to. Whenever we do have one over here, we stop the timer. Of course, we want to open the actual, the correct the correct panel or end. We want to activate the object. Like the wind effects we want to set is our wind panel dot selective Haagen-Dazs parentheses to be true. Same for the effect. I don't know what I renamed it. I guess I named that when a fact dot set active to be true here as well. When we are GameOver and game over is true. Then we want to pick the loose pentanol over here and open this one up. So those panel not set active to be true. Don't forget to save and go back to the start function. I don't have a start yet, so we could do this and awake, but I don't want to waste awake for that. So I used to start and close parentheses. Open, close curly brace in start. We want to set just in case when panel, That's sad, active, totally false. Lose panel dot selective to the force. And the when affect. Dots are active to the force. You need to test this out. Was the winner thanked. Usually we don't need to do this, but probably we want to and we can test this out whenever we don't activate or deactivate the F exponent from the very start on. So I unable when affects confetti, I go to the game manager and I set things up. So in Game Manager, we now need to pass in all the three objects do when panel, the layers panel and the wind effect. So the wind panel again is the one over here. We just drag it over. The loose panel is the one which is called Game Over panel. So I want to drag this one into the loose panel or GameOver panel. Now we have the wind effect, which is fx confetti over here. So make sure you hit the correct one. If we now press Start, nothing should be visible of them. As you can see, the actual wind panel is gone, the lowest panels gone, and the effect is not available or not active at this point. Now, we can try to win. You can make a super small game actually and see how high or how good the effect is going to be in the end. So I played until I got the last one. And now you can see, Yay, You won. Congratulations. And a background. We can see the flying particles. And now we should be able to press on these buttons. They should gather feedback by pressing on them, but they don't do anything. Also, we have the little white line in the center which we probably want to deactivate as well. So we don't see the actual panel behind it at all. To deactivate that line in the background, we can go to 2D view just to make sure and try to find the whole object in hold the object, we just deactivate the Alpha channel to be not 0 but one. Or probably it's better to make it a 0 completely. And of course we need to do this for the game over panels. Well, So thank the holder and set alpha to 0. So we can literally see through the actual piece in between. And now we're so far so good. Then the next part we're going to create the functions to actually go back to the main menu, even if we don't have one yet, as well as start a new round when pressing the next round button or even the retry button over there. 43. #43 Button Script: Welcome back to the course. In this part, we're going to take care of the two buttons on the scripts for them. First off, I want to create a new script, C-sharp script called menu. Menu items or menu buttons or just Menu. Let me name it menu buttons. And of course open this wonder MonoDevelop officers to do. Wonder Jasmine open, we wanna get rid of starting out data at least for the moment. We want to create as public functions for different buttons and corresponding things. Each button can take one argument as a parameter. So what we can do is we can recreate to seen loaders. Literally one is going to reload the current scene and one it's going to load a specific scene. So in that case we can say public void star, or actually load scene or load game, whatever our game mode. Let's name it load seen in here I want to put in a string, parameter, string and name this one scene seem to load. And of course, now we want to load a scene. To load the scene, we need to use the namespace using Unity engine, top scene management. This is necessary. Now we want to load the scene, so we need to say Scene Manager. Load scene. And now we want to say which Scene 2 we want to load. In our case, we can pass in, as you can see, a building the ax or a scene name with multiple different parameters and even a synchronic movement or loading of we need, but we don't. So we just pass in the scene to load. And that's everything we need to know the scene actually. We can now also load or reload the current scene. We can say something like public void, restart level. I'm going to put a big R and the beginning of the year, so it's written better. And open close parentheses. And that case we're going to say scene manager dot load scene. And now it's going to be special in this scene to load or where we usually would load the scene. We now need to say the same thing. We need to say first scene manager, but now we need to tell gap the act of scene whenever the act of scene as we get it. And now we can take it's built the index or its name to reload it. So we literally load the scene which we currently have active. And in this case we pass in the string name parameter. This is how we can restart a level. Later on if you have like multiple gain molds like an easy mode and median mode, a hard mode. You can easily do this by sin to load of by putting in the corresponding seemed names. Don't forget to save the scene, the script. Let's go back to well, wherever we want to do, handle the scene management. You can put this if you want to directly inside the game manager. But you can also put this directly on one of them buttons. This basically does not matter at all. We want to have one of them here, one of them here. So we just want to have, but we only want to have one script running. So in that case, I take menu buttons and put this also into game manager. Now, let's start with the wind panel. Since it's currently in the front. I wanna go back to menu over here. In that case, I want to activate the onclick event by hitting the plus and drag in the game manager because it holds the script. Now we go to Menu buttons and we say load scene. And now we can pass in the string parameter, for example, a scene called menu. We can also do this for the other one, but this one needs an onclick event. Also Dragon Game Manager. Choose menu buttons and say restart level. Okay, So the wind panel is now done and gone. We can now take over to the game over panel. I deactivated the wind panel by just hitting or deactivating it over here, but you can also just hide it with the little I stumble over there. Maybe that's better. So you don't forget to by mistake not activated, even if that doesn't make sense because we activated when needed any ways. So in GameOver panel, we select back to menu, select onclick event and pass in the game manager. Go to Menu buttons. And now we want to set load to scene or load any scene I'm going to pass. And again, menu. We take the other one which is going to retry is basically also restart the level. So I pass in again the game manager, select the function menu buttons and say restart level. Don't forget to save the scene Control S for quick save. And you can always try it out. So you can apply a big round or a small round to test things out. The easiest and the fastest way to test things out is of course, going into the game manager and reduce the game size to a two-by-two. Two-by-two for me is going to be the smallest setting. So we have at least two pairs to complete. Now we get, hi, congratulations, you won. And we can now say we want to play next round if I do so, the complete sin results with a different setting of a here. And yea, complete. If I now press on back to mania, we're going to get a scene's menu couldn't be loaded. This is the red argument over here. This is because the menu scene has not been created by us, but that's what we're going to create in the next video. 44. #44 Menu Scene: Welcome back to the course. In this part, we're going to create a simple menu or forum. Again, the easiest part is first we need to create a new scene. So it just say new scene. We want to build complete empty. You can also go for a builder basic building. And then we click on Create. We don't want to store this one or Lotus 1 additive late just to make sure what we need now is the actual same graphics as we have created beforehand. The easiest way to do that is we can take our sample scene and drag this over here in the hierarchy panel. This is how you can easily put in things between themes. So this one is now loaded seen, this one is the current scene. So we can do is we can select our Canvas, for example, can copy that control C for copy, go into untitled and say Control V for paste. Now I goes to sample scene and just say remove the scene. As you can see, I have no all the UI I had before in the other scene. So we don't need to recreate it or we don't need as the top-left corner, big QI time and we don't need the turns. The only thing we need is one of them panels, win or lose. It doesn't really matter. So I just keep on the loose panel. So everything is active and good to go. We now wanna do is we want to, let's say recreated. So this is now our menu panel, and it has the same settings as before. But what we wanna do is we want to get rid of some things. So in the top bar, we can name this one. Welcome, or I can give it the title. 3d memory. I don't know. Whatever memory. This is going to be your game name literally. Or what you can also say underwater, match that what I would probably name mine. So this is going to be or Underwater matches ready as probably good name. You probably want to drag around a bit from the text Mesh area, so it's not going to intersect too much inside this other area. You can also make some beautiful backgrounds if you want to. And we can also get rid of the actual direct image color of the hair, of the color tint, but we keep it over there so it is able to stretch along current graphic completely. We now can do is we can say something like Hey, user or a switch or a load, or play a game or whatsoever. But we can also get rid of that one text field. And I can create another holder which is organizing all of our buttons inside another vertical layout group. For doing so, why go into the bottom box, create a new UI image and scale this one, maybe up until I'm happy with the size, center it out. And maybe you also increase the size of a here. So this image now wants to have a vertical layer group or that's what I give it. And then I'll take one of them buttons, which basically doesn't matter. I duplicate it just in case so I don't lose anything and just put it in here. So again, the content size Federer or actually the snow content size further to this vertical land group. So we need to take care of that. So we want to control the width completely of this one image over here. So I'm going to make it like that. Also. I want the button to be like laid out the way we want. So we can say something like layout element again and add it to it. And we can say preferred height. And we can actually do any of the height we want. And we should be able to Around was done. But before we do so we probably need another one over here so we can play around with these numbers over the actual height and stuff. So if we select, hey, child control the size of our actual menu buttons, we can do this, but again, we can still go into them, two buttons and child control them by the size we want them to be. Also we can, we should be able to use the image of the here again and give a little spacing in between. So it probably looks better later on and we can give the background and any other color of our liking. So now we can literally duplicate this as often as we want to, depending on how many game modes we are going to have. So for example, we can take one of these, this button as an example. We can say it's going to be a visit my homepage. So if you want to drag attention to your homepage or to the store, we can say the actual homepage to visit, for example. Yeah. Homepage. Then you're going to have something like a normal mode and E or an easy mode. Play, easy. Easy mode or not play but just easy mode. Easy mode. And the center you can put in something like a normal mode. Then you probably have an hard mode. Maybe finally, I insane mode. Get rid of the actual other buttons since I don't think I need them anymore. Because that looks kinda okay. Again, do a free aspect ratio change and take a look if the ratio is going to take correct. But as you can see, it's not 10 percent. So we need to take this image now as well as its corresponding anchors and drag it so that it fits the actual position over there. It's sometimes it's hard to see where the actual anchors are going to be. So try to figure that out or change the graphics to super dark so you can see them better. So I want the anchors to be outside of the hair. So in three aspects, we should see an automatic resizing of all these buttons no matter how broad or how big our option panel is going to be. So again, I believe are going to put an a visit visit homepage without any typos as always. And you can also put in any other credentials at the very bottom or at the top or on the sides like version number, your current homepage and so on and so forth. Again, as an example, I can put in another text much pro acid over here, going UI text, text Mesh pro acid. Put this, for example, over there at the bottom. Of course, need to make sure that your anchor, this one later on, right? Kinda make it a bit broader so we can fit in as an example, complete homepage. Again, take this anchors and make sure that you incur the object correctly to the corresponding space. And you can pass on your homepage, you can say something like https. And then your homepage, for example, www dot Aquaman games.com. As you can see, it's pretty huge. So I go with auto size here as well. So it tries to fit the order size or the actual thing over here. Also I sent to this inside the alignment, so it's always passing day. So was that third again in free aspect, it should automatically, yeah, stretch with the current design however hope rod or how small we are going to put this same N 16 by 10. Again, if you want to make the gaps in between the image itself, it's on its image over here. Or maybe you want to make a direct or bright or any other color you prefer, or you can go completely down to 0. So you see the background through the actual buttons over there. Again, don't forget to save the scene because it was a new scene. You have to put it in your Scenes folder, I call it menu was the big M. And don't forget to save. So now we can create easy modes, normal turbines and sane modes. And we can also visit the homepage whenever we want to press on this one button over here. But again, this is stuff for the next video, I guess. 45. #45 Different Game Modes: Welcome back to the course. In this part, we want to go to and create our easy normal in hard mode. So easy mode is something we need to think about. But first off, let's copy and duplicate the sample scene, the sample seniors to one in which we were working. So hit Control D on your keyboard or Command D on the Mac. And now we want to rename this one to be easy. We can also do this for the other ones, since we are here, we can also say it Normal. Control D again, rename as one too hard. And then you can also duplicate, well literally any scene and name this one insane. On our buttons over here, we want to know different game modes. But first off, we want to see, okay, where and how do we actually load things? To do that I just create a new menu, Let's say handler over here objects just an empty one. So create empty. And we want to add the corresponding script. The script, I am looking for, the menu buttons, since all of them except the homepage thing, is going to be in solid. So Menu buttons is now connected. We're going to select all the buttons holding control, except the last one. Because that is a different story. Well actually we can also take the last one because we're going to make use of the same object. I pass. And now the menu handler object, now I deselect or actually it doesn't matter. I select them all menu and say Load seen. I don't want to load the from this button. I don't want to load the menu. I want to load easy. Make sure you take the complete correct naming convention from that. Second one, I want to load normal. Again, this is the scene name we have created over here, is the hard, insane and normal. So here you want to make sure that you would, since that is case-sensitive, want to put in the same. This one here is going to be hard. Because the big H and the last one is going to be insane. The visit on page one is going to be a different, I'm actually in a different story. We're going to load a or put in our homepage, or you can put in your homepage to visit us an example. But we'll get there. So now whenever we select one of them buttons, we load the corresponding scenes. But we want to prepare them so that they are really easy and set it up, correct? Don't forget to save as menu scene and open by double-click the easy seen. For the easy scene, I want to go out of 2D view and double-click the game manager to go close to it. And you don't know how easy, easy as, but depending on how old the kids are which are playing your game, the easy mode is probably some playfield like, let's say somewhere between two to five or something or two-by-four. Now I want to lay this out so that kids are able to play the game. So maybe we have four in the width and three and the height. If you don't think that this is easy enough, then you can also go lower with the numbers. So also what I wanna do is I want to make sure that all the cards inside the game view. And you can always, if you get distracted to get rid of the canvas as well as the confetti by just disabling them here and see if they are in the view. If you cannot see that correctly, you can also just for the moment in time, deactivate them complete objects and see where they are. And if they are correct at this point, most important thing is that the camera catches the complete game field, so everything is able to be selectable when you're playing the game. Last telling you wanna do is of course the time needed for this round censored, easy mode. You probably want to stay with time complete to somewhere between 80 and 120 seconds. Well, again, this is totally up to you your decision. Don't forget to save the settings for the easy sooner. Now let's go to the normal mode. The normal mode we're gonna do the same. We go here and say, okay, normalise probably some playfield between four by four. You can also put in a bit more inside or even a four by five. The downside is I don't have much more of cards to set up. So probably this is going to be any other mode. Maybe we're going to put in a four by four over here. For the normal mode, I keep the 120 seconds setup over here, Control S for save. And now we can go to hard mode. And hard mode are going to do literally the same, but I put a 5 by 4 field. So I can also see everything of the day. We have set this one up beforehand. You can also play around with the camera and maybe centered the complete play theatre bit more if you want. The last thing we can do is the same mode. Don't forget to save of course. And then saying there's probably going to be the hardest at all. But I cannot go over 20 cards at this point. But what you can do is you can reduce the play time. So you say, maybe I want to put another kind of layout over here if you want to. But you also want to maybe reduce the time to just AD for this amount, at least for the moment, you can add as much cards to the sprite list as you want and go even higher with these numbers. So in the end you probably have, I don't know, something like by 10 fields. Calculation as easy, but you just need to make sure that you have enough card pairs as you can tell. So you need like 50 card Paris to put it 10 by 10 field over here. So again, I put mine to four by five over here and just reduce the actual time and save the actual scene. So now we have all the game modes and place. So from menu mode, we should be able to load them. But before we can do this, we need to go to the Build Settings. We need to two and order you put in the build settings is going to be at first the menu. And then it doesn't matter in which order we're going to put the other ones. Important here is that the menu is very much in the top. Or if you have like a logo scene which is going to come before the actual menu, you can also put them over there. So we need to make sure that menu, easy, insane, hard, normal are going to be inside. I don't implement the sample scene because this is the works in the trolley from now on. So like if you need to test anything, if you want to introduce more functionality, you probably want to start inside the sample scene. Pretty good. Whenever we now press play. And you should be able to press one of these buttons like insane mode. But interestingly, they do not react 0 since we actually just copied over the canvas. The canvas needs a secondary element. In this case, it's going to be the event handler. We need to implement the event handler. Otherwise we don't have any inputs on then k-means it's called event system. So just added, don't rename it, just let it be here. This is going to be responsible for any of the inputs of the mouse or keyboard or whatever. And now we should be able to load any mode over here. We don't have any hover over facts, but if I click and sane mode, you can see we are starting at 80. So we are having the correct one over here. And now we are able to play insane mode and see if we are actually able to solve this in a short amount of time. If the game is a bit darker. So you can currently see those tiles are known to a even white anymore. This is going to happen because we haven't baked in light. Once you create a build, this is not an issue anymore. So just keep that in mind. Also, we see the actual, the actual gizmos over here because I still have gizmos activated so you can deactivate that. You wouldn't see that in the, in the game later on as well. And the others, how you can literally try to, I don't know, beat the game or give the players some interesting challenges. Do you probably want to implement even more functionalities to that and wants the time is over, you give them the possibility to retry the game. Again, I'm not going to hard over here and try to win because I'm absolutely not able to anymore. Because I haven't done any concentration over here anyways, the star was somewhere here, but that is not my deal at this point. I want to see the game over scene right now, which we do. And now we can say try again to retry or go back to menu. Let's try back to menu and see if it works. Pretty good. Now we're back over here. And then the next part, we just implement our new on our actual visit homepage button functionality. 46. #46 Website Button: Welcome back to the course. In this part, we want to go and implement our load or visit homepage button would just super simple to implement. And probably also some Exit button to accept the app. Even that is probably not necessary, but sometimes, well, it might be to do so we first off open our menu button script and create a web. Yeah, our web loader. To do that we say public, void, load URL. Or we can do is we can again do the same as we do here. Like we implement a string and scientists as being a parameter to fill out or we just pass it over directly into it. This is totally up to you. To load a URL. We should be able to say something like application dot open URL. The Open Neural takes a string as a parameter. As you can see, the string parameter needs to be as following, HTTPS, colon, double backslash, and then www dot optim and games or whatever. Again, whatever your website is.com. And now we close that. And safe. Again, you can make this ring being part as here and put this argument as over here inside the open URL part. Now the final step to visit the actual homepage of the actual creator of that. You can easily do this as well. To do so, we select the little button which is going to call the function. We scroll down. And instead of menu buttons stuff, we're going to say we want to load the URL. Don't forget to save. And what you want to do is you want to rename your buttons here probably as well. So we say visit homepage, a button. And then we have the insane mode. We have the hard mode. We do have the normal mode. And of course we have the easy mode. That's it. Don't forget to save the scene Control S again, and now let's try to visit the homepage. So whenever I click on this one button, my browser is opening and it's loading, as you can see, Ottoman games.com. Pretty good. So now this is also working and it also works by the way, on mobile or anywhere else where you want this to be loaded. 47. #47 Adding Desk Background: Welcome back to the course in this part, which is going to be rather the last part. I want to put something in the background as being my desk. To do so we can go and implement another extra texture. I created just a little checker image, which is going to be between white and gray checkered. So please check out the lesson or the resource files wherever I put it, this one, make sure you drag this one into your textures folder. The next thing is you wanted to selected and make it so that it's a Sprite 2D UI and apply the changes. When we create 3D backgrounds, we need to create a material for this one checker evidence, the 2D background. We don't need to in my case, I need to go to Create. Right-click inside the actual folder over here, right-click Create. And now we want to create a new material. Depending on the render pipeline, you need to choose a different one. I just haven't implemented yet another render pipeline of especially of a specific run the pipeline over here. So we can just take it as is. I'm going to put the, the checker now inside the albedo channel. And the cool part about it is I can tile this is any time by using this toiling. But let me place box wherever I think I'm going to put this material on. So I create a new 3D object cube. So we can see this over here. I want to make it so that the box or the cube is going to be laying under our actual active, they leave visible gizmos. To do that, I just drag this part over here down. And now I can resize it literally to any size I want. Can even go outside of the camera view. So why overstretch? With purpose? I can do this on the top and the bottom as much as necessary. Since the camera can catch quite some information, we probably want to resize that a bit more just in case. Also later on you can do some more effects to the camera whenever you, for example, I've collected or created or solved the complete Playford so you can rotate the camera around the playfield if you want to, just so you know about it. Now what we wanna do is we wanna take the check on material and put this on the cube. Now you can see it's rather huge, so we want to play around on the material itself. So first off, we do have two's tilings, a secondary map styling and as first domain map styling. Let's put this one not to be a 10 by 10. Since we were changing the text of time from actual default to Sprite 2D, we cannot tile this one directly in the material. What we need to do is we need to set this one back to default. And then we want to go and apply the changes. Go to the cube again. I was playing around with the different material over here. So we just take the normal standard material over here. As you can see, we can tint this and to any color we want and which is probably going to fit our game as best as we want to. Probably mine is going to be somewhere dark orange over here. You can also put in any other textures on the background on the desk literally. And the last thing is, we want to go back again to tiling and set this one, for example, to 10 by 10. It looks so dark again because we are overlaying our actual scene here with those to win and blues panel. But if we go in play mode, we should see the effect. As you can see now the complete game screen is actually dark or is actually yellow, orange, and looks kind of good. Once you're happy with the result, you can also go over to the other scenes and duplicate this background cube. I just rename this cube by hitting F2 again, back ground cube. You can also name this one desk and you're good to go to copy this one all over. You just can say Control C. And now we open the next scene. We are currently in the Easy mode, so I open heart mode and put in now this control V was the background cube COM completed. Then we say Save Scene, and then we say unload scene, or in this case remove scene. Now we do the same for insane control V. Safe seen remove scene. We can also do this for the menu for 12 or for the normal mode. Control V U2, pass them. Safe, seen, remove seen. Safe, easy scene. And now we're good to go. We can also do this by the way, for the sample scene because that is now part of that as well. Control V, safe seen, remove seen. Control S again, for saving this one. So each C now has a different or has the background, set it up in whichever setting you prefer. And you can even go and create more of them inside the actual like more materials was a different color. Like yeah, just duplicate the checker Control D to duplicate. And you can make the duplicated, check them, for example, light blue. And you can now say, okay, Easy mode is the one which has a light blue background as an example. And if you know, press play over here, you should see the easy mode is going to be like that. Pretty good. So now whenever you are in the actual menu mode or menu scene, you should be able to go into easy mode which has a light blue. Normal mode has orange. Now, as you can see, the lightest not baked. But if we go and easy mode, we should see the actual pollutant offers material and the background. Pretty good. 48. #48 Menu Background: Welcome back to the course in this part, I just want to put in the checker my background over here as being a holder of the actual scene on the background since I didn't knew where and how I want to put us. So in that case, without touching the menu panel, we just select the Canvas, select UI and say much. What I wanna do is I want to say a stretch that over the complete surface by using uniform stretch holding old and put the corner right here. Now I want to put in my image, my checker. The problem is that the checker has to have a different setting. Our current SEC checker one as the default material used. So I duplicate Control D, the actual checker. And this is going to be our UI checkout, for example. Now we can change this one to be a sprite to DUI and apply the changes. Now I can make this one part of the actual sprite image. The other one wouldn't not be able to do this because I couldn't drag it into if it is not declared or defined as being an actual sprite. Now what I wanna do is I want to tile this. To do so we go to image type tiled. Now we can use the per pixel unit multiplier and child us one up and down to whatever we like and place. Also it says that it looks like the tile you want to have no border. So we don't really need a border for this one, but we actually can implement one if we want to by just putting the center point being the only piece which is not changing. So you can make it even more interesting. Furthermore, later on, it would be, would be different than being a slice one. But again, this is something you can test out on your own. I can literally go into the sprite editor, as you probably know. And we can define the centers and status of 512 by 512. 256, going to copy that one to be in all of them numbers and apply the changes. Now the tile would look different as you can see in each of them corners. Now, we're going to have one part and the other ones are going to be stretched in between. The real tiling is not working the way it should. That is because of the actual multiplier as well as the actual sliced. So as you can see, if we go for this simple one, nothing is going to happen. But we also do have a filled and the tile. Again, the tiled is only tiling wherever it can. The best part would be creating a double checker. So we can also fill the center as well as fill the sides of the hill. So as you can see, that does not make any change or M doesn't make any, any sense to have it here. So what I do is I am going to go back to our zeros 0000. So everything is fine. I apply the changes again, closest Sprite Editor and everything is tiled again. Going back into the image, I can implement or increase tiling as much as I want to and make it look as I want to probably go with the title of three or four or 2.5. Again, all of that totally up to you. And now what I want to do is I want to take the image and put this hierarchically above the menu panel. And also to fit the actual image that takes care of its own by the tile already. But we can also take this and to any color we like to. And once you are happy with the actual color of the hair, we are completely done creating. Again. 49. #49 Cleaning Debugs: Welcome back to the course. This is just a small clean up lesson over here and which we get rid of all the debug lines in our code. And probably you also want to get into and do some more, let's say generic arguments like putting any infos in between the lines so you know exactly what, what script is going to do over here. So the current script is rather open and everything is fine over here, the same for the menu buttons, but there are again, some debug lines. The debug lines, for example, come here and like whenever we hit some ordering to this debug line as firing, what you can do is you can just comment it out or just a little line completely that is totally up to you. There are also, there's one more line over here is like the debug log whenever we check for women and check follows. So we can get rid of these ones as well. The other ones should not contain any other debug lines. But if that is the case, you can always go and hit Control F and to check for debunk anywhere. So you can do this by any scripts, literally Control F and pass in debug. And if you don't find any debugs anymore or any debug lines tells you there's none found over here. Once you have saved, you shouldn't see any other debug lines anymore in the console. So that is probably a good way to clean up things, clear the console, get rid of maximize on play and try again. And I guess no direct line should pop up anymore because you don't need them inside the built. 50. #50 Conclusion: Welcome back to the course. This is the conclusion video of underwater mesh 3D or how to create the AME 3D matching game in Unity. We were actually creating this little menu over here by using some graphics, make them scalable and stuff like that. We were creating a visit homepage button to open the browser. No matter on which device you are. We were creating a different game modes of here in which we have set it up timing. So we have a timer which runs downwards and we just fill this or actually get rid of this bar. So whenever the game is over, the time is over. We just go and see game over screen over here, which we created as well. Also, we were creating those confetti effects whenever we gonna create a match over here. Also, we are counting how much churns we actually use over here in the game. As well as we are going to show a windscreen whenever we win the game and also even so more confetti at this particular runtime, we also work creating this little background checkout effect of there, which is just an object, 3D object, we passed all over the place. So whenever we now lose or win, we're going to see a different screen and we are able to read, load scenes and stuff like that. I'm not playing seriously, seriously over here, so just bear with me. So and the last one over here is going to give us this, you win and all this confetti as shooting inside the scene. Pretty nice and dandy, I would say so. You were learning also how to go back to the menu own play another round so we can actually play around. We can also see what the score was, how much time was left and how much turns it Turk, and your players are able to get into it. You can also try out any other insane mode and so on and so forth, or your players can do. There's one more thing we need to take in consideration is the actual game manager we were creating, which was give us the possibility to do some editors scripting over here to automatically calculate the paramount we use based on the settings of a here. We were also learning how to use gizmos and stuff like that. We were blocking recasts. We were shooting ranked castes into the scene to do the animations. So at the end, you're going to have like a pretty decent memory 3D game. Don't forget to add more sprites, the sprite list, so you can have or create even bigger memory games. Don't forget to put in your score of your liking as well as a time to complete. Probably you want to also implement a combo system and wedge like how much cards you combo ones after another. And implement this over into the game as well. So you get maybe more points by combos and stuff like that, like additional score at this point. If you want to save that content, like one to save the biggest or the best course you have made, you just need to simply save them inside the player prefs as an example, super-simple, nothing fancy overall. But yeah, that's what we just implemented, that's what you all learned and probably learned even more. We were looking into four loops and stuff like that. We were shuffling the game field. We were just picking random sprites and so on and so forth. So I hope you enjoyed this course. Thanks a lot for joining me on this little lesson, actually on this little round. And I hope you become a way better game developer actually in the future. Don't forget to rate this course whenever you are done with that course actually. And let me know if you have any problems or if you're struggling at any time or any point, and I tried to help you out as best as I can. So once again, thanks a lot for tuning in. And I hope to see you and one of my other courses Have a good one. Bye-bye. 51. #51 Bug Fix: Welcome back to the course. In this little video, we are going to talk about a small bug a student has encountered. Let's talk about that. So first off, what he discovered is when we select the card once, that's okay. But if we select the same card, we're going to get the high. You got something open. Like we got the score for this one card of here. And also if I keep clicking on that, I'm going to get a bunch of these null reference exceptions. That is, because this car does not actually appear or does not yet exist anymore, literally for the game itself because we have removed it. So the deal here is we need to fix that. Also. We want to make sure that when ever we have one open, that we are not able to select this 1 second time, so we don't get the actual match. And of course the same is going to appear to any other of these cards. So thanks for discovering that in this video we are going to go over and fix that. So first of why does that happen? It happens because the card we are going to add to that card list of here is going to be added because we are not checking if the cards till the one we are just collect is already inside the pig cards list. That's what we need to do as an extra check over here. So it's a simple check for existence literally. So if in our Picard's list, if the car, that, if this card list actually contains our card, we tried to add, so we just put in the cart over here. What do we want to do that is the case. So instead of adding this card and checking athlete for the match, we just want to get out of here because the card or rarely accessed, in that case, we just go and return. The return statement once again, just brings us out of the current complete function at this point, as you can see, the return statement terminates execution of the method and which is appears and returns control to the calling method. So basically, we are ending the complete check whenever we click on a card which has been added to the pig card list, already. Don't forget to save and let's try that out. First off, we let the compiler run C of the error messages. We can clear the console because we want to produce new ones. And now let's see if we still have the same issue. So first off, I can open this one. I can try to click this 100 times if I want to, but nothing is appearing over here in the console. Instead, I can open a second one which does not is not contained inside this list. So I can test this was any other card here as well. I can try to do this, but as you can see, no fancy problems over here. And when we get a real match, then of course, the game or actually the card match is going to fire. That has everything you need to do to avoid this little block.