Learn Unity Beginner/Intermediate 2023 (FREE COMPLETE Course - Unity Tutorial)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello and welcome I'm your code monkey and here is a free complete course on making a game from start to finish if you've always wanted to learn how to make a game or if you already know the basics but want to see how to organize a more complex project then this video is for you it's perfect for both beginners and more intermediate users this is a completely free course video but it has the same level of quality as my paid courses or my Steam games you can download the project files to follow along or inspect the funnel game you can even play the final game directly on scene we're going to start commonly from scratch and build a really awesome game with tons of systems and mechanics building this design requires working with lots of unity and c-sharp features so this is a really awesome project for you to learn after following this course and learning all of these techniques you won't be able to build all kinds of games in all kinds of genres this is going to involve learning about the basics of unity and c-sharp learning how to make a character controller physics raycast learn all about c-sharp interface and events using script more objects handling UI the new input system and lots more very importantly everything that we're going to do here is going to be focused on writing good easy to understand clean code meaning that I will not be teaching you bad practices that some beginner tutorials teach the code that we're going to write here is production quality code this is not a throwaway demo the quality of the code and the structure of the game that we're going to build is on the same level of quality as my own Steam games as you can see from the video link this is indeed a complete very thorough course so don't try to watch this whole thing in one sitting take your time take it slow and just focus on learning there are chapters for every single lecture in the video here's a quick overview of the entire course all the steps that we're going to take to reach the final published game so first of all we're going to start commonly from scratch by selecting a Unity version and creating a brand new project with that new project we will then learn all about the basics of the UNT interface and setup plane layout then the other important part is Visual Studio which is where we're going to be writing all of our code after that comes an extremely important lecture all about coding style and naming rules like I said the code in this course is on the same level of quality as my Steam games so having proper naming rules and good code sound is Paramount next we're going to download and import all the assets that we're going to use in the course everything is included so you can follow along with every step of the way with yes it's important we're going to set up some quick post processing just to make the game look good then for our first piece of logic we're going to make a simple character controller with that logic working we will then Implement a proper character visual with the included assets next we're going to learn the basics of animation and the animator component and with that we're going to make our player really Common live with some simple but really nice animations then we're going to install the send machine package this isn't actually used too much in this course but I still wanted to include it because it is such a useful tool so I do want you to know about it after that comes another extremely extremely important lecture with regards to writing some good link code we're going to do a nice refactor to replace the Legacy input Venture with the brand new input system learning how to refactor is an extremely important and very valuable skill that will massively improve the quality of your code with that then we're going to implement some nice Collision detection to make sure our character doesn't want through walls next we're going to create the very first kitchen counter and make a script to handle how to interact with it then we're going to learn all about c-sharp events and create a proper interact input next we're going to build a selected counter visual which will require us to learn about the extremely useful Singleton pattern with the counters working we're going to start working on the kitchen objects themselves so these are going to be the ingredients and the plates we're going to use scriptable objects to Define all of the types then a very important part of our design is each kitchen object will have to be placed somewhere so we're going to take some time to really think about the best way to achieve that all while riding some good clean code next we're going to enable the player to pick up an object in doing so we're going to learn about c-sharp interfaces then we're going to make a container counter this is from where we can spawn new objects with that we will enable the player to pick up objects and drop them anywhere where there's space then we're going to make the cutting counter this one enables the player to cut an ingredient into slices so to do that we're going to make an alternate interaction and for handling the cutting we're going to once again use script more objects to define a proper cutting recipe then we're going to learn about a really awesome Unity feature we're on canvases and use that to display a nice progress Bar for our cutting progress after that is a quick lecture just going to make a very useful generic script to make any object look at the camera next for another counter we're going to build a trash bin this is where the player can drop objects to destroy them then the stove counter this one is going to be quite a bit complex we're going to create recipes for cooking and for burning we're going to learn how to make a basic state machine and handle timers next we're going to make the plates counter this is a simple encounter that just spawns a bunch of plates after that we're going to make some custom Logic on the plate to be able to hold other objects with that logic working we're going to build a complete visual for all the objects that can exist on the plate then make a nice UI element on the plane itself to showcase the icons of what exactly is on that plate afterwards we're going to make the very last counter the delivery counter this is where we drop the completed plates and in this lecture we're also going to learn about the unity share graph and make a quick simple custom Shader then we're going to build the delivering manager class that generates the recipes that the customers are requesting next we're going to build a UI to showcase the wedding recipes after that comes something pretty crucial we're going to add some music and then add some sound effects for all kinds of game actions without the game won't be almost done so next we're going to build a proper game start and a game end then make a simple main menu and handle scene loading after that hand on creating a basic pause window then make an options menu enable the player to modify the audio levels and rebound keys after that we're going to enable menu navigation with a controller and in the end as usual comes the Polish stage so we're going to add all kinds of small tweaks and effects to make the game feel really great like I've said many times polish is what separates good games from great games after all of that we will have our final completed project so as you can see you will learn about tons of Topics by following this course also let me point out one of the reasons why I chose this specific design is because my next free course won't be on taking the game that we're going to build here and make it multiplayer so if you've ever wanted to make multiplayer games then that course will be excellent for you definitely take your time following this course the multiplayer free course should hopefully be out next month or if you're watching this in the future check the links in description although that multiplayer video won't be starting from where this course ends so definitely make sure you watch this one now if you are new to the channel then welcome and here's a bit about me and my credentials or why you shouldn't listen to what I have to teach my name is Hugo and I've been running this Code Monkey YouTube channel for five years now in total almost 700 videos on all kinds of topics including tons of tutorials sharing my knowledge to help you on your Game Dev Journey I'm also a professional indie game developer making games for over 10 years with 8 successful Games published on scene so what I'm teaching here is based on a lot of years of experience making a lot of games just like with my paid courses I'm always going to be in the common censoring questions so if you get stuck at a particular point or need extra clarification on something go ahead post a comment and I'll do my best to help do make sure you include a timestamp of what you're referring to I will also be updating the pin comment with any frequently asked questions that I see so actually right now go ahead pause the video and scroll down a bit just to look at that comment since on YouTube I cannot update the video after it's published I will be updating that comment over the next months and years with anything that comes up also I've been running this channel for five years and in that time I've made almost 700 videos so there's lots of topics that I've covered separately in more detail all of those videos are linked in the description throughout this course I will be focused on building this specific game using whatever it takes to build it meaning for example when we get to using c-sharp events I won't teach the basics about how they work in order to achieve what we want to build but if you then want to learn about c-sharp events in more detail definitely go watch a dedicated video and I also made a page on my website for this course it contains a link to download all of the project assets you can also download the complete project files for every single lecture so if you get stuck at any point you can download the code at that lecture and compare with your own there's also references to all of the videos and I will also be including frequently asked questions for each lecture so definitely keep that page open in a second tab as you follow along this course now this free course Took a ton of work to make so I really hope you find this video helpful go ahead and hit the like button if it helps you it's a small thing but it generally does help this video on the YouTube algorithm making this course was a ton of work and by making it commonly free it means it will obviously never make as much money as if I had just made this a paid course I'm personally okay with that decision with the hopes that by making it free it won't reach and help many more people I'm also a big believer that education should be free so if you can't afford one of my paid courses like if you're just a kid or going through a rough time I still want you to have access to high quality education so you can achieve your Game Dev dreams one easy way you can help me for free is simply by liking this video subscribing to the channel and just watching this course that will hopefully help push this video on the YouTube algorithm and help it reach many more people another free way to support what I do is I'm currently working on my next team game called turn one Liberation you can wish list the game on Steam wishlists matter a lot for steam visibility so just by doing that you won't be helping me and just in case you can't afford it and you find this free course useful you can also support what I do in a few other ways I spent a bunch of money making this course I hired an artist for the 3D assets so that I had the right to distribute them so that you can download it and follow along same thing for the music and sound effects the logo and the cost to upload the game to seem so I would like to at least not lose money on this project hopefully there's enough of you who can't afford to help me so that I can at least break even and for one way you can support is I added this exact same course on my website as a regular paid course although I want to be very very clear there is absolutely no difference between this free video and the paid course there is absolutely nothing behind any kind of payroll all of the lectures are free all of the apps are free everything is free you don't have to pay for anything if you can't afford it or you just don't want to the paid version is essentially a donation the only difference is this free YouTube video has regular YouTube ads whereas the paid version on the website doesn't have any ads that's it that's the only thing so the only reason why I made that paid version is just in case some of you can't afford it and you want to support what I do and want to help me break even on this project but again only do that if you can't afford them if you can't that's personally fine I hope you'll learn a ton from watching and following this free course beyond that if you follow this course and you enjoy my teaching sound perhaps look into my other courses if you like this video then I think you won't really like my turn-based strategy course that is the perfect course to follow up on this one one it Dives even deeper into some of the concepts used here and it will help you make the jump from beginner to Advanced and since you're interested in unity I think my ultimate unity overview course would also be very useful to you each lecture on that course is focused on teaching one entitled feature there's already over 15 lectures including plenty of small but very important things that you just wouldn't see in a regular YouTube video if you're interested in visual scripting I have course on making three unique games internally with visual scripting and no code at all or if you prefer code you can learn how to build a nice Builder Defender game so if you enjoy my teaching Style on this free course then check out my other ones then of course YouTube has Channel memberships and super thanks so you can use those if you want I also have my patreon if you prefer that and in a lot of my videos I have some affiliate links if you ever pick up anything through those I get a nice commission and I also have some of my own assets on the unity Astor so if you enjoy this free course and you want to support what I do there's plenty of ways but again don't feel obligated if you can't afford it or you just don't want to that's perfectly fine I hope you'll learn a ton from watching and following this recourse alright so that's enough talk of that for now before we begin building the game from scratch let's inspect the final polish game that we're going to build so let's see that in the next lecture hello and welcome I'm your code monkey here let's take a look at the final game that we're going to build so we start off on a simple but really nice main menu so we've got a nice visual a nice logo and a bunch of useful buttons then of course the game has a nice loading system so when I click on play it's going to load into a unloading scene and then funnel into the final game scene so let's go ahead and play and if there we go here we do see the game scene and right away we see a nice internal window so it's telling us how to play the game so the basic interactions and then over here the controls importantly these are all rebindable so over here this element is all Dynamic then we can look at this tutorial for as long as we want and we are waiting for the interact to continue there's also a really nice song playing in the background so the game has music now we can look at this tutorial for as long as we want and when we're ready we can interact and continue and as soon as we do if there you go we've got a nice countdown some nice animations a nice sound effect and there you go now we are playing okay so here I am controlling a nice character I can move in any direction there is Collision detection so obviously I cannot go inside solid objects so I can walk around and for the goal of the game over here on the left side we've got recipes that the customers are waiting for so for example One customer wants a simple Burger so for that we gonna need to pick up a nice bun so let's pick it up then the burger obviously requires a meat Patty so let's go ahead we can pick one up from here but this one is an uncooked meat padding so we need to drop it over here on the stove and there you go it starts cooking we've got a nice timer we've got a nice warm bar UI and there you go it keeps counting and we've got some nice park on some nice visuals and over there even a nice indicator telling us the meat is about to burn and there you go the meat has burned so now I can pick this up and I'm holding some burnt meat so the customer probably doesn't want to eat this so we can go over here to the trash or trash it let's try doing another one and do it properly so let's wait for it to cook pick up a plate so we can pick it up directly onto the plate there you go to the meat is cooked so let's pick it up then go pick up some bread and there you go here we have our camelli recipe so let's go into the delivery counter deliver it and there you go a nice delivery success all right awesome we've just delivered our first recipe so then someone else wants a salad so let's go ahead pick up a tomato here we have a big uncut tomato so let's drop it onto a cutting board and now we can interact with it so we can interact with a secondary interaction key and by interacting we cut the tomatoes so it takes a few cuts and there you go with slices and it's sliced into tomato slices so let's do the same thing for the Cabbage here we are holding a regular cabbage then slice it and this one actually takes a bunch more and there you go got both slices okay great so now let's pick up the plate pick up both slices and deliver to the customer and there you go got a nice success all right awesome and of course we have a correct identification of if we have a crack recipe or not so if I just pick up an empty plate and deliver it there you go got a film delivery because nobody wants just an empty plate alright so here you can already see quite a lot of interactions quite a lot of systems at work so the character has a nice character controller it has physics interaction you can see how it identifies the counter that is in from the character I can press a button to interact with the counter and interacting with different counters does different things so if I interact with a clear counter I can pick up or drop things over here I can pick up drop it with an alternate interaction I can do the second action then there's the stove machine so that one has a nice State machine so it counts up over here we've got some nice particles we've got a nice Bloom so all the Visions look really great so we've got some post processing we have a bunch of UI elements directly on the world and outside of here we've got some regular UI elements so we've got the recipes with Dynamic icons for all of them we've got a timer over there on the top right corner showing how long we have to deliver on our recipes and on the kitchen counter we're also using a custom Shader so this was built using shade wrap so as you can see lots of internalized systems then the game also has of course the basics that any game should have so I can pause the game and there you go we've got a nice pause menu so we can resume to go back or pause it again and of course while pause everything is possible that's great we can go back into the main menu or we can go into options and over here we can play around the sound effects volume the Music Volume we've got all of our controls importantly these are the controls for the keyboard and also the GamePad so the game can be played with any Gamepad so it can be an Xbox controller PlayStation switch controller it doesn't matter all of them work and we can also rebind all these Keys both the keys as well as the GamePad inputs so let's go ahead and deliver a cheeseburger so here's some burn meat so let's toss this then pick up some more meat pick up a plate here we've got some cheese we've got some bread pick up the meat and deliver it all right awesome and of course finally at the end when our timers left here we have a nice game over window showing how many recipes we delivered alright so this is the final game that we're going to build as you can see it involves lots of interesting interactions which require learning lots of different skills we're going to be using c-sharp interfaces c-sharp events the new input system shade graphs critical objects we're going to learn about c-sharp events making character controller handle collisions and so on like I said one thing that we're going to focus heavily throughout the making of this game is on writing good clean code meaning that the final game that we're going to build won't be very easy to expand upon thanks to how long the code is very clean it will be very easy to add more recipes maybe more counters with more actions maybe things like perhaps washing dishes adding an oven and so on or really you could make something completely different this game is all about character and interactions so that could be whatever you want you could take this as a base and build some kind of sci-fi game something like Among Us or FTL you could make a survival crafting game like rust or Minecraft or Don't Starve really fun learning how to build this game by the end you won't have gained the knowledge required to build all kinds of unique and interesting games alright so now that we've seen the final game Let's actually build it just before we do let's get a quick refresher of the absolute Basics you should know in the next lecture hello and welcome I'm your code monkey in this lecture we're going to just get a quick refresher of the absolute Basics you should know in order to be able to follow everything in this course okay so like I said this free course is targeted at both beginners and more intermediate users in order to start following the course you really only need to know the absolute Basics I've made three useful videos with all of the basic knowledge required to follow this course watch the video on how to download install and set up Unity then the quick Unity Basics and the c-sharp basics those three Quick videos contain all of the absolute basic knowledge you need so if you're a complete beginner go ahead pause this video and go quickly watch those and even if you are already somewhat familiar with unity still go ahead and give those videos a watch perhaps in a faster speed just so you know everything that this course assumes that you know here I will assume that you know the basics covered in those videos like what is a game object what is a transform what is a mono Behavior how scripts have a start and update and some c-sharp Basics as long as you know those absolute Basics you should be able to follow everything in this course I won't teach everything above the absolute Basics and if you are a more advanced users definitely keep watching the beginning of this course might not have much that is new to you but as we build the game and start using more advanced tools like script of objects c-sharp events and interfaces refactoring code and focusing on Project architecture and writing some good clean code if you are not a complete beginner you will still learn quite a lot from seeing how this project is built and again like I said I answer comments every single day so any questions you have just post them there and I'll do my best to help this course is split into lectures they are all as chapters on videos so you can navigate around let me also take this time to point out that you are not expected to follow this course in one sitting go ahead and take your time focus on actually learning remember that's the only goal you're not competing with anyone you're gaining knowledge just for yourself so take as much time as you need re-watch some lectures if you feel you didn't fully get it or just ask some questions whatever you do take your time and just focus on actually learning so again if you haven't done so go ahead pause this video and go watch those three Basics videos with that we're going to have everything we need to get started we're going to start only from scratch so let's begin creating a brand new project in the next lecture hello and welcome I'm your code monkey in this lecture we're going to begin actually building our game so let's create a chameleon 2 project and start building it on from scratch okay so the first thing that we need is to install Unity now I cover this in detail on that other Basics video so here I will assume that you already have Unity Hub installed the first decision we really need to make is choosing a Unity version Sony Hub you go into installs and install an editor and now Unity recommends that you use the LTS version or long term sport you should be using that one in most cases it's what it installs by default which as the time of this recording the latest one the latest LTS one is 2021.3 however I want this video to stay up to date for as long as possible so for making this game I will actually be using version 2022.2 if you're watching this video where it is came out then download this version and if you're watching this months in the future after version 22 on TS is out then you can use that one it won't probably be the exact same thing as version 22.2 so you should be able to follow everything exactly for any changes I will Point them out in the updated pin comment and if you're watching this years in the future and there's an even newer LTS version I would still recommend you follow using the 22 LTS don't worry about using a quote unquote older version everything you'll learn here in this version will still be applicable even 10 years from now so I said I'm going to be installing this one in terms of modulus doesn't really need anything I already have Visual Studio Community installed and all the other ones are unticked so install okay so the version is installed now let's create a new project let's go into the projects tab then create a new project and now first up up here make sure to select the right version so again I'm going to be using 22.2 then for the templates this has mainly to do with the UNT render pipelines now if you're a beginner don't worry about that too much just go ahead and select the 3D urp template so scroll down this one right here 3D urp make sure to select this one and not the one that says just reading the urp here stands for the universal render pipeline which means our game will be playable on literally any platform so we can make the funnel game and put it on steam or consoles are mobile it won't run on everything then over here on the right side let's quickly just download the template there it is it's done now select the name for your project so I'm going to call this kitchen chaos and then select the founder for it all right so that's it again make sure you're using the exact right version make sure you're using the 3D urp template give it a name a folder and let's head on create all right so it's open and right away you might or might not see a window talking about urp material upgrades I think this has to do with the template not having the default materials updated to the latest Erp version so if you're watching this in the future chances are you might not see this one at all but if you do then just go ahead click on OK and it will automatically upgrade all of the default materials alright so here we have our basic unity window now since we started a project starting from the RP template we have down here A bunch of Erp helper files so you can click to select the readme file and you can see it over here on the right side on the inspector if you want you can browse around these links in order to learn more about urp but in our case we're building the our game we really don't need this so we're here on the inspection let's just click this button to clean up these readme files just go ahead click on yes and okay that's it so basically you should only have these files in your project window so there's a scene folder and inside we've got the simple scene then we've got the settings and inside a bunch of urp assets while this should have been set up automatically since we use the 3D template and then finally we just have the urp equivalent settings asset now let's just verify find everything worked correctly so let's go to the top left go into edit then go down into project settings then over here let's go into the graphics Tab and you should see the urp High Fidelity asset assigned by default if not you can click on the circle icon and assign it then the other menus over here the urp mobile settings again this one should be set by default then down here on the quality tab on this one make sure High Fidelity is selected basically whatever you select here is the quality that we'll be using in the editor and in turn the selected quality over here also has a render pipeline Ascent now in order to avoid any confusion let's actually get rid of the other ones so let's just click on the trash icon to get rid of the performance and the bounce quality so just click and click okay so we only have this one then let's close the project settings and let's go into the settings folder and over here let's select the urp balance there are two assets for each quality so select those leave the High Fidelity and the performance and let's delete these alright that's it by the way if you made a mistake and accidentally deleted something don't worry you can always just click over here on the plus icon on the project window and then go over here under rendering and you can create a new urp asset with the universe personal render okay so just like this so we only have one quality setting we have high fidelity the quality setting is using this random pipeline asset which is also using this renderer so that's really it with this we have the absolute bare minimum we need if in the end after building the whole game you want to provide multiple quality settings then you can come back to this menu and recreate them but in order to avoid confusion while building the game let's keep things like this as simple as possible okay so that's the basic setup done next we want to prepare our layout so let's continue on to the next lecture hello and welcome I'm your code monkey in this lecture we're going to learn about the union layout and set it up so first things first let's familiarize ourselves with the various NT Windows to create our own layout it's very important that you feel uncomfortable with your layout that you have easy access to all the things that you need then you know where everything is you can see that there's lots of tabs everywhere over here on the NT window all of them can be dragged and dropped in any different position so you can customize your layout to get it looking exactly as you want you can set it up in any way but it will be easier to follow this course if you're following the same layout as me I'm assuming you've seen my quick Basics video so I'm assuming you know what is the inspector what is a game object what is a transform what is the console where is the hierarchy and so on if this is the very first time you're seeing the UNT interface go watch that other quick video first just learn the absolute Basics now for me I've been using Unity for over 10 years now so let's see the layout that I've developed over the years first the inspector on the right side just like default that way we always have a nice view of the selected object and whatever scripts and components it has then for the hierarchy I like to put it down here only on left side we're going to make sure that in our scene is always organized so we don't need the hierarchy to take up tons of space then with the project files next to it this corner is enough to really browse all of the files we want the console to be on the tab right next to it usually I find that when making the game I want to look at the project window but when playing the game I just want to look at the console so keeping them in the same place but on different tabs works great then over here on the center of the scene View and again with the game view right next to it okay so this is the basic layout that I normally use now for a couple more options let's go into the project window and on the top right corner you can see over here these little three dots by default it shows you a two column layout so there's a column here and a column here but personally I prefer the one column layout this shock is one of the project files in a nice compact list view the one thing where I prefer the other one is if you're browsing for some visual assets over here you can increase the thumbnail size but for most times I really like to use the one com layout much more compact also since we're talking about the project window just in case you don't know there's over here this little button with the eye this one has to do with package visibility if you toggle it then some of the inside compacts are hidden whereas if you untangle it then you can see all the various packages with all the source code and so on you can expand over here the packages and right now it is showing all of them all of them with source code the things everything in there and if you click on this then it hides it only shows a bunch of core ones but for most part you really want to leave this text and leave this one collapse nice and clean okay so then on the console over here once again let's go into the three dots and for the unlock entry for this one I like to select one line this makes the console nice and compact which I personally prefer you can see more logs without taking up more space and if you want to read the home log you can always just click on it to see the home stack Trace now there are also some more options over here if you want for example show the timestamp this will show the timestamp when each message were sent you can use a mono space font meaning a font where every character has the exact same width so a bunch of options but for me leaving it just like this works perfectly fine then also importantly over here these three buttons these toggle the visibility for the type of messages that appear in the console the unlocked one this one is for regular messages we're going to use this a lot then we've got warnings and finally errors if you untangle them then the messages of that type will not show up on the console so if you ever come across an issue where nothing is showing up on the console make sure all three of these buttons are ticked then on left side on clear you can click on the Arrow to see more options I like to set it to clear on play then collapse this one basically collapses messages that are the same all of them into one entry personally I do nothing like this I want to see every single message as it comes out even if it's repeated I've also seen this lead to a lot of confusion for some people they think their code is firing just one message when it's actually firing hundreds So to avoid any confusion make sure you leave this Untitled then for airpods this will automatically pause the game when there occurs you should definitely have this one toggled if there is an area you definitely want to know about it you want to know when it happens so you can fix it whereas if you untuckle this you might get some errors and the game might keep playing which will then lead to lots of confusion when something starts behaving weirdly so always leave this one toggled and then the editor button this one is for more advanced use case so don't worry about it okay so that's the console then over here for the game view we've got a button here to select the aspect ratio let's go ahead and select fully Gene this one is a 16x9 aspect ratio so everything is pretty normal this will really only matter when we start working on the UI but so I like to keep it at 16x9 always then on this button that says play Focus we can modify some options basically Focus won't play exam like this on this small window if you choose maximize then it will maximize this one when playing the game and play in Focus won't play the game even when the window is not in Focus then another important one is actually on the same one as the aspect ratio here we've got a button to turn on vsync usually When developing the game you really want to toggle this that's because right in the beginning when the game doesn't really have anything you can leave it on Talent then this might run at like a thousand frames per second and that will pretty much drive your GPU crazy finally if your game view is looking a bit too pixelated make sure over here on the scale slider make sure this one is not zoomed in this one should always be pushed straight to the left as much as possible okay so that's the game view then over here on the scene view for this one default should be good these two buttons are extremely important pretty much all the time you want to keep the tone handles on the pivot it and not on the center if you ever see your handles on weird places always come back to this you want to sound pivot pretty much all the time then for rotation sometimes local is useful but for the most part you should probably be keeping in and Global then for the great showing the reason why yep down looks pretty good a nice little visual grid then you've got a bunch more options if you want then next to it we've got snapping this one we also don't need this for now and finally same thing for increment also don't need this okay then on the right for the drum mode let's leave it on Shaden for two then let's leave this disabled since we're working on a 3D game for lights let's make sure this one is enabled for sound we're only going to add this in the end so it doesn't really matter for now then for special effects usually you want this one to be enabled so it shows everything you can click on the arrow and make sure all of them are toggled the only exception is always refresh you probably don't need this little scene window to be refreshing at 60 frames per second so you can leave that one unticked and take on the others then these are for the hidden objects so let's leave them toggled for the camera here are the defaults and finally gizmos leave them all enabled as the defaults alright so down that's end here is in layout and going to be using throughout the course it will be easier to follow the course if you're using the exact same layout as me so ideally you should be using this but again like I mentioned all the windows are customizable so if there's something that you absolutely prefer differently then go ahead you can drag and drop and place any Windows anywhere you want so once you have layout your happy win you can go up here to the top right corner where it says default you can click on it and here you've got a bunch of layouts so you can save your new layout so I'm going to save this one as kitchen chaos and then over here you can select anyone you want for example if you ever have some issues with any kind of weird editor Windows you can load back the default layout and then go back and load your own layout okay so with that our layout is set up the next important thing is setting up visual studio so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to set up our Visual Studio alright so with the Intel layout setup let's make sure Visual Studio is also set up correctly I'm going to be using version 22 Community this one is the free version you don't absolutely have to use the same code ID that I'm using you can use writer or vs code or whatever you want so let's see my setup for visual studio but first let's actually set up something over here in unity so let's go up top into window and then let's open up the package manager then over here on the drop down menu let's select the packages and select the ones from DNT registry then let's scroll down to find the visual studio editor package so here it is this one this package basically handles the integration with visual studio so you can use the debugger and a bunch of things alternatively there's also a package over here for visual studio code and there's also one over here for jetbrains Rider so if you're using a different IDE go ahead and install the package for me I'm going to install the visual City one so this one just go ahead and install okay it's done so next let's go up into edit and let's open up the print preferences then over here let's go down into external tools and on the external script editor make sure you select the one you're using so again for me I'm using visual studio 22 and also over here you've got a bunch of extra options now if you want to play around with reading the source code for the very CNT packages then you can tick on these boxes but in our case for this simple game we don't need that so go ahead and leave everything just like this with defaults okay so with this setup now we can go over here into assets and open up the c-sharp project and this should open up visual studio and alright so here it is now for some more settings inside of here in my visual studio I have a really nice extension that adds a bit more colors to my code which makes it easier to read and write so up top let's go into the extensions menu and manage extensions and the important one that I've installed is this one vs4 if you want you can go into the online Tab and over here search for it any Apple that show up in here then for the settings on that extension let's go up here into tools and let's open up the options then over here let's scroll down and find vs4 Yep this one and here are all the settings and expand this and a bunch more settings now for me I think these are on the defaults I don't remember if I changed anything the important one is over here the rainbow braces so these have a bunch of Commerce which make it a bit easier to read the code so let's create a simple script just to see this so back in until let's go into the project window let's click the plus icon and let's create the brand new c-sharp script let's call it just testing wait for it to compile and now let's open now over here I'm just going to write a bunch of simple code just to test it out you don't have to follow this alright so here's a bunch of sample code these are the colors you can see it makes everything a bit easier to read although again this is not a requirement you don't absolutely need this extension but personally I do find it quite useful I find that it helps make the code more readable than having everything be gray okay so that's the setup for this extension next for the text formatting options so once again let's go into two holes go into options and then over here let's go into the text editor then over here I think I've got pretty much all the same defaults then we can go into the c-sharp rules so here are all the settings if you notice something different on your end go ahead and pause the video and compare the settings but again I think everything here is pretty much defaults I believe the only difference that I did was over here on the code style over here for new lines personally I like to have the currently brackets on the same line but if you want you can also change it and put it on the second leg I think that's pretty much the only difference that I did everything else should be exactly the same as defaults so that's the code sound settings and speaking of that the next lecture is very important we're going to talk a bit about naming rules although just before we go let's just clean up our testing script so let's close this one click on the X then back into Unity we don't need the script so let's just delete it okay so with that we have Visual Studio setup and ready to go now let's continue in the next lecture to learn about some naming rules hello and welcome I'm your code monkey in this lecture we're going to learn something extremely important let's learn about naming world this one is a very important lecture that you should definitely refer back to whenever you have some questions so first what exactly are naming rules these are really just rules you follow when writing your code it is extremely important that you are consistent in applying your own rules you don't want one class in your game to be written a certain way and then a different class using a completely different style that would create tons of confusion so naming rules and writing the code correctly is very very important one mistake that I see a lot of beginners do is they send me some code and ask why it's not working then I take a quick look and I see that all of the code is written in a very messy way some functions are on lowercase others using snake case some films are in personal case some in camel case and so on remember that code is case sensitive so it is extremely important that you write the code correctly if you change a character from lowercase to uppercase then you are suddenly referring to something completely different if you're a beginner keep that always in your mind code is case sensitive so don't just write code semi-randomly write it properly as if you were doing an English literature test now with that said when it comes to naming roles you can use whatever name neurons you want different people like different rules for example you can use a prefix in your variables you can use a postpick you can use capitals for consonants chemical case for properties snake case for Fields by the way here are the definitions of what those terms actually mean Pascal K starts with a capital and every word is capitalized camel case starts lowercase and then uppercase for the first selector of every other word kind of like a camel hump in the middle and snake Haze is where you add an underscore in between the words I send every rule can be valid the important thing is that you are consistent in always following through with your rules as you might know Unity mono behaviors have some deformed functions you can Implement things like start and update which are written using pastel case since you can't really change in these rules at least on function names I would say you should base your rules off of theirs so for functions you should probably be using Pascal case for the rules like I said choose whatever makes sense to you here are some of my own personal rooms that have developed jumped over the last 10 years and the code sound that I won't be following in this course for functions I use Pascal case just like unity and just like the c-sharp standard for function parameters I use camel case for Fields also camel case properties are in personal case constants are in uppercase snake case then another rule is that I like to add the top of the variable as a postfix so if it's a list type in the list if it's an array open array and now you might be thinking with this wouldn't it be an issue if we change the type then the name is suddenly wrong and the simple solution for that is that if I change the type then I just use Visual Studio to quickly change the name that's it then for the currently brackets like I mentioned in previous lecture I like them on the same line some people have some very strong opinions about this really it's just a visual style and this is the one that I personally prefer if you like new online then go ahead and use that it doesn't change how the code Works in any way in a final rule spend some time deciding on a proper name and don't be afraid to rename things you will note how all the code that we're going to write in this course has proper names for everything you should never use a variable with a single letter like X X or k the exception of course would be iterated in a for Loop also don't use acronyms or abbreviations those might seem player right now but in a few weeks you might not remember what they mean remember you don't get bonus points for writing extremely compact code so prioritize making your code readable and understandable even if it requires variables and functions with long names so these are my general rules and the code style that I personally follow figure out what works for you and follow your own naming rules but naturally in this course I will be using my own code cell so if when following the course you are not sure how to write some type of code you can refer back to this lecture and watch it again like I've mentioned many times the code that I won't teach you how to write in this course is on the exact same level of quality as my paid courses and my Steam games so as such because that this lecture these naming rules are all extremely important okay so with this very important lecture out of the way now let's start playing with some visuals by importing some Assets in the next lecture hello and welcome I'm your code monkey in this lecture we're going to import the project files with all the assets that we're going to use by the way remember that if you have any questions go ahead and post them in the comments I go through those every day and I'll do my best to help okay so with the project created the next thing we want is to import the assets that we're going to use to make this game you can download all of the assets with the link in the description which by the way like I mentioned a while ago that link contains a Unity package that contains both the assets and the final game so when you download that you get ENT package just go ahead and double click or click and drag and drop it on the projects window here is the asset import window just make sure you select all and let's import okay so here it is let's import the assets folder and inside comes all of the assets meshes textures and so on so everything we're going to need and then it also imported inside of it another ENT package so if you want to import the final project with all of the code already written it's also here if you extract this one you're going to get the complete project files now of course don't do that if you want to follow along with the course and be aware that if you're following along and you accidentally end unpack this one it will override all of your own files so if you want to inspect the final project files go ahead and do that but do that in a separate project in order to make sure that we have no accidents I'm going to delete this one from the current project so just go ahead and delete okay so that's it and over here we've got all of our really nice visuals we can look in the prefabs visuals and over here we've got a visual for a container Sergo that's a container counter then we have a cutting counter we've got a trash bin then on the kitchen object visuals we've got all the visuals so a block of cheese we've got some burned meat we've got a plate and so on these are all the nice 3D models that we're going to use in our game and then over here on the textures folder we also got a bunch of General icons as well as actual icons for all of the various parts okay so all of the assets have been important now let's continue on to the next lecture hello and welcome I'm your code monkey in this lecture we're going to set up post processing now here let me make a quick note usually when making your games you probably don't want to hand on post-processing right way you should first get an ugly prototype up and working before worrying about any visuals so normally I would only add post-processing much later on in the dev process but since this is a course in video format in order for the video to look a bit more appealing let's set a post processing right away now we already have the project set up to use urp so adding post-processing is actually super simple it's actually already added by default first before we do that let's rename our scene with a proper name so inside the scenes folder it starts off with sample scene this will be our main game scene so let's just rename this to game scene okay and now here on the hierarchy we can see by default this scene already contains a global volume game object this is how you actually add post-processing and by default you can see that it also already has a sample and profile attached this is how you add all of the various effects you can click on this link and it will show it over here on the project window now let's film this from scratch instead of starting from this one so let's go into that file into that asset and just delete it okay so now we have no value profile now let's go ahead and click on new to create a brand new one okay so now here we can add overrides add all of the effects that we want let's drag some visual meshes that we imported in the last lecture to get a better look at all these effects and what they do so first let's make some kind of more so let's make a 3D object let's make it a plane let's name this D4 also one extremely important thing whenever you create a brand new object always check the object's transform position by default when you create an object it appears in front of the scene camera which will probably not be on zero zero zero you always want to be very careful with the position of your actual objects so for a plane we do want this to be on the origin so on zero zero zero so make sure you always do that then let's scale it up a bit so on the scale let's put it on 555 which by the way you've got this nice little icon this was added in a recent Indie version basically if you enable this and matches all of these values so if you just change one of them it changes all of them so let's put this on Five okay great now for the visual let's go ahead into the mesh render on the materials and let's select the brand new material so let's click on the circle icon and over here let's find the floor material so here it is it's the one included in the assets there you go we've got a nice basic form material now let's also drag the player visual so let's go inside the assets folder and over here let's go inside the prefabs visuals and down here we find the player visual so let's just go ahead and drag this one so there it is a nice player visual let's also drag a counter so let's find let's say the Clear counter let's drag this one let's rotate it to face the camera something like this and let's also put a cutting counter again we're just placing some visuals just so we can see what the post processing will do and let's also place a bunch more things so let's say a tomato let's place a tomato over there and maybe cabbage all the way over here okay so we've got a handful of nice visual elements so we can test out our post pressing by the way here's a quick empty tip on scene controls whenever you are on the scene view which make sure you're on scene View and not game view those are different so on the scene view you can move the camera with a mouse you can pan with mouse 3 so the middle Mouse button so hold that and pan around we can rotate with the right Mouse button you can rotate around Point by holding down left alt and left click and just drag it around to rotate around an object you can select an object like for example player visual then you can press on F to select that object and now if you hold alt and click it will rotate around that object also another method is you can hold the right Mouse button to move it around and then you can use was to move so d a and so on then you can even press shift to move in faster and you can use the scroll wheel while holding down the right Mouse button or to modify the speed at which you move so there are plenty of camera controls to really get you seeing exactly what you want to see now for another quick empty tip you can move the scene camera to where you want the game camera to be so let's say I want the game camera to see things from about this angle so you just position the scene camera then on the hierarchy select the camera game object so the main camera right here and with that object selected you press Ctrl shift and F and if there you go you can see over here on the camera preview let it position the main camera looking on the exact same position at the exact same direction as the scene camera set the shortcut Ctrl shift F or alternatively go up into game object and over here on line with view now if you look here is the scene View and over here we've got a nice camera view so just position the camera somewhere where we can view all of the Assets Now with this let's add some post processing effects so first let's select the global volume game object and over here we can add all of our effect overrides first up let's begin by adding tone mapping so there you go we've got the effect and over here we've got a nice little checkbox so you can enable it in order to enable this effect and set one of the options now for this one I'm not too familiar with color correction but I find that usually adding a neutral tone map usually that helps also make sure you're looking at the game View and not the scene view if you're looking in the game View and you enable and disable this effect you should see a difference whereas on the scene view if you enable and disable it doesn't actually show that even if you're on the scene view over here you have all the effects enabled even with that some effects for some reason don't show up on the scene view so when playing around these effects almost make sure you're unlocking through the game view so like I said you should be able to toggle this and see a visual difference on the game view if you don't then make sure the camera has post processing enabled so let's select the main camera game object and down here there's a tongue for post Crossing make sure this one is enabled and then also on the render pipeline assets so let's find that one on the project window over here we've got the settings and we've got the urp High Fidelity this one should be using a renderer so if you click on the renderer over here you should have post-rossing enabled again all of this should already be correctly set up by default so if you're going to take a global volume enable our disabled you should see a visual difference okay so next Effect one that I always like to add is a bit of saturation so let's add an override post processing and let's add a brand new here it is color adjustments then over here you've got plenty of things to play around with for me I like to add a bit of saturation so just lift it up a little bit let's say just about 20 and I also like to add a little bit of contrast over here and let's also add 20. and there you go it makes the colors pop a little bit more so personally I don't like this effect then later on we're going to have some glowing objects for example the stove let's actually try dragging that into the scene so let's go into scene View and in the assets let's find the stove counter so here it is and inside the stove counter there are some things so here it is the stove on visual this one is disabled by default also on the inspector let's just enable on this game object to make it visible again don't worry about the positioning of the objects on the scene view right now we're only positioning them just to set up the post pressing we're going to delete them all at the end of this lecture okay so now in enable let's go into the game View and over here we see the stove enabled so now let's go into the local volume let's add an override go into post pressing let's add a volume effect so right now notice how that one is not glowing red hot for that work we need to have Bloom and we need to enable the threshold and the intensity if we raise the intensity we do see yep there we go a really nice low there by the way here's a quick visual attempt if you want to make your game feel a bit more ethereal and magical one good way is to put the threshold that on low value below one so something like 0.5 and then put the intensity as a little bit and with this notice how everything has a slight low even colors that don't have any extra intensity so the floor is glowing the character is going so everything looks quite a bit ethereum this is a bit extreme but it is an interesting effect also another quick note here in case you're not seeing anything change make sure you go into the render prop online assets so the urp High Fidelity and over here make sure AGR is enabled you can look at so low if I disable it yep that one stops glowing and with that enabled it does start glowing AGR stands for high dynamic range so that is how you can have a color go with an intensity above one which actually makes it low when you have the balloon post pressing if even with that you're still seeing issues then make sure you go into the renderer and over here for the post processing sometimes Unity has a weird bug and doesn't generate this post-process data file so if that does happen just go ahead untoggle and toggle this and it should work and finally like I said on the camera make sure you have post Crossing in Arrow so with all that you should be able to see the game view glow okay back into our effects with our balloon working like I said you can lower this below one to get a nice ethereum look but this is a bit too intensive on what we want so let's make it a bit more subtle so on the threshold let's put it at 0.95 so there's a slight low on the white Parts but nothing too intense and for intensity let's put it at a wrong number one okay so I think that's a nice amount of Bloom all the colors glow a little bit and we can see over there the stove it is indeed glowing okay great now if you ever forget all these steps and you can get your project to Glow I made a nice video with a nice checklist of everything needed for you low definitely go ahead and watch that video whenever you have issues then for another fun effect we have yet so let's go into ad override post Crossing and let's find the vignette what this one does is adds a bit of Darkness to the colors so if we enable the intensity and we increase it you can see what it does so it adds Darkness around the corners there personally I find this one looks good when it's quite a bit subtle so let's put the intensity at some like 0.25 and then for the smoothness let's also put it on 0.4 so just like that just a slight Darkness on the edges so personally I think it looks pretty good and that's pretty much it for the Post Crossing on the volume component I like how this looks you can see difference with the volume enabled or disabled quite a big difference looks pretty nice but again these are just visuals so feel free to play around maybe add some more effects using different settings these are just visuals they don't impact the game logic at all so feel free to make it work exactly as you wanted then yet another thing related to post processing but not in this component it's some anti-aliasing for that one place where you can change it is on the main camera over here you see a film for post Crossing and you have a bunch of types so fxa a or smaa or if you want some more higher end post processing you can go into the render prop online Essence so urp and hyphenoly and over here we see anti-analyzing msai this one is a bit more expensive but looks a bit better if you want to see difference you can go over here into the aim View and on the slider up top on the scale you can increase this quite a bit so with this we can now see the pixelation and you can see over here if I switch at the only thing from 4X back into the table you can see lots of jagged edges and if I put it on 2x Yep looks a bit more smooth 4X a bit more smooth and 8x even more smooth so with that you can see difference on all the edges on the things by default this renderer has on 4X and nothing on the camera this already unlocks pretty good but to make the video look even better I'm going to put it on 8X and on the main camera I'm also going to leave it with no anti-alency you can combine them but if you do then everything looks a bit too wiry so I don't quite like that effect so put this one on none and the other one on 8X although again this is just a visual so if you have a low end PC feel free to go into the urp and over here disable anti-alizing so the game looks a bit worse but it won't run much better okay let's drag the scale back down okay now one final thing we can add is some really nice screen space ambient conclusion for that let's go into the render so not the render pipeline asset the renderer and over here by default it already added screen space ambient Collision if it didn't add you can click on ADD render feature and over here you won't be able to see it I don't see it because I already have it okay so here it is basically what this effect does is it adds some tiny Shadows where geometry intersect if we enable and disable it quickly we can see the effect over there on the counters so you can see with default effects it already Works quite nicely for example look there on the player we can barely see the difference between the head and body but if we enable this it has that nice little Shadow I think it looks really nice but then we've got a bunch of settings we can play around increase the intensity the radius and so on Now One important thing when setting all these effects is to remember the point of view of the camera in this case we're making a top-down game so before we play around these settings let's actually position the camera in a correct position so let's go ahead select the main camera and let's position it above pointing down so let's put it on an X of 0 on a y of 21.5 on his head of minus 21.3 then for the rotation on the X 46 then 0 and 0. and finally on the camera over here on the field of view instead of 16 that's really wine for this game let's go with 20. okay so this is the view that we're going to use for our game let me just rotate the object so they actually face the camera so on the hierarchy let's just select all the objects let's rotate them all around and just position them again we're only using these just to see what they look like we're going to delete all of these objects in a bit okay so yep that's the game view now that we have the camera set up let's work on the settings for the eminent conclusion so let's go down select the renderer and over here for the settings for the intensity and let's put it on four for the radiance let's put it at 0.3 and direct lighting strength let's put it all the way up to one okay so you can toggle this enable and disable to see difference and yep I do think these settings look pretty good finally the last thing we need to check is in lightning window so let's go into window then down into rendering and let's go into lighting how it pops up the unlighting window personally I like to Anchor it over there next thing inspector and over here we're really going to leave everything on defaults so you can leave it as the lighting settings assets and nothing assigned and then on the environment tab over here again all of the defaults I didn't touch any of these so we've got environment lighting from the Skybox and then some multiplier of one so everything pretty much on defaults although again like I said most of these visual effects are very much personal preference so if you want to make your game look a bit different than mine then go ahead you can play around with lighting over here you can change Skybox gradient color and so on if you want you can use some bake lighting then if you want you can add all kinds of extra effects and also by the way remember that the effects are stored on this profile over here so for example you can click over here on the Clone button and it will include the effects and let's click on it to find it yep there you go so that's the one that I've built and here's a clone one so if you want you can make a clone one and then make it look very different for example let's go into chromatic aberration make it really intense and for example let's go into the counter curves and over here for some reason let's drag the green up and so on so there you go completely different visual so if you want to play around make some weird effects and if you want to go back to just revert back into the original profile personally I'm quite happy with how this looks so I'm going to be using this one okay again you can enable and disable the volume game object to see quite the big difference that post-processing makes if you ever want to make your game look quite a lot better always make sure that some post processing alright so like I said this looks really good I like it now before we go to the next lecture let's just clean this up so let's get rid of all of these objects so the counter cabbage tomato and so on let's get rid of all of them except the four so let's leave the four and get rid of all these alright so here we have our nice empty scene let's just save our scene and let's get ready for the next lecture hi there this is a quick intermission so how are you doing are you enjoying the course so far are you having any trouble with anything is there something you didn't understand if so remember I'm always active in the comments answering all the questions so if there's anything you need some extra clarification go ahead and ask and I'll do my best to help also remember to check out the pin comment YouTube videos cannot be updated so for any notes or comments I'll put them in the pin comment and definitely check out the website page for this course as people ask more and more questions I will keep that page updated with any frequently asked questions for every single lecture so that way you can see what others have asked and learn from them and you can also download the project files for each lecture so keep that page open on a second Tab and check it every time you start watching a new lecture I really hope you're enjoying the course and I hope you've already learned quite a few things go ahead and hit the like button and subscribe to the channel if you haven't already okay so let's go to the next lecture hello and welcome I'm your kudmaki in this lecture we're going to begin creating our character let's make a nice character controller so we can move our character in the world okay so first let's begin by creating the character game object and now usually most beginner tutorials will tell you to just right click go into 3D object and create something like a capsule that way you would have the game object with the visual included however for a good project structure and good organization you should only separate the visuals from the logic for example here in let's say that I don't want my capsule exam like this let's say that I want my player to be a little bit more skinny to do that I would have to modify on the scale on this game object so put it maybe on 0.7.7 so something like this basically by doing that by modifying the visual I also modified the scale on the actual player game object having a non-uniform scale on a logic game object that can cause all kind of problems with any kind of logic component also I would prefer to have my character on the floor but if I put it on yf0 notice how the character is half underneath the floor so if I were to use this method I would have to apply some kind of offset in order to make the visual above the floor so that would require rearranging all the logic to work with an offset on the Y position so because of those reasons and many more you should not Place both the logic and the visual on the same game object instead you should separate them so let's get rid of this and instead let's create an empty game object let's name this the player let's put it on zero zero zero okay and now inside of it now inside let's create let's say a capsule now in this one we can easily scale this to get any size and shape you want so for example 0.7.7 then since the visual is a child of the game object we can also easily offset this so let's say you put it up by about one unit so with this we can position the visual so that basically the player game object is over here on zero zero and the character is above the floor so we don't have any weird offsets this will make all of our logic much more simplified and on this empty Parent Game object we can attach all of the logic components we want and then in the child visual we can either replace whatever visuals we want so as a general rule you should always try to do this only separate the logic from the Visions in your game objects okay so with that we have the player game object now let's make our character controller script and before we do let's keep things once again organized so before we do let's create a brand new folder so let's right click on the assets create a brand new folder call it scripts and now inside let's right click and create new c-sharp script called the player wait for the code to compound then select the player game object and attach the script again remember logic components go on the parent game object not the channel vision so the challenge visual this one only has visual components and the player this is the one that actually has the logic components so let's open up this script okay so here's our first c-sharp script like I said I'm going to assume you know the absolute Basics go watch the c-sharp basics video If you haven't seen it yet so I won't assume that you know what is a function what is a variable what is start and update so pretty much the absolute basics for a character controller we first need some input from the player and for that EMT actually has two methods you have the Legacy input manager and the new input system basically the Legacy input manager is super simple and very easy to use so this one is perfect for quickly prototyping and the new input system is extremely capable with tons of features but it's also a bit more complex so what I do is while I'm doing a simple demo or testing out a new prototype by just using Legacy input manager but when making a more complex project like for example my sim game then at a certain point I refactor my code to use the new input system so here I'm going to teach you both as well as teaching you how to refactor code which is an extremely useful skill so let's first begin by using the Simpson Legacy input manager we want some basic was movement to move our character and we're going to need to run that logic on every single frame so let's do it on update and let's actually get rid of the code that Unity writes by default let's start coming from scratch and let's get rid of this just close okay so here let's start by writing private void update and now here very important if you're a beginner make sure that update is written exactly like this if you write update with lowercase if you do this then it won't work the function will not be calmed automatically I'm pointing this out because I have seen a bunch of comments from beginners wondering why their code doesn't work and it's as simple as this with a lowercase Unity will not call this automatically it needs to be exactly perfect so again if you're a beginner make sure you write the code exactly the code is case sensitive so this is very important also another note you saw that the code that Unity wrote by default when we made a new script it just had void update it did not have the private keyword private is what is called an accessor you have private then you have public and then there are some more advanced ones secondly you can omit the accessor and in most cases it will default to private however in writing good clean code you should be as explicit as possible there should be no room for misunderstandings so while technically you could emit the private you should always include it to make your code easy to read and easy to understand this one is the first of many clean code rules that I will teach you during this course like I said all of the code that I'm writing here is on the same level of quality that I use in my own professional games I'm not going to teach you bad practices like so many beginner tutorials do so always be explicit always include the accessor okay so we have our update Running code on every single frame then to test if a key is being pressed we just go inside input then over here we've got two functions so we have get key and get key down both these functions were turning Boeing so that's how the true or false the difference between them is that get key down this one only returns true for a single frame when the key is pressed whereas get key this one stays true for as long as the key is held down for example for an action like jumping you just want to know when the player presses the button so for that one you would use get key down however in our case for a character controller we want to know if the key is being held down we don't want just one frame but always so for movement let's make sure we go with get game then requires a key so let's write our key code and then choose the key let's say we want w and then let's just put this inside and if just like this okay so here we have code we want to run while holding down the down key let's do a quick test just to verify everything is working perfectly and for testing we can use a super useful debug.log this one lets us print a message in the console someone said One log here just say something like pressing and then let's also do an else and if else let's do a debug.log and just do a dash okay so here is our very basic script let's make sure to save it so Ctrl s then back in unity over here make sure you have the script attached to the player game object and now we can test and now down here on the console we can already see dashes so I'm not pressing anything also like I mentioned in the setup lecture if you're seeing just one message then maybe that means you have over here the collapse Target if you talk on it and look how it only shows one message but then over here on the right side it says the number of messages personally I prefer to always keep it untoggle so I can see every single message also over here on the right make sure you have info messages visible if you untangle this and you don't see it so make sure this one and actually both of them make sure all of them are enabled okay so we're seeing a whole bunch of dashes and one more note if over here these chromebars stop scrolling so right now you can see it's stuck up instead of being down there so if that happens one is easy way to reset that is just click over here on clear and it goes back into AutoZone okay so we have the dashes I am not pressing anything now as I press yep there you go there's a message if you don't see it make sure the game window is in focus so selective game View and click right here on the middle to make this one the focused window then if you press the down key you should see the message and if I Let Go yep there it is and I stash okay great so all the basic logic is working back in the code here now that logic is working let's get rid of the else here and let's set this for all the other keys so let's copy paste this so we're going to need w a s and D so let's make all of these okay so we have our inputs let's also get rid of the logs we don't need this all right so we have all of our key presses now let's construct a vector with our inputs and since we're just going to have two axes the double s that is forward and backwards and this one is left and right so just two axis so because we have just two let's use a vector two and let's call it the input vector let's construct it so we'll do a new one and start off at zero zero okay then over here the logic is pretty simple so when we press W then let's go into the input vector and set the Y to pause one then when we have an S we want to go backwards so put the Y on -1 for the a we want to go left so that's an x on the minus one and finally for the D that is an x on plus one okay so with this we have our correct input Vector let's do a quick log just to test so debug down log on the input vector okay so let's test all right so we can see in log zero zero okay makes sense now if I press W yep we've got an 1 on the Y if I press a we got minus one in the X press D plus one press s and minus one okay great so everything works except we also need to be careful about one other thing if I press both W and D with this look at that the vector is 1 1 which is correct that's exactly what it is then except the factor one one actually has a bigger magnitude than just one vector if we leave it like this then the character will move faster when moving diagonally versus when moving in just one direction for our input Vector we really want it to be normalized meaning we wanted to have the same size regardless of the combination of keys that we're pressing so back in the code here after calculating the input vector and let's simply normalize it so we go into the input vector and we set it equals to input Vector Dot normalized so this will normalize our input Vector let's see and over here if I press doubly you've got one press s minus one okay so all those work now if I press both W and D if there go now it says 0.71 when you combine both these I need the math these do end up with a magnitude of one so with this our character will move at the same speed on both diagonals and straights okay so we have the input Vector on correct now let's actually apply some movement for that there are many ways of making a character controller for example you can decide to use physics or not over here I want to keep the game simple so let's not use physics instead let's just move the player transform directly over here we have our input Vector okay great now we want to apply this to our character position so first we access the transform this one refers to the transform where this script is attached to this script was attached to the player so this is going to refer to the player transform then we want to modify the position so let's access the position and now for moving we don't want to just assign it if we do something like this like this the player would never leave the center of the world he would always be near zero zero so instead we don't want to just assign it but instead we want to add onto it now if you're a complete beginner and you don't know this syntax then this one is exactly the same as this so transform dot position equals transform dot position plus input vector so both these little lines are doing the exact same thing personally I prefer to use the shorthand I find that equally readable and more compact okay so we have this and we add our input Vector to the transform position except we can also see a really nice error basically it's telling us that we are mixing two types our input is a vector two where we only have an X and Y but transform that position is a vector 3 meaning it has an X Y and Z one simple solution is to cast our input Vector onto a vector three so we just convert this from one type into the other one and yep we don't have the error so let's test and now if I press W any of the character does move Let's ignore the massive speed for now so it does move it does seem slightly correct except you can obviously notice that it's not correct we are moving on the x-axis on left and right that is correct but then we are moving up and down instead of fourth and back basically we convert the effector 2 directly into a vector three so we are moving on the X and Y axes but in our 3D game we really don't want the characters to fly so instead we want to move on the XZ axis so back in code here instead of directly casting this down into a vector 3. let's construct a move to your vector similar to Vector three let's call it our move there for our move Direction and over here we construct a new vector3 and basically we're just going to assign the input y to the Zenon here so first of all for the X7 is correct so input vector.x then for the Y let's leave this one on zero and finally let's use the input vector.y as I said on the Move direction also now at this point you might be questioning if we're using a vector 3 here why don't we also use a vector 3 appear and then just assign the Z directly that's certainly a possibility and for making a super quick prototype I might even do that myself but the proper answer to that is once again all about writing good clean code the input logically only has two axes there's no z-axis on your keyboard so logically it makes no sense for the input to have three axes and beyond that you should keep the logic separate so you should first get the input and then actually move the object we're going to see the benefit of that separation when we refactor this code to work with the new input system doing that will in turn make enabling Gamepad joystick support super easy because we have the input Vector separated from the actual movement some of that to say and let's do things properly let's keep the input Vector separate from the movement Vector so we just translate the X Y onto X end and then we just apply this into our transform position okay so let's test so now if I press the right turn left and press W and S and there you go okay great so it is indeed moving Left Right forward and back okay great so it is working but as you can see it's moving insanely fast you might think the issue here is just applying some sort of movement speed multiplier except there's actually one sneaky issue here on the game view on the top right corner we've got a stats button and over here we can see a whole bunch of things specifically we can look at the frame rate we can see that it's running at 144 frames per second over here on the left side on this button I have vsync enabled this will cap the frame rate to the monitor's refresh rate so that is why I'm seeing 144 Hertz I can overhear disable vsync and the upload that goes all the way up to 700. basically now the game is running as fast as my computer can run it and if I press the movement keys and look at that now it's moving even faster now I've completely lost track of where my player is this is not what we want we don't want the player to move at different speeds depending on the frame rate we want it to always move at the same speed regardless of frame rate so when you do any kind of movement Logic on an update you always need to make sure to multiply by time dot Delta time what this variable contains is the number of seconds in Labs since the last frame for example let's unlock to this we no longer need the input Vector so let's unlock just the time that down to time okay so we can see there there's basically telling us how many seconds it is taking to render a single frame once again note how I have vsync enabled so I'm running at 144 frames per second and now if I disable it let's see what happens to that number so if I disable and you have a look at that that number is now much much smaller and the game is now running much much faster so by incorporating this value into our calculation we are going to be taking into account the frame rate thus making sure that movement is always frame rate independent right now with this frame rate if I move you can see I'm moving at this speed and now if I enable vsync change the frame rate and I move and I'm still moving at the exact same speed okay that's great except obviously it's not exactly great it's moving way too slow so let's also incorporate a movement speed now for this once again most beginner tutorials will teach you to go all the way up here and find a public float move speed maybe they found it to some villain like 7f something like that then you have this field and then down here you simply use it in the calculation so movement here move multiply it by move speed and by time dot time so this is what most tutorials will teach you by making it public up here what you're doing is you're enabling access from the editor so if you go over here in the editor over there on the player we can see the move speed variable we can see this exposed and we can modify it this makes it really easy for testing and for iterating upon the value even while the game is running so the game is playing I can move and I have this move speed now I can modify this and yep now I got a different move speed so I can use this to quickly to rate and find the perfect value so it's great to have this variable exposed in the editor and this feature is indeed the reason why most beginner tutorials will teach you to make it public it's so you can see it in the editor that is indeed a very valuable thing being able to easily iterate upon important values is always very useful however when you make something public when you do that you don't just expose the film to the editor you are exposing it to every other class in your entire code base so some other class could access this field and set the player's movement speed to something like zero and you would have no idea that was happening because the issue would not be on this code right here I have an entire video on this subject why you should not make everything public this is an extremely important topic to know about this one tiny change will massively improve the quality of your code definitely go ahead and watch that video to learn why such a bad thing and make sure you don't do it so to avoid all kinds of problems you should never make films public so very quickly the obvious alternative is make it private making it private means that only this class only the code in here only this can modify this film so you know for certain that no other class can ever modify this however making it private also means the editor cannot modify this film so we've lost our very useful iteration approach so what we can do to expose it just to the editor is to keep it private and then we add the attribute serialize field this way this field is still private meaning that it can only be modified by the code inside the player class but with this attribute over here in the editor yep we do have an editable field so only the code in that class in the editor can modify it nothing else can touch it nothing else can read or write which is exactly what we want one of the main rules in writing good clean code is minimizing complexity and one of the easier ways to minimize complexity is simply to minimize axis by making this feel private we are minimizing complexity because it doesn't matter how complex our game is maybe our code base is a thousand classes long it doesn't really matter because only this class can never touch this field so if we have a bug related movement speed we know for certain it has to be inside this code and nothing else so we minimize the things we need to keep in our head which is always a very good thing okay so with all that said we have our movement speed and down here we are incorporating it into our calculation just with this we have our character working with a variable movement speed and by using Delta time we have our movement correctly being frame rate independent so here's our character and using the keys I can walk around and yep the character moves in any direction so we have movement only working while using the Legacy input manager like I said we're going to learn how to refactor our code to use the new input system learning how to refactor is an extremely important skill to improve your own programming skills it is something that you should always do when necessary it will massively help you improve the quality of your code so we're going to do that but before we get to that let's actually do something a bit more fun and add some proper visuals and animations to our player in the next lecture hello and welcome I'm your code monkey in this lecture we're going to replace our boring capsule visual with a nice proper character mesh okay so in the included assets project files over here if we go inside the prefab visuals we see a nice player visual let's position it inside the player game object so let's drag it inside again because we separate the logic and visuals this is going to be pretty easy we don't need to modify the parent game object at all we just dropped the visualize this channel that's it also again very important make sure the visual is over here on low composition zero zero zero only the parent game object should move the visual itself should never move if you notice some weird positions as your player moves and rotates always check to make sure that the channel visual is on zero zero zero okay so with this let's delete the old capsule delete it okay so here we have a pretty simple but really nice character visual it's really just two spheres stacked on top of one another with a bunch of eyes very simple for the visual itself the material is using just a solid color so here it is inside the assets material you can see a bunch of player bodies with different color these different colors they won't be used in the upcoming multiplayer video basically each player will have a different color also by the way if you're a complete beginner here's a quick lecture on materials these are materials and if we call it select we can see a bunch of sets related to that material basically the materials have a Shader and then a bunch of properties now the Shader is the actual code that runs on the graphics card that says how an object should be rendered by default you have a whole bunch of included shaders we're using the universal render pipeline so you should mostly be using the ones inside the urp and by default you probably want to be using the standard light Shader then of course you can also build your own custom shaders one excellent tool for doing that is shade graph which I have covered in detail in a previous video it's a fully visual tool that you can use to make shaders without having to write any shutter code it's a great tool I've also made a bunch of tutorials on all kinds of effects you can make although right now we're not going to be using custom shaders we're going to do that later on the course but for now we're going to stick with default light Shader so materials have a combination of shaders and the properties on that Shader for example over here for the phone light sharing you can see that it has over here based map that has a counter field this is what you can change to apply a different color to your player also as to how you apply a material to an object over here on the player visual you can see the objects are made up of a sphere so this is the mesh and then the mesh render this is the one that has the material so both these are what stores the shape as well as the visual for the object the mesh is just a 3D shape but just by some of the mesh filter doesn't actually render anything so it needs a mesh render which needs a material attached to it so for example over here on the hierarching let's right click on empty space and let's create a brand new Cube just to see it so if there you go it does create an object and as you can see it has a mesh filter and a mesh render now to apply a different material you can click on this little circle icon and it shows you all the materials in that project alternatively you can grab the material directly from the project window so for example the player body just grab it and drop it in there or you can also drop the material over here on scene view as you can see as I Mouse over different objects it applies that material to a different object although note that only works over here on scene view it does not work on game view so this basically sets the material over there on the object right now one more very important thing on materials if you have multiple meshes only using the exact same material and then you modify the material it won't change the vision while all meshes using that material so for example if I modify the color here put it on something different there you go all three instances all three objects that are all using the exact same material they all update to the new color if for example you wanted the head to be a different color from the rest then you would just create new material so you can right click on the project window let's create a new material then you can give it a name give it colors use a different shade or whatever and then use this one for something different so that's pretty much the basics for materials and by the way if you're a complete beginner and you have questions remember to post them in the comments and I'll do my best to help like I said I want to keep this video moving I'm trying to teach as much as possible while still keeping the video reasonable length so if you need any further clarification on anything specific just go ahead and ask in the comments okay so when materials are out of the way here we have our player with visual let's just get rid of our Cube okay and just with this if we test and yep over here we already have a nice player visual walking around okay great except the player isn't actually rotating ideally the visual should be facing the walking direction so if I walk down it should be rotated to face down so let's have that doing that is actually going to be pretty simple let's go into our script here we are on the player script and over here we already have the movement Direction so we're going to use this in order to make sure to rotate the game object to face this move Direction and for rotating and transform there are many many ways to do it one obvious one is to modify the transform dot rotation however this one as you can see works with quaternions for me even though I've been doing Game Dev for over 10 years I still find quaternions quite a bit confusing so I normally don't use this method another method is to modify the transform dot Euler angles this one is much more intuitive and makes more sense to me it works with regular Euler angles which is much easier to understand if you don't know that name it really just means the angles that go from 0 to 360. then for another method you can also use the function transform Dot and look at this one makes a transform look at a certain point so it can be a transform Target can be a vector three for one position and anything like that so this is a very useful function we could calculate a point right in front of our move Direction and look at it or finally the method that I personally like to use for this specific purpose which is just modify the transform dot forward this one has the normalized vector representing the foreign axes and importantly you can get it and you can also set it so you have both read and write you can read it to get the current transform for it but you can also write to it to essentially rotate the transform so we can just assign this to our forward Vector also by the way you also have transform dot up and transform dot right both these work exactly the same way for example transforms are right this one is extremely useful for 2D games but over here we're working in 3D so we want to transform that forward and all we need is the forward Vector which is really just in move Direction so let's set this one equal Z move there okay so just like this it shouldn't really work let's also just clean up the log we already need to see the Delta time okay so let's see like this okay here we are and as I move and you better go and look at that the player object does indeed rotate to face the move Direction okay so it's already looking great all right awesome however it also looks a bit odd with how it's instant so I move left and right look at that it instantly rotates so there's no smoothing nothing it's way too janky so let's add some nice simple smoothing and for that let's use a really awesome really useful math function called lerp it helps you interpolate between two values I made a quick video showcasing a bunch of uses for it you can alert floats Vector 3s quaternions or just about anything it's really perfect for making some smooth movement or smooth rotation so for that we can access the function inside the vector 3 class so we can find an alert then here we actually have two options we've got learn this one interpolates and we've got slurp this one interpolates but with a spherical interpolation basically if you're dealing with rotations like what we have here then we want to be using slurp whereas if you're dealing with just positions and you want to use so here let's use slurp this one as you can see takes an a a b and a t like I said this interpolates between A and B based on T so for example if T is zero then it won't return the value a if T is one then it won't return to Value B if C is 0.5 then it won't return the point in between A and B if you want to learn some more about interpolation and the math behind this then I highly recommend you look at my video on splines splines are basically just a whole bunch of merps put together so anyways over here we can add some smoothing to our Rotation by just using the current transform.ford as our a then for the B this one is our Target so let's use the move there and finally 14 let's use time dot Delta time meaning that with this over time the character won't rotate towards our Target movement Direction so just with this let's test so here if I move to the right and you have a look at that it is indeed rotating it's way too slow but yep it is rotating smoothly all right so let's just add a bit more speed so over here let's just find a float for the rotate spin let's put it at some like 10f then we just multiply it to times that down time multiplied by our speed let's see and move any up there you go look at that much much better okay great so as you can see everything works as I move the character does rotate to face the move Direction all right great so here we have our character with a nice visual all rotating to face the move Direction now next step is we want to add some nice animation so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to add some animations to our player character now I have already included some pre-made animations with a pre-made animator over here inside the Asus folder but let's first do it from scratch so you'll learn how to do it first to animate we're going to need the animator component if we go inside the player visual game object once again remember all the visuals go on the visual game object so for adding the animator component we want it on the visual and not on the logic component so anyways over here as you can see by default I already attach it with the assets included but let's do it from scratch so let's remove this by default now let's add a new component let's go on an animator also one very very important thing here it's the animator component not the animation component these QR can only difference the animation component this one is actually related to unity's Legacy animation system from a very long time ago it's only here pretty much for a backwards compatibility and for super simple use cases so most of the time make sure you're using the anime tour component okay so to drive this animator component we need an NM troller let's go into our project files and let's create and create a brand new animated control let's call this my player animator then let's select the player Visual and just drag the controller on there okay again if you have issues then you cannot drag the animator onto the film make sure you're using the animator and not the animation component okay so with this we have assigned our animator controller now let's double click on it to open the animated window and if you don't see it then go into window then go into animation and open up the animator window and also if you still don't see anything that maybe you might have some issues with your layout if that's the case then go on to the top right corner layout and go back into the default and then back into your own layout and finally if you still don't see anything on this window if you don't see defontes make sure you have the object selected in the hierarchy so with that you should be able to see these states so this is our animator controller now I have a really detailed overview of the animator and the animation windows in my ultimate unity overview course so you can go watch those lectures for some really in-depth explanations about everything this does basically the animator is a state machine so you have various States and you can create transitions between each state by default you have these three special States there's the entry State exit and any state these are used for making transitions but we don't really need to worry about them just for now first let's just make a basic new animation and for that the easy way to do it is to open up the animation window so let's go up top into window go into animation and open up the animation window so here it is again that's a different window that's animation not anywhere and for me for this window I like to dock it down here so there's a nice timeline so I think this is good okay and now if we select the object in the hierarchy that has our animator then we can see the text here so to begin animating we've got a nice button to create an animation so let's go ahead and click on this and now let's give it a name for now let's first make the iPhone animation so let's just call this Idol and name just like that we have created an animation you can see the animation window down here has changed we now see a nice timeline showing the time and also on the animated controller you can see the new animation was added as a brand new state so a new state was created and if you click to select it on the right side in the inspector you see the motion so the actual animation selected and you can also see that there's an arrow pointing from the entry onto the unknown state so that means this one is going to be the default State when the animated controller starts it won't start playing right on this state let me just point out one more thing related to animations so on the project window we can see yep here is our animation that we just created and you can see the inspector unlocks just like this now if your inspector looks differently that might be because you accidentally created the Legacy animation that has to do with the previous animation system that I talked about the one that is Legacy that should really no longer be used so if you see a different inspector then a quick way to fix it is to click on these three dots on the inspector these three dots then you change the inspector into debug inspector and over here you see a toggle on foreign legacy so for the animations that we want to use right now we do not want to be using Legacy animations so make sure this one is untoggled if in our case is toggle just untoggle it then go back into the normal inspector and now yep it shouldn't look just like this okay so we have our animation and now it's on our animator controller now it's actually make an animation so let's select the animation window though and again let's make sure to select the objects and let's select the player visual game object so here on the animation window we see this nice little red button this one enables or disables recording so if you click on it you can see yep the timeline is now red meaning that we are now recording and now we can do anything to any channel objects and it won't record any changes we make now note what I said that's very important it needs to be challenged objects if you select for example the apparent game object then all of a sudden it stops recording so you can only animate child objects so let's select the player visual let's enable recording then let's expand the player visual let's make sure that our timeline is on zero so drag it all the way to the left and now for example let's grab the head object and let's move it just a tiny tiny bit basically just move it enough in order to make sure that the position over here is in red meaning that we have recorded a keyframe then let's drag the timeline by a little bit let's go over here to frame 30. this one is actually going to be half a second and soon to be that because over here on the samples this is the frame rate for the animation so at 6C that means we have 60 frames this makes one second so 30 frames would be half a second you can also zoom out by scrolling over here or dragging the handles down here so let's go into 30 half a second and on this one let's move the head by a little bit something like this as you can see down there we can note that I record the new keyframe and now if we hit on the play button we can preview the animation any upon like that that does do exactly that so it starts off down and then moves up okay so that's great but we don't want to snap back so let's actually add another keyframe right at the end so let's stop playing the animation and to make sure we have a perfect Loop let's just click to select the keyframe let's press Ctrl C then let's go down into the one second Mark let's press Ctrl V and there you go there's the exact same keyframe so now if we hit on play the other go we have our nice seamless Loop so the head goes up and down and repeats forever alright awesome okay so that's great now let's also do one thing let's also record a keyframe on the body however we don't want it to move at least not in this idle animation we just want to have a static keyframe so let's select the body and let me actually move it a bit to the side just to make sure to record and now manually we can modify things over here here to modify the actual keyframe data so on this one I don't want it to move so let's put it all the way back at zero just make sure we have a nice keyframe recording now the reason why we are recording the body position even without moving it is because the wonk animation will indeed move the body but when we get back to idle we want the body to go back to this exact position so that is why we need the keyframe here okay so that's done so we can stop recording so let's click on the red button again okay great by the way one more note to make sure that the animation Loops go into the project window and over here select the animation and make sure on Loop time is enabled it should be there by default okay so the animation is set up and if we unlock in the animator it's already the default set so if we hit point we should be able to see the anal animation playing non-stop so let's hit play and if there it is the anal animation with the head moving up and down everything works perfectly alright awesome okay so next up let's make a wonk animation now for me when making an animation that is based on another one I like to actually duplicate it instead of starting from scratch so over here on the project window let's select the anal animation and let's duplicate it so Ctrl D let's learn name this one to the wonk animation and now if we select the player Visual and then we go into the animation window over here we see a nice little drop down menu for all of the animations except right now we don't see the wonk animation we only see the idle animation that is because this menu only shows animations that are attached to the animator so first we need to add the animation onto the animator component and how we do that is actually super simple let's just open up the project window and just write the wonk animation and drop it here that's it so with this we have attached a new state to the animated controller and now if once again we select the object in the hierarchy go into the animation click the drop down menu any up now we do see the wonk animation so let's click to select this one and now for this one let's make the animation so let's look in scene View and make it bounce just up and down so I'm going to enable record go back here and for the body this one already has a keyframe so let's go up here move it a little bit and then copy the keyframe put it the same one at the end something like this so there you go just goes up and down once actually input it offsets it looks a bit better so something like this by the way in a bit we're going to replace these animations with the ones that I made previously so don't worry about making the animations perfect unless you want to do that okay so there you go that's the animation although for walking should be much faster so here's a quick animated tip this top bar here lets you select all of the keyframes within a certain time so if I click the select note how it selects both those keyframes and also if you click and drag once on top of here you can select multiple keyframes so for example to select everything just click and drag to select all of them and now you see these nice little vertical bars so if you click on those and then you drag them you can basically modify the time of all the animations and everything matches up so for example let's make this one super fast let's put it just 20 frames there you go now it's a much faster walking Mission okay great let's click on the right to stop recording all right and back in the animator so over here we have both animations and now what we need is to make a transition going from idle into wonk otherwise the wonk animation will never play so how we make a transition is also super simple let's right click on the I don't say let's make a transition then now we have a nice little arrow under the mouse and now if we go into the wonk and click on it there you go we have a nice transition now we can click on the transition itself to select it and over here in the inspector we see a bunch of transition options so let's expand the settings yep there you go everything now like I said I covered all of these options in a lot of detail in my ultimate TNT of recourse so if you want to learn more go watch that here on let's just learn the basics for how to achieve our goal and making a simple player animator the important one is over here the exit time basically if this one is toggled then this transition won't be triggered automatically meaning it won't play the outline Mission and immediately transition into the walk animation so for example if we hit play and look at it quickly if there go there's the idle any of transitions into wonk and now it stays there forever okay so that's good but not exactly what we want we want the Wonka mission to only play When the character is walking and when it stops we want to go back into the idle animation now for that we need to use animator parameters so back in our animator on the top left corner we see something called layers we don't need to worry about that for now and then next week we see parameters then we can click on the plus button or to create the brand new parameter and you can see all the various types that we can create now for wonky we want something that we can set to either true or false so let's go with a nice bullion and for name let's go with is wonky again pay very close attention to the capitalization this is extremely important just like code is walking is different from is walking so make sure the capitalization is perfect okay so with that we have our nice parameter now let's click on transition going from idling to wonk and now let's untick exit time we don't want this transition to trigger automatically and as soon as we do we see this nice little warning basically it's telling us that this transition will never happen so over here we have the nice conditions if we click on the plus icon we can add some conditions and for this one we want this transition to happen from idling to walk when the parameter is walking is set to true so that's it this is our transition now let you see the reverse so let's right click on the wall make Transition go back into Idol let's click the select transition get rid of the exit time and conditions when is Walking is set to false okay so just like this our basic animation logic should be working so let's test so here we are and the character is playing the online Mission by the way you can look at the end better while the game is running so let me just drag the animator window just drag it and put it on the side of the game view so we can see both at the same time okay great and right now note how it's not updating so there's nothing moving over here on the animated component that is because like I said you must select the object so on the hierarchy make sure you select the player Visual and you have there go now you do see that updating so make sure the object is selected in the hierarchy and over here we see a nice little progress bar showing the Adeline Mission constantly playing in looping okay great another important thing is over here the parameters you can manually change the state of these while the game is running so for example if I click it's going to trigger the is walking parameter which should trigger this transition and should go into one so if I click and if there go transitions into the wonk animation and now yep it is playing The Walking animation and if I click to untick it look at over there what happens untake and there you go transitions back into idle alright awesome so as you can see we have overall logic working we have the animator with both of our states and by changing this parameter we can change which animation is playing now of course the goal is not to trigger this manually by clicking on it but rather doing it through code but at least for now we know that our animator is fully set up again if you want more detail on the animator and animation windows and everything related to animations then check out those lectures in my ultimate TNT overview course and also later on for more advanced use cases I have video on the animation rigging package this one is for more advanced use cases for making Dynamic procedural animations it's really fun so definitely check it out but only after finishing this course that one is a much more advanced duel for now let's continue here so we want to trigger our parameter but do it through code and again here we have yet another clean code question technically we could add that code directly over here on the player script we could just grab the animator component and change the parameter and in this case for this very simple game that would actually not necessarily be a very bad approach since the game is so simple with so few animations but like I said I want to teach you proper good practices so let's make it properly and actually separate the animations from the logic for then let's go into our project right click in our scripts folder create a new c-sharp script let's come with the player animator let's select the player visual game object and attach the component okay so now here first let's grab the animator now one approach is like we've seen we could just make a serialized film and and drag the reference in the editor that's one approach or alternatively since the animator is attached to the same game object as this script then we can just do a get component both approaches are really valid so here let's use get component just to see a different approach so we just have a field for our animator so animator and then we just do a private void awake and then awake lets you get component of type animator and we set our animator variable again like I mentioned very important make sure you don't mix animator and animation these are two different components we want the animator okay so with this we have a reference to our end meta component and now how we modify the parameter is actually very simple we just access the animator and then we have a bunch of set functions you can see we have one for each type so we've got a set bone set float then down here a set trigger set Vector so function to set any parameter type now we made the Boolean so let's use the set bone and this one as you can see takes the name for the animator parameter by the way strings are a horrible horrible way of identifying things but suddenly this system really does require strings to identify the parameter we want to change change if you're wondering why strings are bad for identifying things the reason is because it's very easy to make a mistake for example if you use is walking here then this won't work however if you instead right is walking then all of a sudden does not work if your right is walking like this doesn't work like this doesn't work and even though it doesn't work it will also not throw any compiler errors that is because for the compiler a string is a string it's always valid but then when the code runs this one is going to be different than our parameter which is named exam like this always remember that strings are case sensitive so that's one reason why you should never use strings to identify things it's very very easy to make tons of mistakes that are then very difficult to find out but like I said in this animator system we have to use strings there's no other way in order to minimize our usage of strings one thing we can do is for example let's define a constant up here so let's make a private make it cons for a constant meaning this will never change make enough type string and conlet is wonky again refer back into the naming wrong section for constants we always use uppercase snake case so is walking and let's set it with is wonky again make sure you don't make a mistake here make sure you type it exam like you did on the animator then down here let's use is one and now if you do make a mistake so if we accidentally use something different now we do get a compound error so at least we have a little bit of protection okay so this one takes a string for the name and then a simple Boolean for the value so this is going to be the value that we want to set to our parameter now for this one we want to set to True when the player is walking and false when it's not so for that we need to ask the player what it's doing so let's go over here into our player class and let's make a function to return just that so let's make it public because we're going to access it from another script we're going to return a boom and call it is wonky now over here we just need to return if the player is walking so let's make a local field to store that saved so over here private bone is walking again note the capitalization for films we start with camel case whereas for functions we have Pascal case so these are different okay so basically in order to Define if we are working that's very simple it's just down here we have the movement Direction so we are walking if the move direction is different from Vector 3.0 which by the way Vector 3.0 is just a shorthand for writing zero zero zero so if the movement direction is different from zero then we are indeed walking so we Define that we update that film on every update and then over here we just return it okay just like this and now back in our player animated component over here first we need a reference to the player so let's add it here let's add a serialized film of type player and we need to compound this in order to drag the reference so let's just come without this line just make sure the code compounds now here with the code compound let's write the reference of our player okay that's it and then over here for the animator set is wonking let's go into the player and let's ask is walking and of course we don't want to do this just on awake we want to do it on every single frame so let's do a private void update and on update let's do this alright that's it so this should be working let's test so here we are starting off as Idle and as I move yep there you go it is playing The Walking animation and now if I stop and if there go back into idle alright Awesome everything does work perfectly okay great we can can even look at the animator to see the state change so here with both side aside and with the objects selected in the hierarchy right now you can see he's walking his phone so it's on idle and as I move that one stays true that one goes into wonk and now if I don't let go if there and go back into falls back into idle all right awesome so with this everything is working perfectly if you're having issues make sure you pay attention to the capitalization so make sure the name you wrote here is exactly the same one that you wrote here and it's exactly the same that you're using here alright so all of our animations are working perfectly now if you want you can go ahead and make your own animations or you can use the ones that I pre-bumped so in the included project files inside the assets here we've got the animations and we've got the player with the idol and the wonk animations if we double click on this don't look at it you can see yep it looks exactly the same so there's a parameter called is walking in our transition so everything is exactly the same just over here let's select the employer Visual and on the prefab like we saw we already have the animated component we just removed that one from the prefab in order to build it on from scratch but if you want to use my image then we can just go ahead remove the animator that we added and then right click on this one on the remove component let's revert back to changes and there you go here we have our animator with the player controller so that's the one in the animations and just like this if we had on play and actually over here I found an issue although in your case there shouldn't be any issue because I've updated the assets but this is a good time to teach you about any issues with animations so if you select the animation and you select the animation and over here you might see some of them in yellow saying missing basically the way that animations work is based on the actual name of the object if it cannot find an object with the exact same name then it cannot load the same animation so my problem is that when I initially made the assets package I made this animation and the object was previously named face and then I renamed it the head so now it normally loads so if you ever have problems with loading animations just make sure the name is perfectly matched so in my case I can just click in here in order to rename this keyframe on the animation and I'm just going to use the name that I renamed it so head and just like this yep the animation does play correctly so it's just a nice quick tip if you ever have problems with and missions always remember that the stored keyframes their own stored based on name so if you rename the thing in here or over here on the game object if you're in a name you're going to have missing animations but if you make sure the names match and the animation shouldn't work perfectly so let's hit on play and if there go there's the anal animation and if I move yep there's the nice wonk animation so everything still works perfectly because it's only using the exact same parameter alright awesome so like I said if you want film free to make your own animations or use the ones that I've included for me I'm going to be using these ones so the ones that we made just for learning which I created down here so the multiplier animator and these animations I'm just going to delete these just to keep the project clean so just delete and just like that okay so now there we have our character fully working let's quickly handle our camera hello and welcome I'm your code monkey in this lecture we're going to quickly install cinemachine this is a Unity tool that makes handling cameras super easy our game isn't really going to have a moving camera so this part isn't strictly necessary but same machine is a super useful tool so I definitely want you to learn about okay so let's begin by installing the package let's go into window open up the package manager then up top let's make sure we are in the UNT registry make sure you're on the all Tab and now just scroll down until you find yep there it is send machine okay so let's go ahead and install this all right Sunstone so let's close this and now the way that send machine works is by creating what is called a send machine virtual camera so let's go up top into the game object menu then scroll down into cinemachine and over here you can see that we can create a multitude of virtual camera types now just by the names you can see how this tool is insanely useful for example making a free download camera doing that from scratch is a bit tricky but with same machine it is super easy for our case like I said we want the absolute most basic thing possible so let's just create an empty virtual camera okay that's it this creates a virtual camera over here in the hierarchy and turn this object has the send machine virtual camera component and also importantly when we added this it also added over here on the main camera if we scroll down we can see it has a sin machine brain component basically the way send machine works is it works on top of the main camera so it doesn't replace it it works on top of it and drives the main camera so now that we're using send machine if we try modifying the main camera game object so there's one over here if I try to drag the field of view nope does not work I cannot move it if I try to move the position nope can't do it it if I try to rotate it nope that does not work like I said when working with cinemachine the sin machine brain is what drives the main camera so rather than modifying the things over here on the camera itself what we need to do is change them on the virtual camera so over here we have pretty much the exact same options that we have on the main camera for example modifying the fov over here we've got the lens so we can modify the fov and if we look in the game scene as we modify this one yep it does modify the actual properties on the actual main camera now this has tons and tons of options related to everything the most important ones are all kinds of options down here for the body and the aim so this is where the camera is positioned and where it's looking at using this you can make a funnel camera in five seconds it really is insanely useful if you want to learn about Sim machine in more detail I have a dedicated video on it I go through what all of these options do then I also have another super detailed video on how to make a camera system with pan Zoom scroll in both 2D and 3D and a bunch more features again all of it using send machine but in our case we really want to keep it simple so let's just position our virtual camera on the same settings that we had previously so for first let's set the film review so for a game we want something narrow so let's go with just 20. then for the position let's put it above so zero on the X then 21.5 on the Y and minus 21.3 on the Zen then for the rotation 46 on the X and then 0 on the others okay so our camera is positioned in the exact same position and if we head on 20 yep everything still works the same the camera is going from the same point of view and the character still works everything's still exactly the same now since we're using cinemachine we can easily add some things on top of this like for example we can add some noise to our scene machine camera to make it smoothly move a little bit this one is a fun simple effect that can make our game feel a bit more Dynamic especially in games like this where we have a fixed overhead view how we do that is over here on the scene Mission virtual camera we've got a film for noise so let's click and let's select basic multi-channel purlin and then over here we've got the noise profile so we can choose one of the included ones or we can create our own profile so for example let's go with handheld normal mild and by the way you can actually modify these settings while the game is playing so here it is the game playing and you can see what this effect does it adds a nice little wobble to the camera and then over here at my student frequency so we can play around these so you can make it really intense so something like this that is way too intense so there you go quite a lot so for something more subtle maybe put 0.5 and 0.5 there you go just a slight little movement in the camera so this would help make the game a little bit more Dynamic so this could be a fun effect although actually in my case in order to make sure that the video doesn't get way too compressed I'm actually going to disable this on my end so just set the channel noise to none but you can see how easy it is to add complex camera features when using send machine and of course when using cinemachine if you want you can use it to make your game a lot more unique now for me I want to design here where the camera is fixed but let's say for example you wanted the camera to actually follow the player like I said you'll watch that dedicated video tool and learn all about cinemachine but over here very quickly let me just show you how to do that but at the same time don't bother following this part it's just to show what scene machine can do that I'm going to revert back to this state so first of all for testing one great thing about scene machine is you can have multiple virtual cameras you can have as many as you want and then the priority and the game object enabled state is what defines which camera is actually being used so for example on this second one let's make it follow the camera and put the priority on 20 so that it's above then over here for the body I'm going to select transposer let's put it with World space it requires a funnel Target so let me drag the player as the final Target and put it as slightly above and behind Okay so it's pretty similar as before then for the aim let me also drag the aim player Target and just with this it should already work so if I head on play if they're going to look at that the camera is now moving and following the player so I can move the player anywhere and yep the camera follows along so as you can see it's this simple to really make some complex camera movement doing some complex camera logic just like this would require a ton of work manually but with thin machine it is super easy then you can even play around with either priority or enable and disable and there you go see the machine even transitions between the state of only your virtual cameras so as you can see in lots and lots of things you can make with your camera very easily all thanks to cinemachine like I said in my case I just want the fix overhead camera so I'm just going to delete this secondary virtual camera and there you go just this one on top looking at the player and looking down with a low fov and Yep this is the exactly the kind of camera that I want for my game okay so that's in machine it's a really awesome tool for making camera handling much much easier so this was a quick lecture all about learning about Sin machine now let's handle the tests that was actually left and done quite a while ago let's finally learn how to refactor code and implement the new input system so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to refactor our code from the Legacy input manager onto the new input system so the simpleton character controller that we made is working perfectly fine within Legacy input manager like I said this one is excellent for making quick prototypes and demos as you can see it's super easy to use but now let's quickly refactor this code to use the new input system instead also like I said in the beginning of this course here I'm going to be focused primarily on building this game so for example for any Unity tools that I use like the new input system I'm going to cover enough to be able to use a tool and Achieve our goals in building this game of course every tool does a lot more than just what we're going to use so definitely make sure to watch the dedicated videos Link in the description for example the input system tutorial is 40 minutes long covering everything you need to know about system whereas here we're just going to learn enough to know how to use it so let's refactor this code to make it work with new input system except before we work with new input system let's just refactor this code so we can completely decoup on the input from the player class again we want to focus on writing good clean code so we should keep all of our input logic in its own class that other scripts can access remember the goal with clean code is to minimize and manage complexity so every class should do one thing and just one thing meaning that the player class should only handle the player and then the input list should only handle the input the only reason why I put this over here in the beginning is exactly to teach you about refactoring and how it's a very common thing that you should be doing all the time this is exactly how I build my own games I start by making a prototype and I write the input directly inside the player class then at some point I refactor the code to split them up so don't be afraid to refactor code it's a Perfectly Natural part of the Game Dev process and actually a very very good thing okay so let's make a script just to manage our inputs let's make a new c-sharp script call this game input let's create an empty game object give it the same name input as always keep things lean so put it on zero zero zero let's attach the script and open okay so here's our script and let's get everything related to the inputs on the player for the input we are calculating the input Vector then getting the actual inputs from the keyboard and returning the input vector so let's put this on the other script so over here let's make a new function let's make it public since we want to access it from the player we're going to return a vector 2 and let's call it get movement vector now here let's really just copy paste the exact same code that we have on player so let's copy paste all of this let's go and paste it here okay so we get the input Vector we get the inputs we normalize it and then return the input vector okay so that's it super simple also by the way here we have an interesting question which is do we normalize the input over here or do we do it over here on the player both options can be valid you can make it so that the game unplug glass returns a regular input or you can make it return a normalized vector you can use either option but whatever you do make sure you are explicit so over here I am going to normalize input inside the game input class however I'm also going to make sure to rename this function so instead of get movement Vector get movement Vector normalize that way it is 100 clear this returns a movement Vector as a normalized vector okay great so now let's use this in our player over here in our player class we need some reference to our input class now later on in this course I'm going to teach you about the Singleton pattern but for now let's just do a simple direct reference again remember don't make it public make it a serialized film private so over here let's make a serialized film private of type game input and let's call it just game input okay so we have this we're going to drag it in the editor then over here we simply grab the vector 2 for the input Vector we simply go into this one and we get the movement vector normalized and okay that's it no more errors let's just make sure to save all of our scripts and back in the editor let's go into the player and just drag the reference for the game input okay so just like this everything should still work everything should work exactly the same as previously Let's test and make sure so here we are moving and yep everything still works I can move in any direction okay so far so good and what we have done here is essentially we have refactor our code and conveniently separate the input from the player class this is an excellent thing so again don't be afraid to refactor code also what we did here of putting the code in a separate class and then doing a quick test to make sure that everything soon works the same as previously this is exactly what you should do whenever you do some kind of reorganizational refactoring in the end you want to end up with the exact same behaviors previously just with the code organized in a different way okay so now that we have this separate game input class now we can very easily refactor the Legacy input manager onto the new input system so the first thing we need is to install the package so let's open up the package manager let's make sure up here we are in the ENT registry make sure we are in all and let's scroll down to find the input system so here it is let's go ahead and install okay the package is installed and right away we see this message basically it's asking us if we want to enable the new input system now you could click on yes but let's actually go ahead and click on no we're going to enable it manually so click on no then let's close this window and now let's go up here into edit then let's go into project settings then on the left side let's go into player and now let's scroll down expand over here the other settings tab and keep scrolling down until we see yep here it is the active input Henley this is where you can select which input system you're using basically if you click yes on that window it would automatically set this option to use the new input system so it would only enable that one and can only disable the unless input manager but like I said the lace input manager is still pretty useful so normally for me I prefer to enable both of them so let's go ahead click on both and this will restart the editor so okay let's go alright the editor has restarted so now the new input system is now enabled okay so the way that this system works is by creating something called an input actions asset so on the project files let's click on the plus icon let's create something and let's find the input actions so we need to scroll down here so click on the little arrow to go down and find the input actions creates this file let's call this the player input actions okay now let's go ahead and double click on it and yep there you go out pops out the input system window basically this one is where we're going to manage all of the settings for all of our inputs also by the way and like I've mentioned if you're watching this in the future and for some reason the input system got a new update and changed this window if so make sure you check the pinned comment I'll keep it updated with any changes on anything in this course so over here we've got the action Maps then we've got the actions and then we've got properties now action maps are how you can have different maps for example one action map would be for the player whilst walking normally and you could have another one whilst driving a vehicle then for the individual actions in each action map and finally the properties for each action again if you want to learn about the entire input system itself in more detail go ahead and watch my dedicated video on it in order for this course to not be 20 hours long I'm really only going to use enough to make sure that we can achieve our goal so over here we just need one action map so let's click on the plus icon let's name this the player and now for the actions right away we have a new action so let's just rename this one let's call this action move then with the section selected over here on the Action Properties we can select the action type again in the dedicated video I cover what all of these mean for movement we do not want a button we want movement in multiple directions so let's go with value then over here for the control type for this one let's go with the vector 2 and then let's expand our action over here we can see our bindings however we don't want this default binding so let's actually delete this one instead let's click on the plus icon and over here for the type first for the keyboard and let's go with this one up down left right composite so this one adds essentially four bindings let's go ahead and name this was then for the up let's select the bindings over here on the path let's click on it then we can either find it manually over here or click on the listen and I'll press the W button yep there you go W then for down let's go ahead and listen s then for the unless listen a and for the right let's listen d okay great so with this our input as it is correctly set up one thing you must never forget is up here make sure to save the asset you can see this little asterisk here that means we have unsafe changes also alternatively there's an auto save there but for now let's just manually save the acid okay great so now let's see how to actually use this in our code there are many ways we can use the input system one way is by using the built-in player input component so for example on the player we would add the player input so you could add this one attach and input actions asset so this is our player input actions then over here we have various behaviors in order to be able to trigger our actions but in this course like I said I'm going to be using the exact same code quality that I used in my own Steam games so I will not be using this component so let's remove this instead I won't be using the native c-sharp method so what's like the player input actions and over here on the inspector we see this nice toggle to generate a c-sharp class let's go ahead enable it and for these films we can leave them all on defense that's okay let's just go ahead click on apply and now it's going to generate those scripts and compound them okay great basically what this is doing is auto generating some c-sharp code and on the employer input actions we can see over here yep we've got the generate script if you want you can even open this to see all of the source code now all this like it says here this was all auto generated so don't make any modifications here if you change anything any manual changes won't be lost when you save some changes in the input asset so if you want go ahead and read through in order to see how all this works but in order to use it sectionally super simple you don't need to worry about this script first thing we need is to construct our script class that was Auto General so let's do it over here in our game input let's make a product void awake and on awake let's construct it so let's do a new player input actions so we construct an object of this time so we have this although just like this it won't be active so we need to manually activate whatever action map we want so let's go inside and let's go inside the player so this is the action map that we created and let's call enable one okay so just like this it's really already working all we need to do is modify our code over here on the yet movement Vector so for that we're going to need to access this so let's actually make this a member variable so private let's store it up here instead of making a local variable in here okay so we have this one and then down here on the input vector let's go inside the player input actions inside the player action map and then we called it move so we've got this one and then we defined it as a vector two so over here we can call read value and this one takes in the type of the value now we Define it as a vector two so let's read it as a vector two and just like this this returns a vector 2 which is really going to be our input Vector so let's put it exactly like this and we can now get rid of the rest of it all right so that's it and just like this we should already have everything working exactly the same as previously so let's just do a debug download just to make sure so let's test so here we are and the output is zero zero now I press W there you go plus one minus one left right and all of the ones in between all right awesome so we have the new input system all of it working flawlessly also by the way over here we can normalize the input just like we were doing previously so we do it over here through code or alternatively we can also go into the player input actions and over here there's something called a processor so you can go into this action add a processor and make it normalized so these processes here can be quite useful I cover the modeling detail in the other dedicated video but over here let's stick with making it through code that works just as well okay so that's our refactoring done with that simple change we are now using the new input system so you can see how by refactoring our code to make sure to use the game input less when we change from the input manager onto the new input system when we made that change we did not have to touch a player class at all the player class just has the game input to get the movement vector and does not care what system he uses to get them so here we have a very practical very excellent example of the power of writing good clean code because we separated things correctly we managed to change something completely and not have to make any changes on any other class so now that we're using the new input system let's just quickly see one of the main benefits of this system which is easily supporting gamepads and more keys for example a lot of people like using ones but some people also like to use the arrow keys with this system that is super easy to add so let's go into the move what's another one let's add another one up down left right composite let's call it arrow keys then let's just put them so let's listen on the up Arrow then over here we've got the down arrow then we have the left arrow and finally we have the right arrow alright so we've got all the arrows and now we don't even need to touch any code at all let's just make sure to save the ascent which again in turn that is going to Auto generate the c-sharp class and go into compound okay so we don't need to touch any code at all let's just hit on play and now if I move we're using the ones Keys yep still works and if I go into the arrow keys yep also still works alright great now for another one let's make it for a Gamepad so I just connected an Xbox controller and we can see over here on the log yep the game did identify it so this is the new input system in action let's once again open up the input actions and over here on the Move let's add another one and this time let's just make it a regular binding and over here on the path once again if we want we can go down here and specifically find some joysticks so you can find any of them or once again let's just use in listen now I'm just going to move the thumbstick on the controller yep there it is I know if you wanted you could go specific and make it just work with Xbox controllers or you can just use the generic left stick this will make it work with an Xbox controller or a PlayStation or really anything so let's go with this one and that's it nothing else we need to do let's just save the asset and that's it we don't need to touch any of our code to make our game playable with a controller so let's go ahead and test so here we are and first of all if I move the keys yep song Works move the arrow keys yep both of them works and now if I use my Gamepad any up there you go everything works perfectly alright awesome so as you can see this is one of the main benefits of the new input system it makes handling different inputs really super easily as you saw we didn't have to touch our code at all we just had new bindings and just like that our game is playable with all kinds of inputs so here you can really see just how powerful new input system is okay so with this our basic character movement is working great we can walk around everything looks great now in the next lecture let's apply some collisions to our player hey again here's another quick intermission I hope you've already learned a ton from the course have you seen the benefits of writing good clean code has the course already helped you understand some more advanced concepts I really hope the answer is yes to both those remember to follow the website page as you follow along I won't be adding frequently asked questions to every lecture if you ever get stuck you can just download the project files for a lecture and compare with your own and definitely check out the related videos when I reference them this course is focused on making this game but you should definitely learn more about some of these Concepts in more detail and you can learn that in the videos that I mentioned by the way if you're watching this right now this is the secret con loud so go ahead post the time step in the comments with a nice monk Emoji I want to see how many people make it this far okay so that's it for now let's go to the next lecture hello and welcome I'm your code monkey in this lecture we're going to apply some collisions to our player movement okay so here we have our game so far we have our player walking around and everything looks pretty good however now let's create over here in the hurricane let's right click create a brand new Cube so there you go let's place it over here and push it down okay there's the cube make it just a little bit bigger so there's the cube and by default it has a boxcon leather component so it has physics and the player if I move and nope there's our issue the player is going right through the object now the player is not meant to be a ghost so let's fix this over here in our player script we are hearing the input Vector calculating the move Direction and then just moving the transform so right now we're moving it no matter what now before we do that let's first do a test to see if any object is in the way and how we're going to do that is by firing a raycast this one is a physics operation that basically fires on laser from a certain point towards a certain direction and then tells you if it hits something how we do that is let's go inside the physics class and let's call the raycast function this one as you can see has many many versions of this function with all kinds of parameters let's use this one option number seven which takes a vector 3 for the origin a direction and a max distance so first for the origin that is from where we want to fire our recast let's put the player object in so that's transform dot position then for the direction this is going to be our move Direction so let's use our move there and finally for distance let's use some kind of player size player width something like that some lights to find up here a float for the player size and put that 0.7 units let's try out with the size just like this okay so basically this returns a Boolean it's going to return true if it hits something and funks if nothing is in the way so let's just do a bone call it can move and basically we can move if this raycast doesn't hit anything so we can move if this one is false so if the raycast is false then can move is going to be true that's very simple so if we can move then we move the transform position otherwise we don't okay that's it super simple Let's test so here we are I can move around and if I go towards the cube and nope no longer works so I can no longer go inside that Cube okay great now in your case if it's not working first of all make sure that the cube make sure it is touching the floor we use the transform position as the origin which is right on the floor so if the box is raised up then you won't be able to go through so make sure the cube is touching the form also make sure the cube has a box on leather component it can be any type of calendar but you if you made a cube then it should have a box layer by default and it should have the same shape as the visual and also remember that the 2D and the 3D physics systems those are completely separate they are completely different worlds so make sure you're using 3D components and not the 2D ones so for example if I add boxing weather 2D if I add this one then it will not work so make sure you're using the 3D and not the 2D components same thing over here on the script make sure you're using physics and not physics 2D also finally if you're still having issues make sure you check the player position again the player should be on a y of zero the only thing that might have an offset is the player Vision although if you're using the same acid me then this one should also be on a y of zero so all of these on y of zero and then you can also check the four by default this one has a mesh calendar but if it is exactly on yf0 with no rotation then it shouldn't cause any issues alternatively you can also just disable or remove the mesh con leather from before since we're not going to need that so with all that yep everything works I can move the player but I cannot go through solid objects alright awesome so it is working but for this particular use case a recast isn't necessarily the best method we should use basically Rick asses like I said kind of like a super thin laser but as you can see the player visually has an actual body shape so the visual and logic are using can only in different shapes if I go ahead and push towards the box you can see it works just fine however if the player is a bit more off to the side and the center of the player right in front of it is not the box and I move and yep there you go now I am going through the box the reason is because the erase accounts being fired from the center of the player and like I said it's kind of like an infinitely thin laser so it has no shape so as long as the center of the player is not hitting the box and it can go through it whereas what we really want is for the visual and logic to have pretty much the same shape so let's not use a raycast over here on the code instead of a recast we can use a physics query with an actual shape there are all kinds of casts you can use as you can see all of them with different shapes you've got a box cast if you want to have a box a capsule if you want the capsule or a sphere cast all of these were pretty much the exact same way except instead of a raycast which fires an infinitely thin laser these are going to have an actual shape and for player controllers for the most part you really want to be using a capsule cast that's usually the generally accepted player shape although alternatively a boxcast also can work very well in our case let's just go with a simple capsule cast this one to define a capsule has a 0.1 and a 0.2 by the way if you have no idea what is a capsule then we can go over here in the hurricane let's right click create a 3D object let's make it a capsule and there you go this is the capsule it's kind of like a stretch sphere so it has around the top round bottom and then over here in the middle it's just a cylinder and over here for the raycast takes a 0.1 and a 0.2 so that is going to be the bottom of the capsule and the top of the capsule basically with those two points we can Define the height of the actual capsule okay so let's just get rid of this capsule let's just lean it and over in the code let's put those now 4.1 it is indeed going to be the transformed opposition since that is the point at the bottom and for the second point for this one it's essentially going to be the player head so we can take the transform dot position so this is the bottom and we can essentially just lift it up so let's add a vector 3 dot up and multiply by some kind of player height let's define up here a float for the player height and I tested it in the editor and the player is about T and Stone so over here let's go ahead and move it up by that much okay so next we want the radius so this is pretty much the player size that we defined previously so let's use the same thing but as always let's make sure to write good clean code since now we are referring to a radius let's actually rename this to be a bit more clear and by the way here's a quick Visual Studio tip you can right click on a symbol and then you can click on the rename option alternatively use a shortcut Ctrl R control R if you do that then now you can change the name so for example on player radius and note how it changes every single instance of that variable so this renaming feature is extremely useful always make sure to rename something if you find the name that works best Okay so let's rename this to play radius then we have Direction so that is as usual going to be our move Direction and then finally we have the move distance for that we can use the actual move distance so that is going to be the movement speed multiplied by time dot all the time so I just find here a fluid for the move distance and you should see that just move speed time dot Delta time we have the move distance and we use it both in here as well as down here okay so here we have our cancel cast the rest logic is exactly the same so if this one is false that means it didn't hit anything so if it didn't hit anything then we can move and then we move the transform okay let's test and over here now if I go towards the box and the Epson works is only the same as previously that's great and now if I go towards the end and make sure that the center is not hitting the box and I try to move forward and nope now we no longer go inside the cube so even on the edges everything still works perfectly alright awesome so it works it looks good but it also is a little bit janky for example let's stretch this cube out a little bit so let's put it just on One Direction so stretches like this let's see now if I move towards it then nope I cannot go through it so that is correct and if I move left and right yep that's also correct that works however if I now press W and D at the same time in order to move diagonally and nope right now it does not move the reason is because the diagonal Vector that one is indeed hitting the collider but usually in games when you move diagonally and you cannot move in when Direction then it tries to essentially hug the wall and move around it so if I press wnd it should essentially be moving straight to the right so let's solve that so here in our code we're making our Capstone cast okay that's great then we need to test if we cannot move so let's see if we cannot move so it can move is false if so then that means we cannot move towards this direction and if we can then essentially we basically want to split the movement Direction and just move on the X or just on the Z so first let's attempt just the X movement so attempt only X movement let's create a new vector 3. let's call it move the year X and we make a new Vector three let's take in the move there dot X then zero on all the other so we only want the test moving in the X Direction and then let's do literally the same thing so let's get our can move try to move under this direction so let's go inside a move there move there on the X so we do that capsule cast and if we can move then that means we can move only on the x-axis so can move only on the X and if so let's set the move there equals the move there X so if we can move them down here when we use the move there we're going to move only on the X and if we cannot move then that means we cannot move only on the X and if so then let's attempt only Zed movement so over here again let's do the exact same thing so let's copy this let's just change this one so instead of move to your X we've got moved here on the Zen so over here we use 0 on the X 0 and Y and axis we moved here and get the Zen then let's use this movement Direction over there and finally the same thing so if we can move then that means we can move only on the Zen and let's set the move there equals the move there Z and if not then we cannot move in any direction okay so that's it now this might seem a bit confusing but it becomes a lot more clear When You See It In Action again remember the scenario we're trying to solve which is when moving diagonally so for example when we're moving forwards into the right if we do that then let's say this one is going to hit something so we cannot move so if we are trying to move both forwards and to the right then we're going to only attempt the X movement so we're only going to try moving to the right and then we're going to see yep going to the right that does work so we can move and we're going to move just to the right all right so let's test and see if all of this is working all right so here we are and if I move straight to the wall and nope there is 11 so I cannot move anymore okay great now if I move just left and just right and it does work now if I press W and then D and if there you go now it does hug the wall and continues to move same thing if I go on the left over here if I press D no I cannot go through it now if I press D and S at the same time and there you go it hugs the wall and moves around so now our controller is much more easy much more understandable okay so this is great now this is one of those tiny things that makes your character controller feel much more responsive so that's great however we also do see one more issue right now you can see that I'm right next to the wall and if I press A and D then look at that I'm moving with this spin however now if I press wnd look at that now I'm moving diagonally and it's actually moving slower basically this is the same issue that we saw previously where we had to normalize the input so we didn't go faster in diagonals basically now we have the opposite problem since we are normalizing the vector we are cutting down on the left right vector and with that basically if we are moving diagonally then we are essentially going slower whereas if I stop moving diagonal and just move left right it moves at a different speed that solution for this is really super simple over here in our code when we are constructing the move to your X and move the ears in when we do this very simple let's just normalize it so if this one is less than one then it won't be going into one so let's normalize that one and down okay that's it let's test and now from here move forward and hug the wall on left right yep does work and if I stop moving diagonally just going left right yep all still works with the exact same speed all right awesome okay so that's really it as you can see it's super simple to add Collision detection to your movement scripts you just do a physics query to testify our character should move and just move it by the way if you want to learn more about collisions and physics queries there's a bunch of interesting videos that you can watch for example one is on various methods of finding a Target then another one is on various methods of handling projectiles and finally another one is a very quick checklist on why collisions are not working basically there's lots of really interesting things you can do with physics so make sure you understand these functions okay so now that we have all of this working let's first just clean up our scene so over here our default Cube we don't want this so let's just get rid of this and with this we are ready to build our first kitchen counter and let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to begin building one of our main game mechanics we're going to make a kitchen counter and handle the logic for the player to be able to interact with that counter okay so let's begin by making our kitchen counter and just like we did when we made the player let's first make an empty game object and place the visual inside of it so let's right click on the hierarchy and create an empty game object call this the clear counter so it's going to be clear on top so we can place and pick up objects let's make sure to reset our transform so let's put it on zero zero zero let's move it just a little bit just so it's not exactly on top of the player okay now inside let's add the visual so let's go inside the assets folder and then over here we've got the prefabs visuals and inside we've got the counters visuals and over here let's find the clear counter Vision so let's go ahead and drag it inside the game object again make sure the challenge visual is on zero zero zero the unlockable position okay great now just like we did in the online lecture where we added Collision detection that shouldn't already be working by default but in order for it to work it needs a physics line either however note how the vision over here there's no collider and inside there's no collider there's only visuals again this is the same thing that relates to separating logic and visuals basically the visual prefab this one only has visual components so only meshes animations and that sort of thing and the main Parent Game object this is the one that is going to have all of the logic components set means any kind of scripts Behavior as well as any colliders so over here on the parent game object let's add new component let's find a box Collider again make sure you add a box of leather not a boxing leather 2D and I chose a boxing Ledges because this is the shape that makes most sense for our counter and now let's scale the boxing leather again that's the boxing ladder not the transform so leave that one with a scale of one one that's good and over here on the box leather for the size let's put it up with a size that fits the visual so 1.5 1.5 1.5 and finally we just need to lift it up a bit over here on the scene view you can see those little green tiny lines these refer to the boxing leather shape so let's lift it up by a little bit in order to make it perfect let's put it up by 0.5 on the Y alright so there you go that one does have the perfect shape if we test just like this it should already be working it's okay so here's my player and if I move towards it and yep there you go it does work so it is a solid object I cannot go through it okay great let's just visually rotate the calendar so let's do that and again for rotation let's make sure we rotate the apparent game object and not the visual we want the visual to be on rotation zero zero zero okay great so on the parent game object let's just rotate it around by the way here's a quick empty tap if you want to rotate hold down control and then click to rotate and now instead of rotating on every angle it goes on a 15 angle increment so just hold down this way you can easily get it to 180 degrees so it's just for fun just make it face the player okay great so now let's interact with this counter and doing this is actually super simple we already learned how to do a raycast to handle collisions and for interactions that's exactly the same thing so let's go into our player script and we're going to do a recast to handle that but before we do let's organize our code here let's make a proper function to handle our movement so let's make it private since this is going to be in local function return void and call it handle movement and then inside let's put all of this code so let's copy all this put it in there and then on update we simply call this function okay great and now let's make another function so private void let's call it handle interactions and we just call this function on our update okay great everything is much more organized so now here let's do a raycast so once again go inside physics do a raycast for the origin let's start on transform.position for this obviously we want the move Direction so an approach would be to make this a film variable sorted up here so that way we can access it in both functions however if you remember how we handled the whole issue with the diagonals basically we're modifying the move Direction so for moving diagonally then this one modifies to only move left or right we don't want that for the interaction we want pretty much the exact same one even if it's pointing towards a solid object so let's not make the same member variable only reuse it instead let's just grab it again create it again over here so we get it and we want this one even if it's pointing towards a solid object so let's use this as our move Direction and now for the distance let's define a fixed distance so something like two units would work and also here's another very important lesson with regards to writing good clean code so you would think to write code like this so let's put the two right in here that would work everything would work perfectly but then let's say you get back to this code after one week would you remember what this 2f means the answer is probably not you would probably very easily forget exactly what this means so because of that you should never use numbers directly in the code like this instead you can either make a field appear if you want to make it customizable or much simpler is actually what we already did previously so let's define a local variable with a proper name so let's define a float and this one is going to represent our interact distance so let's call it exactly that interact with the distance and let's put 2f and over here instead of using a number let's just use that variable now if we were to get back to this code after a long time it would be extremely clear what this parameter represents the technical term for what we did here is called Magic numbers and I've also covered them in detail in another quick video but as I always remember very simply never use magic numbers okay so with this we have our recast it's pointing forwards for this distance but this is actually not very useful because the rickhouse this one only returns a bullion so all this tells us is if there's something in front or not it does not actually get as the actual object reference so for that let's use a different version of the raycast function so as you can see we've got all kinds of versions in order to get the object reference let's use this version right here this one which has an out parameter for a raycast hit note the out keyword here this is important this means that this is an output parameter whereas the other parameters those are all essentially inputs that you give to the function whereas this output this is basically a value that the function outputs so let's use this so we've got the origin we've got Direction then we've got the rake asset in order to use it we need to make sure to write the out keyword here and then also very important we need to write the type so let's call it break asset and then the name so let's call it break asset basically what we're doing here is essentially defining a variable of this type with this name we're defining it and giving it to the function immediately so we can use it afterwards if you don't include the type if you just include the name then you get an error because this name Rick has said this was never defined alternatively you can Define it before you pass it in so over here you can do recast it recast it and just like this it works because you are defining it here and using it here but in order to make the code a bit more compact you can just Define it here in the same place where you get it okay so let's use this and with this the function still returns just a Boolean so just hit something or not but then we've got the rake asset output this will be filmed with data from the Collision if we do hit something we can inspect this to see what that it contains so you can right click on top of the type and then go to definition and up here we do see the definition for the rake acid struct you can see this is a structure to get information back from a raycast you can inspect this to see all of the kinds of things that this one returns for example you have a vector 3 point for the impact point in workspace where the ray actually had a collider it can get the normal of the surface and so on so you can get all kinds of things for a use case what we want is to identify the object that we hit and for that we can use the transform so it's going to be the transform of the rigid body or the collider that was hit so let's just do a quick test if we hit something lets you unlock on that object so let's do an if so if this one is true then that means we hit something so if so let's do a debug unlock go inside the rake asset and log the transform okay so like this we should be able to see on the console if we do hit something let's also do an ounce just to be able to easily see when we hit something so on else let's just log an empty Dash and in our game in order to make sure that our Collision is working that we are correctly detecting it let's just duplicate this object but before we do let's make this a proper prefab if you have an object of a certain tab that you want to create multiple instances of it you should be using a prefab rather than just duplicate an object that way with the prefab if you make any changes to that prefab it applies to all of the copies of that prefab so let's first make this one a prefab and again since this is our first prefab let's first make a nice folder to keep things organized so folder for our prefabs and to make game module prefab is super simple you just click and drag directly from the hierarchy and drop it inside the folder there you go there's our prefront and now let's just duplicate this make sure it has a different name so it has one so that's enough with this we should be able to see it just for testing let's put it just off to the side okay so let's see so here we are in the console we see a dash so by default we are not hitting anything okay so that makes sense now if I move towards this object and if there you go it does I didn't find that object and if I stop moving it stops identifying okay great now if I move towards this one and if there we go this is the one with the name of one and this is the one with the name of none all right awesome so just like this we are correctly identifying what object is in front except we also have an issue so if I move towards the object then yep it does work but if I stop moving once I'm still facing that object right now it's returning none now the reason for that is because of the move data that we're using here if we're not moving in any direction then basically this Vector won't be zero zero zero so we're going to be firing a raycast towards no direction at all so obviously it's not going to hit anything the solution to that is super simple we just need to keep track of the last interact move Direction so let's go up here to find a film for that so let's make a private let's make a vector 3 and call it the last interact Direction and then down here when we have our handle interaction so we get the movement here okay that's great so then we just check if the move direction is different from Vector 3.0 by the way this is a constant a shorthand for zero zero zero so if it is not zero then that means we are moving in some Direction so so let's set the unless in direct direction to this move Direction and basically if it is not if move there is zero then we are not going to modify this so this one is only going to contain the unless interact Direction and then down here instead of using the move Direction Let's just use this one so that way even when we stop moving we are still going to be using the last indirect Direction okay so with this let's test so here we are and if I move towards it yep it works and if I stop moving and yep it still works alright great so we can move towards it Point towards a certain object and then yep it still works okay great now let's actually interact with this counter and to do that let's make a class for the counters itself so let's make a new script in the UC sharp script let's come with the same name so clear counter okay there's our script now very importantly for attaching the script remember that we have two instances of our prefab if you just select it in the heart key and you just drag it on there if you do that then you're not actually adding this script to the prefab itself you're only adding it to this specific instance of that prefab so if you look at this one yep it has a script but this other one which is a copy of the same prefab this one does not have it also over here on the inspector you can see the little script icon has a nice little plus that means it is something that you are adding on top of the prefab so that means this script is not present on the base prefab basically this is not what we want we don't want just this object to have this script we want all instances of this prefab to have this script so instead let's get rid of this one from here we want to modify the prefab itself so one way to do that is to select the prefab on the project window so here it is the actual prefab and now we can drag the script on there so that works or another alternative is something like the prefab in the hierarchy and on the inspector over here we see a nice button to open the prefab and if we actually go into scene view then we can see what that does so with the object selected so this is an instance of that prefab but if we click on open then essentially we are opening and we are working inside the prefab so now if we make sure to add our script and let's go back outside this prefab so on the top left corner over here we can see where we are so we were inside our scene and then we are inside the clear counter prefab so if we click on the scenes we can go back now it tells us that we made some changes to the prefab so let's save them and if we add that script and we can see both instances of the prefab they both have the same script and we can see on there on the icon that this is not an override this is an actual script at on the base prefab so whenever working with prefabs always make very sure that you are adding it on the right place if you want something on the base prefab make sure you either add it on the prefab itself or go inside the prefab by double clicking on it or select an instance in there and open to go inside the prefab so always keep in mind different switches between a prefab and an instance of a prefab okay so we have our script let's open it and over here let's just make one super simple function so let's make it public because we want to call this from our player class let's return void and just call it interact okay that's it super simple for now let's just do a debug.log and just say interact okay so that's it and now over here on the player when we have our handle interactions function so interact we do our raycast and we find out if we hit something so when we do the first thing that we should do is identify what this transform is so is this something just like a dumb Cube or is it an actual counter now when it comes to identifying things this is another place where a lot of beginner tutorials will teach you to use the unity attack system so that's over here in the editor when you select any object over here in the inspector you can see a tag so you can see untagged and you can add all kinds of tags this is something that a lot of beginner tutorials teach but Unity tags are horrible you should never never use them I covered in more detail why that is in the advanced concepts video the main reason is because of well pretty much the same thing that I mentioned a while ago when we were handling animator parameters so you were doing this and I talked about how this one takes a string and how strings are horrible way for identifying objects they are very brittle very error prone it's very easy to make mistakes and tags have the exact same problems because tags are strings so we do not want to use tags to identify objects instead over here on the player script let's use a different method for identifying objects and the best way to do that is to Simply get our counter component so we have our transform and then from inside that transform we can call the function try get component this one then takes the type of component and again note how this is an out parameter so let's put out and we want to test if this is a type clear counter so clear counter and call it clear counter and this one basically does the same thing as a recast so it returns a Boolean so either true or false so if this one is true then that means that object has that component so over here we know has clear counter by the way if you're not familiar with tryget component this is pretty much the same thing as the regular get component except it automatically handles the null check for you so if we just did this it's exactly the same thing as this so you do an if recast it what's X is a transform get component component of type clear counter naturally this one is not inside now but let's store this well your counter equals this then you do if this one is not known then we know has a clear counter so basically what we have up here is the exact same thing that we have down here so just using trigate component it's just a bit more Compact and I find much easier to read than to always get component and test if it is not null over here we just have one function with a nice out parameter and everything works perfectly so that's the try get component I much prefer that method so let's use that by the way on the trackit component over here you can see it has a type inside some angle brackets basically these are called c-sharp generics these are an extremely powerful c-sharp tool I have a dedicated video on them and I've used them in tons of videos definitely go ahead and learn about them basically this lets you write code that works with many classes not just one specific type in this case the target component can work with any type of component so it can be Unity built-in components or it can be components that you made yourself then if it finds a type it returns true so for right now it's not strictly necessary to know the specifics about how c-sharp generics work but definitely make sure you add that video to your queue and watch it afterwards c-sharp generics are an extremely useful c-sharp feature okay so we do this and basically if we are inside of here then we know this object has a clear counter and we have our clear counter reference so over here it's super simple let's just call the interact function alright so that's really it let's just get ready else we no longer want that log so we should be able to see unlock whenever we call our interact in a counter alright so here we are and if I move around okay that's good over here the console is empty all right now if I move towards the counter if there you go I'm interacting with it and if I move towards this one if there you go interacting all right great so with this we are correctly identifying the object and interacting with it now let's just do one final thing over here we are doing a recast to find the counter and right now we are doing a raycast towards any object that has any kind of physics calendar so maybe that's our counter or maybe just a random wall for example if we had an invisible wall in front of our counter then this code would not work that's because this raycast and this raycast set it only Returns the very first object that it does hit so if the counter was behind the wall then the brake acid object here would be a reference to that long object perhaps that's what you want or perhaps not in that scenario one thing you can do is instead of using recast you can use the function raycast all and difference for this one is instead of returning just a Boeing just true or false instead it returns an array of all of the objects that it hit with that raycast then you could cycle through them and identify the object so that's one approach or another option is over here on the recast if we look at these function versions We can see that some of them has what it's called a layer mask basically you can set a certain game object to a specific layer and then if you're using layer mask then you can make sure this recast will only hit objects within that layer anything not on that layer will be ignored for that recast this is super useful so let's learn how it works for layer mask we can go up here and Define a type of layer mask so let's make another serialized field private let's make it of type layer mask let's call it the counters layer mask okay so we have this and then down here when we have our recast let's use it so let's find the function that matches up these parameters with the layer mask so here it is we have the origin then we have Direction Drake acid the max distance and then finally we have our layer mask and let's use our counters layer mask okay great now back in the editor let's select our player game object and yep there we see our field of type layer mask and you can see how we can select all kinds of layers and how we set these layers to an object is let's just select our clear counter although again we want to make sure that this change applies to all encounters not just this one specific instance so let's go inside the prefab and over here we've got a Film Forum layer and you can see we've got a bunch of default layers and then we can add some more so let's add some layers and over here let's go to the first empty one and let's call it counters okay we've added the layers so let's go back select our object and now on the layer let's put it on the counters now it asks you if you want to modify the layer for all Channel objects now since we made sure to keep the Dean logic and physics components only on the parent object let's just modify this one and leave the other ones on the default so let's just modify this object only okay so with that our counter is now on the counters layer let's leave the prefab make sure to save it okay great and now if we go back into the player and over here on the counters layer mask yep we do see the counters layer so let's just click the selected by the way this drop down menu can actually select multiple so you can select all kinds of layers so this is multi-select but we only want to counter so only like this and just like this if we do test and if I move towards it and if there you go get the nice interact on both them so everything still works is only the same but now if we had another physics on leather in front of it it would still work because we're using a layer mask to only recast against counter objects alright great now I should point out another way to work with layers is with something called a bit mask that's a bit more advanced usually the layer mask is much easier to follow but if you want to learn about bitmask go ahead and watch that video and also another quick note in this game we're only going to interact with one single object type it's only going to be a counter even though we're going to have multiple types of counters but for games where you want to interact with multiple objects like for example having an interact action to talk with an NPC another one to open a door or push a button for those kinds of multiple interactions to build the system like that make sure you look into my how to interact with objects video it covers how to do all of that how to interact with all kinds of objects it's all based on c-sharp interfaces which we're actually going to use in a few lectures and also have a dedicated video on that topic so keep following this course but then make sure to watch those videos add them to your watch list and make sure you do watch them watch out how to interact video it is something that is necessary in so many games and most tutorials don't actually teach you the correct way of doing it anyway so back in our game we are correctly identifying and interacting with each counter but obviously we don't want to interact automatically just like this instead we want to press a nice button to interact so that means we're going to need to create an interact input action so let's do all of that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to create a proper interact input action and in doing so we're also going to learn about a very powerful and c-sharp feature called events okay so here we have our game so we have the player and if we move towards the counter yep we are correctly identifying it and interacting with it except of course we don't want the interaction to happen automatically it should be on a player input so let's make our interact action let's go inside our player input action so let's double click on it and let's make a brand new action so we've got to move and now we're going to have another one so let's click on the plus icon for this one let's call it interact and for this one action type we do want it to be a button okay great then on the default binding let's go into path let's listen and by default let's bind it to the E key just like so many games so let's go ahead select this one and once again let's make sure to save the asset and let the C sharp OS be generated okay and over here in our game input script in order to listen that is very simple so we go inside the player input actions then inside the player action map and then we can find the interact action and then over here we can see a whole bunch of events that we can interact with we've got these three cancel performed and started these are the three phases of every input again I cover these stages in detail in the input system video the important thing is that these are c-sharp events which I also covered in another dedicated video essentially they are a way for how you can write code to then get notified when something happens rather than running code on every single update constantly testing something for example over here on the movement movement is a pre-constant action so it does make sense to ask the input on every single update if any movement is pressed but for an action like the interact the player is only going to press that say once every five seconds so it makes no sense to constantly check for that action on every single update instead we just want to be notified when that action is triggered and that is exactly what an event does again watch the dedicated video to learn all about c-sharp events in detail they are insanely powerful and we won't be using them more and more as we go through this course for now here are the absolute Basics events have Publishers and subscribers the publisher creates and fires the event when something happens and the subscriber listens that event and gets the enlisting function called when the event is fired now on the generated c-sharp class we've got these three events the one that we want for this case is the performed event so let's go into this one and basically we want to add a listener to that event and we can subscribe to that by doing plus equals so this assigns a listener to that event and now Visual Studio has a nice shortcut so if we press on Tab if there go it automatically creates a function now if you're not using visual studio you can just manually write this function the only thing you need to make sure is that the function signature personally matches the event signature as usual we can inspect the event so we can right click on it and go to the definition and up here is the definition and you can see that this is an event of type action with a combat context action is what is called a dungit I also have a video on delegates if you want to learn more about them in detail for now we don't really need to worry about what is delegate we just need to use it so in order to subscribe to the event we need to make sure that this one returns voyne because an action returns void and needs to have a parameter of this type combat context if I erase this parameter if there go now we have an error because the function signature does not match so it always needs to match the exact same signature okay and also one more note over here when subscribing to the event make sure you only add the function name meaning you do not add parentheses we do not want to count function we just want to pass in the function itself as a reference okay so now when the player presses the interact action it's going to fire off this event which in turn will call this function so over here let's do a debug download just see what this contains for example let's print out the compact context okay so let's see so here we are and if I press on E if there you go I've got a nice event okay great so with this we know when the player presses the key now the next step is how do we get the player class how do we get this one to know when this is performed and the answer is we're going to do the exact same thing we're going to make an event over here on the game input class and the player won't listen to that which in turn the game input grabs from the input system again the home point is separating our concerns so the player does not care about the input system does not care about the interact action it only wants to know when something related to interact happens so over here let's make that nice event first of all let's make it public because we want the player to access it then we need to add the event keyword next we add the donkey type like I said you can learn more about delegates in my dedicated video you can create your own custom Delegate for your event or you can just follow the c-sharp standard and just use the standard event handler and this one exists inside system so let's make sure to go up here and add using system and this one has the event handler class this one is pretty much easy sharp standard for events as you can see it returns void it has an object for the sender and an event RX parameter like I mentioned in the events video you are not forced to use this target you can use whatever delegate you want like for example you saw that the performed uses an action delegate so you can use anything you want to choose that the event handler is the c-sharp standard so it's easier to follow unless you have a specific reason to deviate from the standard you should probably use this one so let's use this and then finally for the name usually you start the name with on and then whatever happened so in our case let's go with on interact action okay so we have defined our event and now for firing it let's go down here into when we have the interact performed and let's go into the event and for finding it it's pretty much exactly the same thing as calling a regular function so we just call it with parentheses then usually for the object sender this is a reference to whoever is sending this event so usually the this keyword and then for the event RX this is in case you want to send some arguments with the event in our case we don't really need to send any extra data for this one just firing the event is going to be enough so for that we can use the constant event RX dot empty okay so that's it with this we are firing an event except just like this we're actually going to have one potential error if we have no subscribers no listeners to this event then essentially this field won't be known so this one over here is going to trigger a non-reference exception let's do a quick test just to see this happening so here if I press on E if there go we have a null reference exception so when working with events you need to first test if there are any listeners and only then do you actually trigger the event so you do if this one is not null if it is not known that means there are some subscribers so we can fire the event so like this it won't work but there's an even more compact way to do this which is perfect for events so instead of this we've got our on interact action then we can add a question mark this is called the non-conditional operator basically the code is going to execute from left to right and then when it gets to this question mark it's going to evaluate the left side and if it is null then the execution won't stop right here on the question mark and will not throw any errors whereas if this one is not null then it continues executing to the right except with this syntax we have an error We cannot put parentheses directly after the question mark but what we can do is simply just call invoke and that does the exact same thing that console function so what we have here is exactly the same thing that we had previously so what we have over here and over here these are the exact same thing it's just this one is much nice much more Compact and especially for events this one is super useful okay so with this we are correctly firing for our event now let's actually listen to it so let's go over here into the player class and let's listen to our event let's do it on a private void start make it on start not an awake this is a very important rule which I'm actually going to cover in detail in the next lecture but for now just make sure to listen on start and not on awake so over here we access the game input then let's access the on interact action event and as usual let's listen to it so let's use press tab to listen to it so it is exactly over here that we want to run our interact code so let's go down into the handle interaction code that we had previously so this one so let's copy paste all this code put it up here so we get the interaction going to the object and Trigger the interact now obviously code duplication is a big No-No so we're only duplicating our code just for a quick test just make sure it works once again refactoring is super useful so we're going to refactor this code to get rid of code duplication in the next lecture but for now we just want to test to make sure that this does work so let's just remove the interact over here from the handle interactions so the only interact function being called is over here when we have our actual input so let's test and see if we can press to interact with the counter alright so here we are and as I move around if I approach a counter yep there you go we no longer have the automated interaction and now if I'm facing the counter and I press the enter I key if there go here we have our nice interaction all right awesome so I can approach I can interact and do whatever I want alright so here we learned about c-sharp events these are super powerful so if this is the first time you're hearing about them then you've just had an awesome new tool to your tone box definitely make sure you watch my dedicated video to learn about them in more detail events are super useful the next thing we're going to need is just a visual to highlight the current selected counter so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to add a visual to our selected counter and in doing so we're also going to learn about the very useful Singleton pattern okay so over here we already have the logic to identify the counter in front of the player and we can interact with it however once the logic works there is no visual indicator at all so let's add that now as usual the super quick and dirty way of doing it would be pretty simple over here on the player script we could just directly enable a visual mesh on the target counter so down here on the handle interaction when we have this over here we can tell the clear counter to enable some kind of visual technically that would work but that would be some pretty dirty code we would basically be making the player responsible for enabling some kind of visual which would mean that we were mixing logic with visuals again we always want to try separating the logic from the visuals as much as possible to keep our code nice and organized so instead of doing the quick and dirty route let's do it properly back in the editor let's create a brand new c-sharp script call this the selected counter visual and now let's go into the prefab again let's go inside it so let's select the clear counter on the hierarchy then on the inspector let's open up go inside the prefab and now let's select the visual inside it and let's duplicate this so you can press Ctrl D to duplicate it let's name this when it's selected and then inside there's a visual with a mesh filter and a mesh render so over here let's swap out the material so let's click on the circle icon and now included in the assets is this material counter selected so it's all the way yep up here the counter selected basically it's just a solid white color within low Alpha so on the kitchen counter inside the sunlight game object let's make sure to use this one with this we have kind of like a ghost visual so if we enable and disable this game object we can see the difference Also let's do one tiny thing which is right now we duplicated the actual visual meaning that these objects are exactly the same they have the exact same size and when that happens you might end up with some rendering bugs if two meshes are on the exact same position you might sometimes see the colors constantly flip back and forth so in order to make sure that doesn't happen let's make this one deselected a tiny tiny bit bigger so over here with the selected game object selected on the inspector over here we've got the scale and also we've got this nice little button here if it's like this then we can modify each proportion differently from one another whereas if we click now these are all linked so now I'm modifying one will modify all of them so let's put this on 1.01 meaning this one is going to be literally just one percent bigger so that's enough of a difference to make sure we don't have any rendering bugs and by default let's also start with the visual hidden so let's do that not on the parent select game object but rather on the kitchen counter inside of it let's make sure to disable this game object by the way the quick shortcut is shift alt and a you can enable or disable the object very useful so let's start with this one disabled so that it's hidden and basically the goal is that when this counter is selected we're going to enable it and show this Visual and when it's not selected we're going to disable it okay so over here on the selected let's add the script that we made so these selected comes revision all right so let's open it now here first thing we need to know is know which counter is selected meaning we need to know which counter the player is currently looking at so let's go over here onto the player script and let's basically just do some simple logic to keep track of the selected counter so over here let's make a field so a private let's make it a type clear counter and just come with the selected counter then down here we have our handle interactions logic okay so we do all of this we try to find the counter in front and if we do find it then we have it here so here on let's just check if it's different so if this clear counter if the one in front is different from the current selected then let's set the selected to this one and let's also make sure to essentially unselect so we want to make sure to set this one to know when there's nothing in front of the player so if the raycast does not hit anything then there is nothing in front of the player so let's set this like the counter back into null and also if there is something but that something does not have the clear counter script then it's also not a counter so over here let's also do an else selected counter equals no so basically if there's a counter in from the player then it's going to set it if not then it's going to be no let's just do a simple debug download to check on the selected counter okay and also just briefly now that we've made this selected counter logic actually up here when we have our interact action like we saw we were previously copying some duplicated code but now we no longer need this since we already know the selected counter so over here when we've got the interact action let's just check if we do have a selected counter so if it is not null if so then we go there and we call the interact function so that's it we no longer need all of this logic okay that's great so let's test back in the editor and let's go back into scenes let's make sure to save the prefab make sure the script was attached save it and let's hit on play and right now if I'm down here yep there you go we've got null and as I approach if there go that one is a clear counter and if I move towards this one yep it's that one okay so basically we are keeping track of the kernel selected counter now basically we just need to notify the visual whenever this one changes so when this one is pointing at that one or pointing at no or pointing at that one we need to know when that happens and for that we basically have two options now one option is pretty much what I mentioned a while ago which is over here we have the selected counter so we can run some kind of logic on the sunlight counter we can do that over here on the player then perhaps over here the counter would fire off some kind of event saying it has been selected and then the counter visual would listen to that event and update itself now that approach would be useful if we wanted to add some kind of logic on the clear counter while selected and that approach would also have the benefit where the visual encounter would only listen to events on its own counter so that's one approach pretty much a very direct approach but another one is very simple the player would simply fire off an event whenever the selected counter changes and then all of the counter visuals would listen to that event then they would identify if the event relates to that counter and if so update their state now the benefit of this approach is that the logic doesn't get bothered with any selection logic so over here the clear counter script never really knows if it's light or not and that's a good thing because it doesn't need to know although the potential con with that approach is that all of these selected countervisions are only going to listen to the same event so both approaches have pros and cons here on let's go with the second approach where all the counters listen to a player event the potential performance con doesn't really matter on a game of this scale we're only going to have about a dozen counters so even if 11 of them are just wasting on listening to the event it's really not going to matter and going in with this approach will actually help us learn about the Singleton pattern which is extremely useful so first let's go over here onto the player class and let's make the event that we're going to fire so as usual let's make it public so we can access it let's make it an event and as usual let's also use the standard event handler let's make sure to add using system so here Visual Studio adds it automatically okay then let's call this on selected counter changed also this is a great moment to learn about the event arcs this is how you can extend a c-sharp event in order to pass in some more data so how you do it by following the c-sharp standard is very simple we just create a class so over here let's make a public class then for name usually you include the name of the event with eventars at the end so in this case on selected counter changed and then event arcs then on this class we make it extend event arcs and finally inside the class we add whatever that we want like for example we want the current selected counter so let's make a public clear counter and put the selected counter okay so we have this nice event arcs with a bunch of extra data and then over here on the event handler we use the version that takes a generic and we pass in our event arcs again I covered the generics in more detail in a separate video definitely go watch that one if you haven't seen it yet c-sharp generics are one of c-sharp's most powerful features okay great so we now have our nice event now let's fire it off so let's go down here to when we're modifying the selected counter so here it is we've got all of these ones so when we modify let's fire off the event so we go into this event and as usual let's use the question mark and then call invoke then for the object sender it's going to be this so pretty much is centered and then for our custom eventarics let's construct an object of that type so construct a new object and then inside we pass in the selected counter and we set it to this selected counter now don't be confused by the fact that we're using the exact same name if you actually Mouse over the cursor Visual Studio actually helps you by telling you which object refers to this so with the cursor here note how all of these are highlighted but this one is not highlighted that's because this field this is the film inside the unselected counter change event RX whereas this one out here is the object that we're referencing in here so even though these two have the exact same name here we're accessing the film inside of that and we're assigning it to the reference that we have down here okay so that's really it we're firing off the event when the selected changes and we're passing it in and let's also make sure to do it over here so let's copy and paste some code and there you go just like this except of course we can already see a bunch of code duplication usually that means it's time to refactor so let's do that pretty quickly let's go down and make a brand new function so let's make a private Droid let's call it set selected counter and we're going to receive a clear counter for the selected counter then over here we just set this dot selected counter so we're modifying the member variable with the one that we receive on the parameter and then let's also fire off the event so let's copy paste the event just like this the exact same thing okay so that's it and now up there instead of code duplication we just do this so over here we set the clear counter just call the function pass in that one and get rid of this and on that one just pass a null just like this get rid of all this and here the same thing just pass in no alright so with this our code is much cleaner and everything still works is all the same so here we have everything done on the player side let's just get rid of unlock we know we need this so we're still handling the selected counter logic and then down here we're firing off the event now we need to do is go over here into the selected counter visual script and here what we want to do is to listen to that event in order to do that we need a reference to the player object now so far when we've been listening to events like for example any player class up here we were listening to some events on the game input so there you go the uninteract action so for the game input reference we just added as a serialized field we did this and then we drag the reference directly and technically we could do the same thing over here on the sound like the counter visual but we're going to have like a dozen counters in our map so it would be pretty tedious to drag and drop the play reference to every single one of them so instead of using a serialized field another approach is to use the Singleton pattern this one is an extremely useful programming pattern it's very useful for things where you only have one instance of something in this case we're making this game single players so we're only ever going to have a single player by the way here's one obvious quick note like I mentioned in the beginning of this course after this video there's going to be another one converting this game into multiplayer and in that case we will have multiple player instances but this is also an excellent reminder of how refactoring code is perfectly fine for right now for this game it is intended as single player so for now we're going to use the Singleton pattern then in the future when we convert this to multiplayer we won't simply refactor that logic again don't be afraid of refactoring code it's a Perfectly Natural part of programming and game development okay so let's implement the single note pattern this is actually super simple the name sounds intimidating but it really is very simple over here on the player script let's make a public field this one let's make it static if you don't know static basically it means that this film belongs to the player class itself and not to any instance of a player so for example if you had a hundred players you would have a hundred instances of moose mean you would have one for each player but there would only be a single static film because this static film belongs to the class itself and not to any instance so let's make a field of Thai player and then for the name the convention is to call it instance and the reason why I'm using Pascal case here so capitalized in the beginning the reason for that is because this is actually not going to be a film but instead it's going to be a property remember the naming rooms that we covered in the beginning of this course it's very important you follow your naming rules always be consistent so your code is easier to understand so with that said since this is the first time we're using a property let me quickly explain what it is basically it's the exact same thing as a regular variable except you can add some logic when getting and setting that field so here let me write some quick code just to show difference between a property and a regular field so for a regular field you would call this maybe instance field something like this so this is a regular field then you would have some kind of public static return the player and call it get instance field then over here you would return the instance field and then maybe another public static void set instance field where you receive a player for the instance field and you would set the player that instance film into this instance field so this is how you do this logic with fields and now with properties you would do public static Flair then call it instance then on the property itself you open up the currently brackets inside the property you put a get then you return something so for that something usually a property has a field underneath it so you'd have a private static player for the instance that's a different name from this one on the get you would return that and on the set you would set the instance equals z value if you're confused here don't worry basically I'm just repeating just so you can see difference here we have a field with a get and a set function so regular functions and up here we have a property and inside the property the property itself has a get and set functions which can also do some logic so you can do some logic in between or you can just return the underlying value so basically using your property is pretty much the exact same thing as using a separate get and set function also one more bonus thing which is that c-sharp is smart enough to automatically create the underlying film for a certain property so if you just want to do a get and a set then you don't need to Define all this you can just Define a property and then inside you can just do get and set and there you go this code here works the exact same thing as we had previously which in turn is the exact same thing as all the code we have here with the getter and a Setter function so here it is a valid functional c-sharp property now I have to say that personally I very very rarely use properties in fact the only place where I use them is over here on the Singleton pattern for everything else I normally use regular films with get and set functions personally that's just the way that I like to code but that's really just personal preference so if you don't like to use properties then go ahead and use them anyway so the reason why I like using a property specifically for the single pattern is because the implicit implementation allows you to do something really nice again remember to go on with clean code we want to minimize complexity and the best way to do that is minimize access here if we set this property and we set it as public then that means that any other class can both get and set so anyone else can have both read and write access so we have the exact same problems that I warned you about when I spoke about why you should not make everything public and of course if we make this private then at that point we kind of lose the purpose of our Singleton since no one else will be able to access this basically we want to be able to access this reference from classes outside of this one we just don't want those classes to also have right access now thankfully properties have an excellent thing which is you can Define accessors for here both the get and the set so we can make the property itself public which means by default both of these won't be public but then we can also add the accessor over here private which in turn means that the get won't be public so any other class can get this but private means that only this class can set it this way we have the exact level of accessibility that we want this is the reason why for this specific use case properties are very useful with just this one line of code we already have our instance with the perfect level of accessibility so now that we have this field to set it let's make a simple awake so let's go over here private void awake and on awake we just set instance equals this however remember that a key point of the Singleton pattern is you only have a single instance of something so in this case we should never have more than one player if we do then something went wrong so we can add a nice safety feature here let's just check if instance if it is not known meaning it has already been set to something if so then that's an error something bad happened similar to a debug.log error because this should never happen so let's say there is more than one player instance this way we have a nice safety check just in case something goes wrong alright so that's really it for the Singleton pattern we just defined a property with a public yet in a private set and on the Wake we just set the instance that's it as you can see it's super simple and now for the really useful part over here on the selected counter visual now we can access the Singleton instance in a super easy way let's make a private void start and on start we just access the player class and from the class we can access the static instance so we can access the Singleton and now we can listen to The unselected Counter event and over here by default Visual Studio gives this function the name of the event and also the property this is in the very descriptive name so I like to rename this so control RR and just rename the instance here instead of instance let's rename it to player okay great so over here we can listen to this event however here is yet another extremely important thing note how I made this on start that is very important if you do this over here on a week instead of start and over here on the player you're also setting the instance on awake if you do that basically there is a chance that this code won't run before this code and if that happens well then this one the player instance has not been set yet so this will be null and don't throw a known reference exception now whether this happens or not it's actually somewhat random it depends on the order in which Unity decides to run both these scripts if Unity decides to run the player first and this one second if that happens then there's no problem but if Unity decides to run this first and then this one then we have a problem let me do a quick test and see if in my case it triggers that error any up in my case it did trigger that error so here we have a no reference exception any app it is being fired on this line now one solution to this problem is you can tell Unity specifically which order the script should run in so you can go up here into edit then go into the project settings then on the left side you've got something called The Script execution order and basically over here you can set the order in which all of these scripts run so if you were to make the player script run before the default time that would make sure that even though both these scripts aren't awake this one would run before this one so that would fix that problem however you should really only use this approach in the last case possible where there really is no other way in this case we do have another better Wing personally I have a very simple room that I like to follow that helps solve this issue as you know Unity has both an awake and a start and all of the awakes on all the objects will all run before all these starts so the simple rule that I follow is that I use a wake for the initialization of that script and for any external reference for that I use it on start so in this case for initializing the player and setting the instance that will lead to the initialization of the player so let's do it on the Wake whereas over here on the visual since here we're going to access the player which is an external reference for this one instead of doing it on Wake let's do it on start this way we are guaranteed to make sure that this instance has been set okay so with all of that here we have our instance so that works great and we have our events so that's great then here we have our event and inside we've got our event arcs so we can go inside the event arcs object and inside we have our selected counter so we need to do is just compare which counter this Vision belongs to so let's actually make a film up here so as usual let's make a serialized film of type clear counter so we have this one and before we go into the editor just make sure it compiles and let's comment this out so now let's go back into the editor and over here let's drag the reference but again remember we're working with a prefab so let's click on open to go inside the prefab and now once inside it let's select the selected game object and just drag the clear counter reference okay great let's go back outside and save the changes all right so now here in the code it's actually very simple so we just do an if if the selected counter matches this clear counter if so then we want to show this visual if not we want to hide it so let's also add a reference for that visual so let's add another serialized field of type game object for the visual game object then back in the editor again let's go inside the prefab and on the select let's drag the channel kitchen counter so drag down that is the visual game object okay let's go back save and back in the code here let's make some simple show and hide functions so private void show and a private void hides and now on the show just going to visual game object and call set active so this enables or disables the game object so for sure let's set it to true and for hiding let's set it back into fonts okay so now it's super simple if the selected counter is this counter then let's show the visual if it is not then let's hide the visual alright that's it super simple let's test so here we are and if I approach that counter yep there you go look at that nice selected Visual and if I get into this one yep there you go I can see it all right great so here we had a really nice visual to our selected counter and more importantly we'll learn about the super useful Singleton pattern as well as learning about c-sharp properties and a very helpful room for how to avoid code timing issues so this was a really detailed really important lecture if you're feeling confused about anything go ahead watch it again or just post a question in the comments and I'll do my best to help so with all of this this is all great we have these unlike the counter and we can see which one is actually being selected then by pressing a button we can actually interact with it so I can move and interact with any of these counters but right now just interacting with them doesn't really do anything so the next thing we need is to create some proper objects for all of our ingredients so we can later pick them up and drop them on counters so let's begin doing that in the next lecture hey again quick intermission your pass C15 lecture marks so congratulations looking at my regular core stats it seems about 80 of people give up by this point so great job with sticking with it the difficulty in complexity is increasing over the lectures so I just want to check in to make sure you're understanding everything remember to post in the comments if you need extra clarification on anything and I'll do my best to answer also check the website to see what questions others have asked and of course remember this is your Learning Journey you're not competing with anyone but yourself so take your time re-watch some lectures if you need to just focus on learning okay let's go to the next lecture hello and welcome I'm your code monkey in this lecture we're going to learn how to create the kitchen objects like the various ingredients okay so far we have our player we can walk around I can approach each of these counters and I can interact with now the next one is to create objects the player can pick up and drop when interacting with a clear counter so let's begin by making the actual objects so let's create a new empty game object call this one the Tomato then again as usual let's separate the visual so in the included assets let's go inside of it then we've got the prefab visuals and we've got the kitchen objects visuals and inside we've got all of the ingredients so let's just find the Tomato Visual and drag it as a child of the tomato and again as usual make sure to put on position low composition zero zero zero and for the main one let's put it on a y of zero and just push it a little bit off to the side just so we can see okay great now this one is obviously not going to exist over here in our world instead we're going to spawn it so let's make it a prefab let's just drag it over here into our prefabs okay there it is let's delete it from our scene and actually on our prefabs let's make a nice folder to keep things nicely separated so inside the prefabs let's make a subfolder currently the kitchen objects let's put the tomato inside of it and let's also make another folder for the counters and let's put the clear counter inside of it okay so everything is nicely organized all right now that we have this let's go inside our clear counter script and over here let's add a simple reference to our prefab so let's make a type transform called the Tomato prefab by the way here you could make this prefab reference of type game object which type you use in this scenario is pretty interchangeable I talked about those differences in another video so when using prefabs using them as transforms or game objects that's pretty much personal preference and personally I just prefer to use them as transforms okay so we have this let's just make this a serialized field so we can set it in the editor and over here in the editor let's open up go inside the counter prefab and just drag the Tomato reference okay great let's go back outside save now back in the code here when the player interacts with it let's just spawn it so let's call instantiate pass in the Tomato prefab and now here is a good question which is where exactly do we spawn this we don't want to spawn on this counter's origin remember that the counter the way we set it up the origin on the actual object is over there on the bottom we don't want to spawn the tomato inside the mesh that would not make sense instead what we want is to spawn up here so the next question is okay so how do we get this point on top of the counter one approach would be to use a vector 3 directly in the code that would work but not very usable so a more designer friendly method is to Simply use an empty game object as a Target so on the counter let's first go inside our prefab and over here let's create an empty game object inside of it let's call this the counter top point let's make sure to leave this one as empty so no components just a transform and now let's just position it so let's lift it up by just about enough so let's make sure we see so there you go just about that so let's put it on position a y of 1.3 all right so this point is going to be our spawn point let's make sure to save the prefab then back in the code here let's add a reference to our point and for reference let's also use a transform reference currently the countertop point okay now let's just come this line just so the code compiles so we can drag the reference back in the editor inside the prefab let's just write the countertop Point reference okay great so now here when we call instantiate let's instantiate it inside the countertop point so this one's found the object so let's say the transform for the Tomato transform and then we go inside this one and let's just make sure we position it correctly so let's put it on in local position of vector 3.0 so this one put the object exactly on top of our countertop point also here very important don't make a mistake make sure you're modifying the low composition and not the global position okay so with this let's test over here in the editor let's go back save our prefab and hit on play so here we are let's approach a counter and interact with it and if there you go it does work the Tomato was indeed spawned all right awesome okay so with this we have pretty much our Basics working we can move up to a counter we can interact with it and spawn an object but now let's say that we want to spawn a different object so let's say now we want to spawn some genes first of all let's make the actual object so on the Tomato let's press Ctrl D to duplicate this one let's rename this to the cheese block and let's go inside of it now in here instead of the Tomato visual let's drag here it is the cheeseboard visual so let's use this one instead okay there's our nice visual let's make sure to save the prefab and go back out and now let's say that we want this one to spawn a tomato and this one on the left to spawn some cheese so let's override the prefab and over here drag the cheese block and now if we hit on play can go up to this one yep there's a tomato go this one any up there's some cheese okay so it all looks great but now let's say we want to know what object we just spawned like what object is on top of this spawn transform just like this in the code all we have is a transform reference so with this the only way to know what type we spawned would be if we had different prefabs for every single object then we could compare them one by one and see which one this matches but then let's say what if we wanted an actual string for the object well then we would need to add tons of fields for all these strings for all of the objects then what about an icon for each type once again we would need tons of fields each one for each icon but if we did it just like that with a bunch of lists then they would be separate that's not very good we should have a proper way of defining our object types and all the data related to them so this is exactly where scriptable objects come in these are objects you can create in your project funnels which are perfect for anything where you have multiple instances of a type like for example multiple weapons multiple armors multiple recipes or maybe multiple ingredients as usual I have a dedicated video on script along objects they are super useful definitely watch out for more detail over here on let's just use them so the first thing we're going to need is to actually Define the type and we do that in a c-sharp script so in our scripts folder let's create new c-sharp script call this the kitchen object so now personally so is just what I like to open to my scriptable object definitions just to make it very clear that it's a script mode object however this is not a requirement it's just a naming room that I like to follow and we're calling this kitchen object because we're going to use this to Define any kitchen object we want to interact with so that's going to be our ingredients like for example the tomato and cheese but also things like a plate and then potentially you could Implement things like a frying pan or framing signature or anything like that so it's going to represent any kind of kitchen object the player can interact with Okay so let's make the script and now let's open it and over here okay first things first is this is not a monobehavior instead let's extend scriptable object and then technically you can have functions inside a straight ball object but for now let's just get rid of this so just an empty class and over here on let's just Place whatever fields we need to store whatever that we want so like I said first we want a prefab so let's make a public transform for our prefab by the way here note how I am indeed using public this is pretty much the one exception to the room I only use scripting objects as read-only data containers I never write to them so since I found that rule I usually make the fields in the description object public that way I can access them directly without having to make a public getter but if you want to feel free to keep following the general rule of not making anything public you could definitely make this just a regular serialized film then exposed with a get function that would work personally I just find it simpler to make it public since I know that as a personal rule I will never write to a script mode object field okay so we have a transform for our prefab let's also add a Sprite for the icon Sprite and finally let's just add a simple string for the object name all right so we have our scribble object definition we have all of the fields for all of the data we want to store now how do we actually create a scribble object for that let's go up here before the class name and we're going to add the attribute so let's add the square brackets and the attribute is the create asset menu this takes some optional parameters again I cover them in detail in the dedicated script and objects video for now let's just leave all the parameters as empty just use defaults and close the attribute okay so that's it let's save this and go back into the editor and over here if we go into the project window click on the plus icon and right up top yep we do see a kitchen object so so if we selected if there you go it creates a brand new object inside of our project files let's name this one tomato and obviously let's keep our project nice and organized so we don't want this inside the scripts folder instead let's make a proper folder so create a new folder come with our scriptable objects and then inside let's put a different folder for each type so let's make another subfolder call it the kitchen object so and let's place the tomato inside of it okay now with the Tomato selected we can look in the inspector and you can see yup it does have all of the fields that we Define okay great so now we can just assign them so this is the tomatoes let's drag the Tomato prefab for the icon Sprite let's find it so there are Sprites included in the regular assets so here is the Tomato Sprite so it's inside the acids then inside textures icons and we have all the icons and finally for the readable name let's just call it tomato alright so that's it here we have a really nice scribble object containing all the data required for our tomato okay awesome with that then we can now go back into our clear counter script and here instead of having a field for our tomato prefab instead of this let's sort of reference of type kitchen object so and let's go on with kitchen object so and then when spawning let's go inside our scriptball object and just spawn the prefab reference so this is going to be the kitchen object transform then over here in the editor let's go inside the clear counter and let's assign the Tomato Kitchen object okay so let's save it and test so here we are on let's approach hit any up there you go it still spawns eat tomato okay great now let's make another type for our cheese block so let's create a brand new kitchen object so called the cheese block and again let's assign first of all the prefab there it is then for the Sprite of the cheese walk and finally this is the cheese well okay so now for example let's go into the second one and on the second counter let's override and say this one spawn a cheese block so let's test so here we are approach this one yep there's tomato this one any of there's some cheese okay great so everything is working so far however the original problem that we're trying to solve identifying the spawn prefab we still don't have a solution for that basically when we spawn a prefab we need to know from which script No Object this prefab came from so essentially what I like to do is just attach some reference to the scripting object in our prefab however again remember that scripting objects are not mono behaviors so if I select the prefab and I try dragging the description object nope it does not work so what we can do is just create a new script so let's make a brand new c-sharp script let's call it kitchen object let's attach this to both prefab so both the cheese and the block attach the same one to both of them and let's open and over here very simple let's just add a serialized film for our kitchen object so a serialized film of type kitchen object so for the kitchen object the cell then let's also make a quick function to expose it so we're going to return kitchen object as so get kitchen object so and we just return the kitchen object as well yep just like this so now here in the editor for the Tomato yep we've got the film so let's say this one is a tomato and the cheese block this one is a cheese block now here obviously we need to make very very sure to drag the correct reference to the right scriven object if you drag the wrong one like for example over here on cheese you would say this one is a tomato if you did that then obviously you would get some very weird results so make sure to check and double check that you drag the right preferences both over here on the prefabs make sure they are referencing the correct Circle object and on the script module itself make sure they are referencing the correct prefont okay so now if you go here on the clear counter we spawn our object okay great then on this object we can do get component of type kitchen object and then we can just ask it to give us the kitchen object as well so for example let's do a debug download on this one so inside you get the kitchen object to sew and then let's print out the object name all right so here we are let's interact with this one and if there you go interacted and spawn the tomato and on this one yep interacted and spawned a cheese block okay awesome we spawned a transform prefab and we identify the spawn object is indeed this type of object all right so here we'll learn about one of the most powerful ENT features scribble objects these are extremely useful for defining a type and then creating multiple instances of that type with whatever that we want so there can be some ingredients like we have here or it could be some weapons could even be some NPC data maybe some Quest data and so on it really is an insanely very useful feature definitely go ahead and watch a dedicated video on script on objects then if you want you can also watch some more videos where I've used scriven objects for example in the Minecraft crafting system using scripting objects or the hydrogenated crafting system which again also uses scribdon objects okay so this is done it's working great now let's continue to the next lecture where we're going to help the kitchen object know where it belongs and help each counter know what kitchen object is on top of it hello and welcome I'm your code monkey in this lecture we're going to create a kitchen object parent meaning that the kitchen object will know where it is and the counter will know if something is on it this is important so that later on we can pick up a kitchen object from one place and drop it in another okay so here we have our player I can move towards this counter interact with it and yep spawn a tomato then on this one's want some cheese okay great but I cannot do anything else in fact if I interact a bunch more times really all I did was just spawn a whole bunch more cheese so instead I want to be able to spawn some cheese and then pick it up so let's think about exactly what that means we want a kitchen object to essentially be placed on a specific Place based on the design that we're trying to implement we're never going to have a kitchen object just randomly thrown around the world we're not going to have tomatoes all over the floor instead the objects will always need to be placed somewhere and that somewhere can be either a counter or it can be being held by the player so essentially that means that each kitchen object is going to have some kind of parent that it's attached to we're going to make sure the counter knows if there is a kitchen object placed on top of it and we're also going to make sure the kitchen object itself knows where it is so first let's do that logic over here on the counter so on the clear counter script let's keep a field for a kitchen object so just a simple private of type kitchen object kitchen object then when the player interacts with it by the way we can get rid of these debug transforms debug logs in all you need them okay so when the plane interacts so if the kitchen object is known if so then we're going to spawn it then when we spawn it let's assign it so this one equals the kitchen object get component of type kitchen object okay so if that one is no we spawn it and we assign it and just with this we should have fixed the issue where we can spawn infinite objects so over here I can interact and now I've interact a bunch more times and now look in the hierarchy inside the clear counter and I go inside the counter top Point nope there's only one tomato okay great so with this basically we made the clear counter know if there's something on top of it now let's do the other side so let's go into the kitchen object and make sure that it knows where it is so over here on the kitchen object script let's add a simple field for a counter so private of type clear counter for the clear counter and now let's just basically make two functions one to set it and one to get it so a public void set clear counter and we're going to receive a parameter of type clear counter okay great and then we're going to have a public return a clear counter for the get clear counter and we're just going to return our clear counter and on this one just set this dark layer counter equals this layer counter all right so on this function we're assigning this field and on this function we're returning this field so now back on the counter script we get the kitchen object reference so on this one let's call set clear counter and pass it in this one and if it is not known so if there's something on top of this let's just do a debug.log let's go on to the kitchen object and get the clear counter so we should be able to click once and spawn an object and click twice and the second time we should be able to see the name of this layer counter all right so over here let's approach and click and yep it's spawn now click again and if we've got the message this one is on the planet counter okay great so far so good so the counter knows if there's a kitchen object on top of it and the kitchen object itself knows where it is now let's add some logic to be able to change a parent counter it's over here on the clear counter script we basically just need to call the set layer counter function with a different counter reference so just for testing let's add a serialized film for the second counter so clear counter for the second clear counter now we're doing this just for testing just make sure the logic Works before we come up with a more General system so just for testing let's come up with some input and again for testing using the lazy input manager to get something quickly up and running is a great thing so let's quickly get a button input on the counter so let's make a private void update and for testing we only want the testing to work on one counter so let's also add up here just a ball testing and then on update if we are testing and we have the input.getkeydown on let's say the T key so if you have that then we can run some kind of testing code so let's say for example if the kitchen object does not know so if we have something on top of this kitchen counter let's go into the kitchen object and call set counter and let's pass in the second clear counter so basically with this we should be able to interact to spawn an object and then press the T key and we should be able to see that object be set to a different parent so here in the after I'll let you set down let's say this one is our main counter so let's drag a reference to the second one the second higher counter drag it and make this one the testing script and also just to verify that it worked over here and lets you a get on the clear counter all right so let's test and see okay so here we are let's approach this one interact and there you go spawn tomato and now if I interact again yep it says the tomato is on the similar counter now if I press the testing key if there go the Tomato was moved onto the other counter okay so the parent change the logic worked however obviously we have two big issues the first one is just a visual you can see the object is still placed on top of this counter even though technically now it belongs to this one and the second issue is that this counter still thinks that it owns this kitchen object and this other counter does not know that it now owns this object so we need to sort all of that first for the visual it's actually very simple here when spawning we are spawning it inside the counter top point and then setting the alarm position to zero so whenever we move to a different second parent when we do that we can just ask that second parent to return the countertop point and move it there so for that let's make a function to return that so public we're going to return transform so get the kitchen object follow transform so it's going to be our countertop point so let's return the counter top point then let's go into the function on the kitchen object when we set the clear counter so over here on the kitchen object on this function so we set the color counter then let's modify this transform.parent go into the nuclear counter in order to get the kitchen object funnel transform and again let's make sure to set the low composition back into Vector 3.0 okay so with this when we set the clear counter to a different one it should automatically teleport to the other counter so let's test so here we are in first let's interact with this one there you go it's Pawn now if I press C testing key and if there go it does move visually okay great so far so good however the counters still have the wrong data by the way here's a quick empty tub on the inspector you already know that you can only see the public and the serialized Fields however there is actually a way to look at private fields on the inspector on the top right there's these three dots and if you click on it over here you can modify it into a debug inspector and when you go into this one Yep this one does show all the private fields so you can see for example on the clear counter so that's the right one this one over here the kitchen object is indeed assigned and we can go into the other one and we can see this one has it as null so debug inspector is really useful in these kinds of cases if you want to inspect any kind of private Fields you can go to this and see it now let's swap back into the regular inspector and let's fix that issue by notifying the counters that the object has changed so over here basically we have two options over here on the calendar counter when we modify the parent when we tell the kitchen object to go to a new parent when we do that we can make the new parent responsible to updating itself or we can just make the kitchen object itself be the one responsible for notifying the new parent both approaches can work personally I think it makes more sense for the kitchen object to handle itself so we just call this function to set the new parent and when this happens basically this kitchen object needs to tell the old parent that it is no longer there and needs to tell the new parent that it is on there so on the counter let's make some function to set and get a kitchen object so over here on the calendar counter script let's go down let's make first one to set so public void set kitchen object and receive a kitchen object and just do this dot kitchen object equals this kitchen object okay great then let's make a getter so public return a kitchen object get the kitchen object and just return this kitchen object okay then let's also make one just to clear it so probably avoid clear kitchen object and this one just sets the kitchen object into null and finally just a nice sample function to test if this counter has anything on top so just a public Bowl has kitchen object and over here we just return if the kitchen object is not known okay so some four very simple functions now if we go into our kitchen of the script over here when we tell it to change the parent let's first go into the current parent and clear it so let's first of all do a quick test for null so if this documentary counter which is the current parent so if this one is not null then we go into the current parent so the clear counter and we tell it to clear the kitchen object and then we go into the new parent and we tell new parent to set the kitchen object and the kitchen object is this one now here will be very very important don't make the mistake of clearing the wrong counter keep in mind that over here this documentary counter this refers to the previous player counter whereas the one in the parameter this is the one this is the new one so make sure you clear the kitchen object from the previous clear counter before you assign it and then you set it on the new clear counter so be very very careful here make sure you don't make mistakes between the quote unquote old color counter and the nuclear counter okay so that's it basically we have this function to set the nuclear counter so set the new parent we clear the kitchen object from the old player counter we added a new one and we update the visual now we can also add some nice safety checks here just to make sure we never make a mistake the kitchen object should never be set to a parent that is already holding something so before we set the kitchen object before we do that let's make sure that one is empty so over here just do an if if the clear counter so that's a new one if this one has a kitchen object then it already has something on there this should never ever happen so let's see what debug.log error and say counter already has a kitchen object we're going to eventually add tests to make sure that this never ever happens but having the air here won't be helpful just in case we missed something so far as the kitchen object we're going to fire an error but this should never happen so we just set the error update to visual and so on okay so finally let's just go over here into the clear counter script and down here we have the interact action so we instantiate the kitchen object we're currently repositioning it and then we're setting this field assigning it to this one now we made the kitchen object responsible for doing all that for modifying the position and for setting the field so we don't need to do this instead we really just need to go and get the component of that and just pass in set for your counter and pass in as this one so we no longer need all this now our code is much more simple also importantly up here we were previously setting the color counter and then doing a debug.log but when we set it a new one that is actually going to clear this field so if we leave this then this is going to throw a null reference exception so let's just get rid of the slog here we normally need it okay so let's test and see if all of our logic is working all right so here we are let's go to this one interactive spawn it okay great and once again we can look in the debug inspector so let's put it on debug look at this layer counter so that's the right one and yep there you go it does have the kitchen object and if I'm looking the other one Yep this one has no okay great now if I press the testing key yep visually it did change and if you look at the counter so if you look at the old ones that's the right one this one is at no okay that's great correct and if you look at the new one Yep this one does have the reference all right awesome so now that we are correctly changing the kitchen object parent for example we can now interact again with this one and yep it does spawn a brand new one and of course if we try moving it to the other one then we should have our error as intended this one is currently already occupied the kitchen object so we should not be able to drop something on there but if I press the testing key if there go nicer okay so that's great we're basically going to fix this error later on when we check to make sure the object can only be spawned when it can be spawned but for now all of our basic logic is working we can spawn an object and change a parent alright so with that here we have added a really important feature to our game that is the ability to know where a kitchen object is now the next step is to enable the player to be able to pick it up and drop it somewhere so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to enable the player to pick up a kitchen object and in doing so we're going to learn about another awesome c-sharp feature called interfaces okay so right now with our game I can already move the player I can approach a counter and try to spawn an object and with the testing key I can move it to a different parent so all of that logic is working now let's make it work actually with the player let's say when we interact once we want to spawn it and if there's an object already on top of it and I interact again then I want to give it to the player okay so here on the clear counter script we've got our interact function in order to make that work we need to have a reference to the player so I just passed it in over here as an argument for our interaction so just pass in the player reference now over here let's do the logic that I send so if the kitchen object is known so if there's nothing here then let's spawn it okay great but if there is something then let's give the object to the player so how we change the object parent is just like what we did up here so let's go into that one set the clear counter and pass in deploy a reference except of course this obviously does not work the parameter on this function is supposed to be of clear counter it does not work with the type of player recently on the logic that we built for setting the parent and change the parent this whole thing only works with the counter so it does not work with any other type so we cannot set the player as a parent now to solve this problem is exactly where c-sharp interfaces come in again I have a video going through them in detail definitely watch it and learn everything about interfaces basically what it is is a contract you define some functions in the interface and then any type can Implement that interface and you can write some code that works with the interface which in turn means that the code won't work with any type as long as it implements that interface so in this specific example we're going to make an interface to represent a kitchen object parent then we're going to implement that interface on both the counter and the player and that way both of them won't be able to be parents of a kitchen object so let's do exactly that now the first thing we do to Define an interface is Let's Make a c-sharp script so let's right click create new c-sharp script and now the standard is to start interface names with the capital I and then the name so in this case let's name it I kitchen object parents and let's open it okay so now to make an interface first of all this does not extend mono Behavior nope and secondly this is not a class instead this is an interface now like I said an interface is essentially a contract where each class that implements that interface must follow that contract what that really means is you can define a bunch of functions here by the way quick note you can also define properties but not Fields I cover all of that in the dedicated interface video but for now here we just want some functions like for example let's just put all of the parent functions that we made previously on the counter so over here on the corner counter a while ago we made all these functions that we needed to make it work as a kitchen object parent so we got the transform set kitchen object get it clear it then has it so let's just copy all this and paste it over here on the interface however one important note is on the interfaces you don't actually include any function implementation the implementation is up to the class that implements this interface although again I should also point out another quick note as of c-sharp 7 you can include a default implementation but that's for more advanced use cases so for here let's just use the basic and not apply any default implementation right here so we just defined the function and put a semicolon so just like this just the function definition with the exact signature so just like this okay so now that we have defined our interface and all the functions that we want to have with this now let's go on to the counter script so over here on the clear counter script over here let's implement the interface and the way we do that is pretty much exactly the same as by extending a class so over here we are already extending Model Behavior then let's set a comment and let's say we are also implementing the ikitchen object parent interface so right now you might be wondering so this is pretty much the same thing as extending a base class and kind of except for one huge difference when extending a base class you can only have a single Base Class like for example over here we have monobehavior you cannot extend multiple base classes there can only be one however when it comes to interfaces you can Implement as many interfaces as you want so over here we have defined our interface and right now we don't even have any errors that's because we already implemented pretty much all the exact functions also Visual Studio has a really nice software icon over here on the left side it is basically saying that this function this implementation is based on the interface but let's see what happens if I decide to comment out these functions so if I comment out all of this and if there we go over here we have an error it is telling us that this class does not implement the members for the interface like I said an interface is like a contract so you must write all of the functions included in the interface so we must Implement these so let's get rid of the comments okay with this our interface is perfectly working over here on the calendar counter now let's just go into the kitchen object over here on this script for now we're still working with the type clear counter so let's just refactor this to instead of working with a clear counter let's make it work with a kitchen object parent so let's just change this from type that to Kitchen object parent let's also rename this so let's use Ctrl RR for the kitchen object parent then we've got a function to return the kitchen object okay that's good for this one instead of setting your counter and let's once again rename this to set kitchen object parent and inside again we receive of type I kitchen object parent then let's also rename the parameter to Kitchen object parents okay so all the names here I have changed okay they're all correct we set it we assign it over here instead of counter let's say kitchen object parent already has that so just like this and finally down here let's return I kitchen object parent and rename this to get kitchen object parent and we return that all right so we have changed everything I can even do control F to search for counter and nope there's no instance of any counter so all this code has now been Rewritten to work with a kitchen object parent something like this everything should be working it's only the same as previously we have no errors here and over here on the clear counter we just have this error on the player and let's fix this in a little bit for now let's just comment it let's just test it out to see if everything still works exactly the same as previously also one final thing since we modified the interact function over here on the player class when we have the interact we just need to pass in this reference okay so let's test all right so here we are let's approach this one interact yep there it is now let me press the testing key and if there go it does move okay so everything is still working exactly the same as previously once again another successful refactoring now here comes the magical moment so right now again everything is still working exactly the same as previously so we can only have counters as parents but now let's go over here onto the player script and over here let's also implement the same interface so let's implement the eye kitchen object parent and again as usual we have our error so we need to implement this also again Visual Studio is very helpful so we can click on the light bulb icon and let's say implement the interface and if we scroll down here it will automatically create all these functions so let's just actually Implement them so for implementing this interface the code is really going to be exactly the same so let's go up here into the clear counter let's go down find all of these functions let's copy them and on the player let's paste them down here at the bottom so we just need to also pick up the kitchen object as well as a reference to the top point so over here on the clear counter and let's just grab both those so let's just grab the kitchen object so go into the player and over here let's add a film for the kitchen object and finally let's add another one for the counter top point so over here a serialized film for the counter top point except obviously the player is not a counter so this name makes no sense on the player so let's just quickly rename this and set call it kitchen object home point okay here we have our new name we've got the kitchen object and down here all of our functions they're all working no errors all right now let's just assign this in the editor so over here let's just go into our player there's a player script and requires a reference to the kitchen object home point so for that let's do it just like we did for the Counterpoint so inside the player let's create an empty game object currently the kitchen object hold points and I always just position it just slightly in front of the player so let's put it on a x of 0 on a y of 1.3 and on a set of one so there you go just ahead that's where the player is going to be holding the objects finally over here on the player let's just drag that reference okay so far so good also one note here like I mentioned previously in order to implement the interface it requires you to write the function code basically what this means is that different objects can implement the exact same interface whilst having different implementations so for example over here on the player when setting the kitchen object perhaps over here you could play some kind of item grab animation or maybe when clearing a kitchen object you could do some kind of logging the only thing that needs to match perfectly is just the function signature and the function signature that means the return type as well as the name and any parameters the implementation itself that is up to the class that wants to implement that interface but in this case we wanted to behave pretty much exam the same way so like this it should be working so we can now go back here onto the clear counter script and okay we have our interaction all right great so if there's nothing we're going to spawn it and if there is something on top of it we want to give it to the player so now let's go into the kitchen object and call the function set kitchen object parent and pass in the play reference and that's it no errors because again this takes a parameter of type kitchen object parent and the player does implement that interface so that's all valid now with this let's says and see if our code is working alright so here we are and let's interact with this counter and there you go the object has been spawned and now if I interact again if they're going to look that the player picked up the object and since our logic is using a transform home Point as the parent the player is automatically carrying this tomato alright awesome so this is really great now over here on the counter we no longer need all of this testing code we now have the ability to actually pick up objects from the player so let's get rid of all this so we don't need this testing code don't need a reference to the second color counter or the testing okay great so here you can see the power of interfaces by just implementing the interface we can now place an item anywhere we want and importantly on any type we want so the counter can hold a kitchen object the player can also hold it we could make a dog character and make it hold a kitchen object we could make a vehicle hold it or anything again interfaces are really really awesome one of the best C sharp features definitely go ahead pause this course for now and watch a dedicated video on them you should be very very familiar with interfaces they will help you in making all kinds of systems and games if you want to see a clear example of the power of interface you can go watch my how to interact with NPC's video that video takes advantage of interface to make sure that the player can interact with any kind of object alright so thanks to interface we can now change the parent of the kitchen object and put it on either a counter or the player now in the next lecture let's make a proper different counter type hello and welcome I'm your code monkey in this lecture we're going to create a different counter type from where we can grab some ingredients okay so far here we have our character working and we have an empty counter and by interacting with it we can spawn an object but obviously that's not the behavior we want in the final game we want different counter types that do different things the cleaner counter should only be used as a place for putting down and grabbing objects it should not spawn anything so let's build a new counter type and for that one option is to make a brand new prefab and build it on from scratch another option is we can duplicate this counter and change a bunch of things or there's a third option that was added in recent TNT versions you can now have what is called prefab variants meaning that we can have a base counter and then we can make variants for all the types so let's do exactly that to learn about prefab variants now first let's duplicate this one just so we don't lose any changes let's rename this prefab to underscore base counter no I'd like to add an underscore just so that the bass prefab is on top since this window is sorted alphabetically now let's go inside the base counter let's go into the scene view so here it is and recently over here we only want to have all of the things that all of the counters will have so all the counters will have a boxing ladder only the same shape so that's good they will also all have a counter top point however for the visual different counters will have different Visions so let's get rid of this same thing for the selected let's get rid of this and on the actual object different encounters will have different Scripts so let's also get rid of this okay so that's it this is the base counter it only has all the things that every single encounter will have so let's go ahead save this prefab go back outside and now let's right click on the base counter and go into create and over here let's scroll down and find the prefab variant now let's name this the clear counter except obviously we can't have two different names so let's put this one into backup we're going to get rid of this one in a little bit so on the very end let's name it clear counter let's open up this variant and now here let's add everything just like we had on the own player counter so since it's going to be exactly let's actually go inside the backup one so here let's just copy the visual in the selected so let's copy this go back inside the clear counter variant and over here only let's paste it so Ctrl V see if there it is he selected any visual finally just scripts over here let's add the clear counter script and now let's just write the references so the kitchen object we're actually going to remove this in a little bit but for now let's assign it the counter top Point Let's drag it and on the selected we also need to drag the kitchen counter reference okay so here is our clear counter as a variant of the base counter so let's go ahead save this and go back outside and now we can finally delete the owned prefab of the clear counter so let's go ahead and delete this and of course over here on the scene we've got some broken prefabs so let's get rid of both these and let's drop the clear counter variant so let's drop it place it over here so let's put it on X of 0 y of zero and Z of 3.5 okay so that's the clear counter and let's just put another one to the side and perfectly on the side so on an X of minus 1.5 okay now we can begin making our container counter so for that once again let's make a variant so right click on the base counter and go into create and let's create a prefab variant call this the container counter and let's go inside of it now here first thing we need is the visual so let's go inside our assets we've got the prefab visuals inside we have the counters visuals and let's find the container counter so let's drag it inside again for the low composition make sure it's on zero zero zero okay great then we need to make the selected so let's duplicate this visual let's rename this to selecton let's go inside on all of these then let's modify the material for the selected material so let's click on the circle icon and select the counter select material okay we've got our nice little ghost icon and just like we did previously let's start with these disabled so all these game options disabled so they are hidden and on the selected let's make sure the scale is one percent bigger so 1.01 also in the selected this one does not need an animator so let's get rid of this now let's add the selected counter visual and obviously for this one we're eventually going to need to refactor it to support multiple visual objects as you can see this selected has multiple but for now just make sure that it works let's just drag just the first one okay great so our container counter has been built the only thing that we need is the main logic script so let's do that let's go into our scripts folder let's create a brand new c-sharp script name it the container counter and let's select the main game object attach a script and let's open it alright so now here let's first think what we want for this counter we want the player to interact with it and when it does we want to spawn an ingredient and give it to the player so that means that we're going to want pretty much the exact same behavior that we made over here on the clear counter so when the player interacts we spawn and we give it to the player so let's actually copy all of this code let's go into the Container counter and over here let's face this we just need to grab the references to the kitchen object and the kitchen object as so so again just like we did on the container counter let's copy all these references and over here let's paste all of them and of course here we have an error in order for this work this needs to implement our interface and let's do exactly that so let's implement the eye kitchen object parent and back in the clear counter let's just copy the exact same code so all of these functions let's just copy them and on the container counter just paste them okay great so we don't have any more errors here so everything should work we should be able to interact with the container counter and we should be able to see an object being spawned on top of it over here in the editor let's just make sure to assign it so let's assign a default kitchen object so let's say tomato and the counter top Point Let's drag the reference and okay everything else should be working so over here on the selected we've got the visual game object on the container counter we've got this okay great so let's go outside into scene View and over here let's just Place some container counters so let's drag one up there let's place it on an X of 1.5 on a y of 0 and Z of 3.5 and let's also Place another one down here so let's rotate it to face it upwards okay so on position zero zero minus five okay great and let's make them spawn different things so on this one up here let's actually spawn a cheese block and on this one down here let's one tomato so let's also modify the icon here so from cheese block and let's put a tomato icon so here it is okay we've got two counters and two clear counters so let's test so here we are and if I approach a container counter and I press the interact button and nope nothing happened we cannot interact with that at all even the selection visual even that one is broken so as I approach note the visual is not showing up now the reason for this is actually pretty obvious if we go over here on the player script down here when we're handling our interactions so let's go into the handle interactions function over here we are doing a recast and we are trying to get component of type clear counter so basically we're not doing anything if that object has a container counter instead of a clear counter so again we have a similar issue to the one that we had in the object parent logic basically we have two types a clear counter and a container counter and we want the player to be able to interact with both them so as a solution for this exact same problem we could also Implement an interface just like we did that would work that would enable the player to interact with multiple counters but in this case since the counters are all very similar very related objects they're all going to be kitchen counters as opposed to object parents where the player and encounter are completely different in this case since they are all very similar a better approach is actually to use inheritance now here I should point out that inheritance is one of those things that is simultaneously very powerful but also very dangerous usually beginners get really excited when they first hear about inheritance but after gaining some experience they start to see the massive downsides one funny joke about it is let's say you want to write some code that all it needs is a Banana class but because of messy inheritance you end up with a monkey and the entire jungle behind it basically the banana extends a monkey which extends a tree which extends the jungle and so on so you just want a small thing but because of a complex inheritance you end up picking up a huge object some of that to say inheritance is something you must use very very carefully it's a powerful tool definitely but you need to make sure that you absolutely use it in the right approach for the problem you're trying to solve now in this case like I said since all of the counters are going to be very closely related in this case it does make sense and of course in the future if that does change we can always refactor if you're a beginner definitely go ahead and research a bit more on c-sharp inheritance the pros and cons I don't have any dedicated video on that topic myself but if you search I'm sure you'll find tons of content again it's a very powerful but also very dangerous tool so definitely use it wisely over here let's make sure we rise so let's use it first thing we need to do is to find the base counter class so let's create a new c-sharp script let's call it the base counter so over here on the script let's get rid of the functions we don't want any default functions and let's also make sure that we do extend mono Behavior we do want that we still want to use this as a component so let's leave the script just like this let's save it then let's go over here into the clear counter script and on this one instead of extending Model Behavior let's extend the base counter okay that's it that's the only change and now let's go into the Container counter and over here same thing let's extend the base counter inside of Model Behavior so now both these counters extend the exact same base counter script so now if we go into the player score so here we are on the player script and on the handle interactions function over here instead of trying to get a component of type player counter let's try to get component of type base counter so let's also rename the so control RR to rename rename this to base counter and of course we need to rename all these references that expect a clear counter instead of the base counter so over here for the selected counter let's modify the type to base counter then also up here when we've got the event RX let's modify the type okay so over here we have the interactor let's leave this for a bit let's go down and let's fix this issue so let's go down into that function to set the selected counter instead of this time let's receive a base counter okay so all of these errors have been solved there's only one left and it's this one the interact we see this error because obviously the base less does not have any kind of interact method so let's add that now for adding methods to a base layer it's sectionally very simple it's really just like any other method so first the accessor for the interact we want the player to be able to access it so let's make it public and also since we're talking about inheritance I should probably mention the other accessor now you already know about public and you also already know about private but there's another one you might not know which is called protected basically this one means that whatever function we defined with this successor it is going to be accessible to this class and any class that extends it so for example if we had a function that was protected the clear counter could count this function because it does extend this Base Class however the player would not be able to call this because it is protected now in our case for the interact action we do want to play the comet so let's make it public just like we had previously then another keyword for every function that we want the chunk lesses to be able to implement in their own way we can Define it as virtual and finally the function signature as normal so for the interact we made a return void call it interact and we received a player argument okay so that's it that's our basic signature for the implementation let's leave it empty over here on the base counter so by default it's not going to do anything in the game design that we're building we're never actually going to end up with anything like this so if you want for safety we can just add a debug.log error to say just base counter.interact because this should never be triggered also I shouldn't point out for a more advanced method instead of making it virtual you could make it abstract and basically what that does is that forces all the classes to implement their own implementation so you would make this extract and just put it just like this as if this were an interface but in doing so you would also need to define a base counter as abstract and so on so basically this is a more advanced method so don't worry about it for now let's keep it a bit more simple so let's make it just virtual void interact okay great so we have this let's save this and now if we go on the calendar counter over here on the interact notice how we have a green screen line basically this is a warning it's telling us that we are hiding the base function now in reality we don't want to hide it instead we want to override it so before the void before the return type we just have the keyword override and Yep this will now override the base function so when the player interacts with an object of type based counter and that object is actually a clear counter when the player calls the interact function instead of running this code it's actually going to run this code now let's do the same thing on the container counter so over here let's also add the keyword override to override the base function okay great so we have no errors here and on the player we also don't have any more errors since that one does now implement the interact function so with this one it says and everything should still be working so over here let's approach the entire counter and let's interact with it any up it does work it spawn some cheese and down here yep it's on the tomato and then if we go on to the empty counter and interact and yep it still works okay so here we added the ability to interact with two different counter types alright great now knows how the selected logic isn't really working well you can see the container counters they are both selected even though the player is not looking at them and actually if I approach it then it actually becomes deselected basically the reason for that is because these selected square of that one is still referencing the clear counter inside of the base counter so right now it's only being selected when the sunlight the counter is known so that is why as I approach it actually hides itself so let's fix this let's go inside the container counter prefab and inside we've got the selected any up over there we have a reference to that so let's open up this script and over here all we need to do is just modify this time so let's make it a type base counter and let's rename this to base counter okay that's the only change we need and by the way since we're here let's also fix the other issue the issue we had where we need to support more than one visual game object so instead of having a field of type just game object let's receive a game object ring so let's modify this to game object array and then down here on the show hide is actually very simple so let's just do a four inch game object for the visual game object in the visual game object ring we go inside set it to true and on this one we set it to false okay that's it super simple now let's just update the prefabs so first over here on the container counter let's write the container counter reference as the base counter okay great and for divisions let's just drag all of them so let's write the counters only drag it on top then the counter hole drag it on top then the single door drag it and the black drag it and also by the way over here on this counter this one actually has an objects right this is the actual Sprite in there but for the selected we really don't want that so if I enable this game object here we've got the object Sprite let's actually delete this we don't need the actual icon Sprite to be highlighted so let's leave it just like this so we only have these four objects and all four of them are on the list okay that's right so all the references in here they're all working perfectly so let's go back outside let's save the prefab let's go inside the empty clear counter and on this one same thing on the selected let's Drag The Insider reference and for the base counter let's also drag that reference okay so let's go outside save it and let's test and now let's see if the selected Works once I approach this one yep it works yep it works and on this one yep it works and down here yep it works all right awesome so we can interact and we can highlight our selection okay everything is working great so now that all the code is working we can inspect the code to see if we can refactor anything we can see for example if there's any kind of common logic that all of the counters share that we should probably write in the base counter and you can see right away that both the clear counter and the container counter both of them implement the kitchen object parent interface that behavior is something that all of the encounters will share so instead of defining it on each counter itself let's actually do it on the base class instead so let's get rid of the interface implementation here and also on the container counter let's get rid of that and set on base counter and let's Implement that one so I catch an object parent and for the functions let's do the same thing so let's cut this one from here and let's paste it on the base counter it's okay now we need these two points so let's go ahead copy all of this let's go into the base counter and paste in except for the base one doesn't need a kitchen object so so just the counter top point and the kitchen object okay so there are no errors on this one let's go into the container let's get rid of the kitchen object and the counter top Point okay great now we see an error but before we worry about that let's actually go into the clear counter and let's do the same thing so let's get rid of this get rid of this and down here get rid of all these functions okay so now the counter scripts are much much more simple all of the common code is now written directly on the base counter now for solving this the container counter needs to know if there's a kitchen object on top of it so now here we have an interesting question with two possible approaches basically we need access to this object so one approach would be to make this protected like I said protected means that any classes that extend this base counter class any of those classes can then modify that field something like this yep there is no more errors that's one approach and the other approach is to instead keep this one as private and whenever we want to interact with it we simply interact through these functions both approaches can work and when in doubt as usual you should probably go with the more limited option so let's leave it as private and work with these functions and send over here on the container counter instead of testing if the kitchen object is no let's just test has kitchen object so if it does not have a kitchen object then we're going to spawn it and for spawning over here we could grab the actual transform funnel so this one up here we could call this function to get it or since that is actually going to be handled automatically when we call this function to set the parent then let's actually not use this at all so we just spawn it and set the kitchen object parent okay great so now let's just look at the clear counter for this one like I said it's not really meant to spawn anything solid sectionally remove all of this code this one is only going to serve to pick up and drop items we're going to handle that in the next lecture but for now let's just go back into the Container counter and let's do the proper logic that I mentioned in the beginning basically on this one we want to spawn the object and we want to immediately give it to the player so when we call set kitchen object parent instead of passing in this let's pass in the player reference and that's really it for the container counter this is all we're going to do so the player interacts and it spawns an object and gives it to the player okay so that's it with this as you can see the code for all of our counters is much much more simplified so basically it only handles the logic related to that specific counter everything else is on the base counter so let's test this so here we are and if I approach the counter interact any of their go spawn some cheese and gave it to the player okay great now just for fun when I made these assets I shall include a nice animation so if you go inside the container counter over here on the visual note how this already has an animator with an animator control and attached to it you can double click to open it up and over here you can see it's very simple basically just has two animations one is the container close and one is container opening and closing these transitions are basically triggered by this parameter this is a trigger parameter so when triggers goes into the open close and when this one ends goes back into closed so let's just quickly add these nice animations however again as usual let's make sure to write some good clean code so let's not add the visual over here on the logic script instead let's make a proper new script over here let's create a new c-sharp script call this the container counter visual okay now we want to attach this only to the visual game object so only this one let's attach okay and over here the first thing we need is to get the animator so let's sort of film for the animator and since it's on the exact same object we can just make an awake and get component of type animator and we just assigned this field okay so with this we have the animator now we just need to know when we should play the animation so let's go over here on the container counter script and basically let's make an event that we're going to fire when the player grabs an object so let's make a public event of time let's stick with the standard so let's use event handler inside using system okay let's name this on player grabbed object then down here when the player interacts and gets an object let's fire off this event so invoke let's invoke with this and event RX dot empty okay so we are firing off this event and over here on the visual first we need the film for the container counter so let's set it up here let's add a serialized field of tribe container counter okay we have this build now let's listen to the event but again we're accessing an external reference so let's make sure to do it on start and not on awake so let's go into this one and listen to the on player grabbed object event okay so here we have the event and it's over here that we want to access the animator and call set trigger in order to play the animation again when working with animator parameters suddenly we do need to use strings there's no way around that but at least we can make it a bit more clean by defining a constant so here a private con string call it open close and let's make sure to use the exact same parameter name so open close and then down here on the set trigger let's call this trigger okay so that said some very simple visual logic and now over here inside the prefab all we need is to drag the container counter reference so let's drag it also make sure that it has the animator and the animated controller so with that everything should already be set up so let's go back into the scenes save the changes and let's hit on play so here we are and if I go towards the tomato and interact any of that I go it plays a nice little animation alright awesome okay so here we created a brand new counter type and we refactored our interact code to be able to interact with any counter type the player can interact with the container counter to pick up an object now the next obvious thing that we need is to enable the player to drop an object on the clear counter so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to enable the player to pick up and drop objects okay so we already have the player working I can approach this container counter interact with it and yep the player picks up something now that's left is being able to put our shade clear counter and being able to drop this object so let's do that let's go over here on the clear counter script and when we interact with it we're going to do a bit of logic first let's just check if this counter is empty meaning if there is no kitchen object on it so let's test if has kitchen object or if not so let's say if we don't have a kitchen object then there is no kitchen object here and if not then there is a kitchen object here okay these are the two valid options so if there is nothing here then let's check the player itself so we go into the player and we can ask the same question so it has kitchen object so if the player is carrying something so over here the player is carrying something if so then basically we just want to drop that object from the player and drop it in here so that's very simple we just go into the player we get the kitchen object that the player is holding and we just modify the kitchen object parent onto this object all right so that's it just with this it should already be working let's do a quick test before we handle the rest of the interactions okay so here moving the player and if I just interact with a clear counter and nope nothing happens okay great since the player is not carrying anything nope nothing happens all right great now let's pick up something from the container counter okay so now the player is carrying a tomato approaching clear counter press a button and yep there you go there it is alright Awesome everything worked now this is an excellent point to know just how easy this was to implement and the reason why it was so easy was because we focus hard on running some good clean code for how the object and the appearance system works because we took some time to think about that it was now very easy to implement this brand new action so this is a very very clear example of the power of writing good clean code okay so with that now let's implement the rest so over here there's no kitchen object here and the player is carrying something but if not we've got the L so player has nothing so if the player doesn't have anything so let's not do anything so player not carrying anything so those are all the possible States up there and then down here if there is a kitchen object on this layer counter if so then let's check if the player has a kitchen object so in this deep layer is carrying something and if not then the player is not carrying anything so basically if there is a kitchen object here and the player is carrying something if so then we don't want to do anything since we can't give the player two items however if there is a kitchen object here and the player is not carrying anything then we want to give it to the player so let's just get the kitchen object the one that is on this clear counter and let's do the exact same thing so set the parent and set the parent onto the player okay so that's it as you can see some very simple logic so let's test okay here we are and if we interact nope nothing happens okay great now pick up a tomato go there drop it yep there it is now if I interact again yeah there you go I picked it up again so I can go somewhere pick it up drop it and everything works perfectly all right awesome now the last thing that we need to fix is the container counter right now it's giving out an object every time even if the player has something so if I pick up the other works now if I pick up again there you go we've got our nice helpful error this should never happen so let's add some nice checks so over here on the container counter okay we have our interaction and before we spawn anything let's just see if the player can pick up something so once again very simple let's just go into the player and we check does the player have a kitchen object if so we're not going to give it anything but if the pointer does not have a kitchen object then yep the player picks it up and we give it the object okay so that's it it's this simple Let's test so here we are let's pick up some cheese okay great now pick up another one and nope nothing happens okay great we're already carrying something so we cannot drop anything now drop it in there now pick up a tomato any of it works I can pick it up drop it and yep everything works okay great let you see one more thing over here the container counter is spawning the object and the object is the one that we assigned so over here in scene view we've got the container counter this one is placed on the scene and we made an override to spawn a cheese block technically we could keep doing this pretty much just duplicate objects modify the Sprite modify over here the kitchen object that would work but another better approach would be to Simply make some prefab variants and yep that does work you can make a variant of a variant so let's do examine that over here on the container counter let's right click going to create and let's create another prefab variant and let's say container counter this one will be the Tomato now let's go inside the prefab and over here make sure it has the kitchen object for the Tomato okay great and over there on the Sprite so let's find the object Sprite and choose the Tomato Sprite so there you go this one okay let's exit and Save all right now once again let's right click on the container and let's make it another one this is going to be the one for the cheese block so let's go inside of it and over here modify it for the cheese block and inside the actual visual let's modify the Sprite and sectionally down so the cheese block okay great let's go back outside and since we're here doing this let's make all of the other grab my objects from the containers so let's first make the kitchen object a so so let's go over here we can right click go into create create new kitchen object so let's make one for the brand then let's see if we get this one we're going to have a cabbage and finally we're going to have the meat Patty uncooked all right so now let's make sure to assign all the data for all these script along objects first we need to make the actual kitchen object so let's duplicate tomato name this one bread let's go inside of it and first for the kitchen object the song Let's make sure to drag the correct one okay there's the bread and for the visual this one is not a tomato so let's go inside our visual acids inside the prefab visuals let's pick up the bread visual okay there it is that's all we need so let's go outside save the changes and then select the bread scripting object drag the prefab reference okay for the Sprite this is the bread and finally just call it bread okay let's do the same thing for the other one so next up for the Cabbage let's do the Cabbage drag the Cabbage script object let's go inside and modify the visual so the Cabbage visual okay that's it then on the Cabbage scorpion object drag the reference for the prefab let's assign the Sprite and finally give it a name cabbage and finally the meat Patty and cooked so let's do that one so let's duplicate it name it meet Patty uncooked let's go inside modify the kitchen object so for this one and for the visual let's select here it is the meat Patty uncooked okay let's go back outside and on the escort mode object let's just drag the prefab assign the Sprites so this one is the uncooked so it's this one and finally meet Patty uncooked okay great so we added all of these squared more objects we also have the pre-files with the visuals and the electric scripts now let's just make the container counter so once again let's create another variant so prefab variant this one is for let's say for the brand then let's make all the other ones already so let's go make another prefab variant this one is going to be for the meat Patty uncooked and finally another variant also here make sure you're creating a variant of the container counter don't make an accident of creating a variant of something else let's make another variant one final one and this one is going to be for the cabbage okay we have all the variants now let's just sign them so let's go inside the bread and over there modify the description object for the brand and for the icon modify for the bread icon okay let's go to the Cabbage save the changes modify that one for the cabbage go into the icon and modify the icon and finally the meat Patty uncooked let's go ahead modify this one for that one and the icon put it on that one all right everything is working now let's just place them over here in our scene so let's get rid of the ones that we made some overrides so let's get rid of that container counter and set for that one let's drag the cheese block put it right in there let's put it on X 1.5 y of 0 Z of 3.5 okay then down here for this one let's put the Cabbage next to it let's rotate it to face upwards so like that let's put it on next of minus 1.5 y of 0 and -5 on the Zen then for tomato let's get rid of this one and use the proper tomato one so let's rotate it put it on an X of 0 y 0 and -5 okay next we want some bread so let's put the bread up here on the left side let's put it on X of minus three zero on the Y and 3.5 on the Zen and finally the meat Patty and Coke let's put it over here a bit more on the side let's put it over here on X of 7.50 and 3.5 alright so we have positioned all of them let's just make some more clear counters so we can actually place the objects so let's put this one over here on minus 4.5 this one over there let's also put some counters let's say one on the right side and a bunch more down here let's rotate them upwards let's put this one on 1.5 minus 5. and one more over here on the side okay great so we have all of our container counters as well as a bunch of clear counters so let's test and make sure that everything works okay so here we are let's go down pick up a tomato yep there's tomato now a cabbage yep there's a cabbage now some bread there's some bread and some cheese there's some cheese and some meat and yep there's some meat all right Awesome everything works so with this over here we added the ability to pick up and drop objects on an empty container and spawn them from all kinds of container counters now in the next lecture let's build the counter we can interact with in a very interesting way hello and welcome I'm your code monkey in this lecture we're going to create a cutting counter so this is going to be a counter where we can place an object like for example tomato and after doing a secondary interaction we can slice it however before we do that let's just fix one slightly annoying issue so right now the player is walking around okay that's great I can approach a counter and interact with it that's great however if I approach account from the sign look how the player is pointing towards the right and if I press the double key I can indeed select it but the player does not rotate to face the counter so that's just a minor visual issue but still I'd like to fix it so let's do that very quickly basically the issue is over here on our player script so we scroll down and find our handle movement function okay so here we were doing a bunch of Capstone cans in order to fix the problem with the diagonal movement so you try to move in One Direction if not try to move in just one of those and if we can move then we assign a move Direction and then move it basically the problem that we have here is that if I press W to face towards the counter then over here when we do this logic so it's going to first attempt the X movement only and the x is going to be zero so the move there X is going to be zero zero zero so it won't actually move anywhere which means it won't be able to move so this one becomes true which then sets the move direction to zero zero zero which then down here when we have our rotation it's not actually going to rotate to anything so we want the player to still not go through any objects but we only want to modify the move there over here if we actually move in any of these directions so the solution is actually super simple it's over here for the can move we can move if there's nothing on there and if the move direction.x is not zero so that's really it if we are attempting to move in the X at all and if there is nothing on there then we can move which means we then assign the move direction if not then we don't touch this and same thing down here so we can move if there's nothing on it and if the move there dot Zed is not zero so that's it just this one simple change and now the player should be able to rotate so here we are and if I look over there and the player is currently unlocking to the left and if I press W to point towards the container counter and if there you go the player does rotate a little bit so that feels a bit more natural all right so that's just a tiny visual thing that I wanted to fix okay so let's keep going now let's handle the actual cutting counter so first of all as usual let's make a counter variant so let's right click on the base counter create a new prefab variant call it the cutting counter let's go inside of it and over here first thing we need is the visual so let's pick up from the assets The Cutting countervision so here it is then we need the selected so let's duplicate this one let's rename this one to seal lectin and on the animator let's get rid of it and instead at the component the selected counter visual okay great now let's write divisions for the visual game object array and by the way here's a quick tip on the right side on the inspector you can see this nice little lock icon so if you click on it then that means this inspector will not change as you select other objects so I can click on and select something different and this one does not change it is still showing the selected object now this is this one when you want for example to drag multiple things so you can unlock the inspector then the hierarchy you can use shift click to select multiple objects and then just drag them all directly inside the array that's it just a nice quick tip so everything is done let's unlock it there it is okay so that said let's just assign the selected material so the counter select material let's make it just one percent bigger so let's select them all 1.01 okay and let's start with all of them disabled okay so the basic setup is done now let's make our script to run this so let's go down let's create a brand new c-sharp script for The Cutting counter let's select the apparent game object and attach a cutting counter and let's open now here as usual instead of all this let's start off by extending the base counter okay once again thanks to how we set things up using such clean code this is pretty much all we need to make a counter with this the counter already works as a counter then next thing we need is to customize any logic specific to this counter by just overriding the interact function so that's it now over here we can put whatever logic we want just for the cutting counter and for this one for star is actually going to be just like the empty counter meaning we're going to be able to drop objects on this so let's just go directly into the clear counter so here it is and let's just copy all of this code go into the cutting counter in Payson okay so the exact same logic so checks if there is a kitchen object or not checks if the employer's carrying something or not and picks up or drops in with this let's do a quick test just to make sure this one is working exactly like the clear counter so over here let's just make sure to drag in less references so on The Cutting counter let's make sure to drag the countertop point so drag that reference and then on the selected Drag The Cutting counter reference okay everything is good let's exit this prefab make sure to save all the changes and over here in the scene view let's Place one of our cutting counter so let's Basin right in there let's put it on X of 4.5 0 and 3.5 okay so let's test all right so here we are now if I approach and I interact nope nothing happens okay great pick up some cheese and drop it on there any of there it is I can pick it up I can pick up some bread drop it and yep everything works okay so far so good now the next goal is to use the knife and actually slice the object that is on there and for that the first thing that we need is we're going to need a different input right now we only have the movement and the interaction so let's add another alt interaction for that let's go into our input action so let's open it up let's make another action so create a new action call it interact alternate and for The Binding let's put it on another key so let's listen and I think on F makes sense so let's go ahead select this one then as usual let's make sure to save the asset which in turn is going to generate C sharp plus and compound the code okay great now we can go here into our game input class and let's do the exact same thing with it for the interact action so first of all let's listen to it so let's go inside the player input actions inside the player action map so this one is the interact alternate and let's listen to the performed event okay and when we have that let's fire off an event pretty much the same thing so interact alternate action and down here let's just fire off this event so let's invoke using this and even RX dot empty okay so we have the input for the interact alternate now let's go on the player to listen the same way we're listening to the regular interact action so over here on the player script let's see how we're doing things so we go into game input and listen to that so it's the same thing game input and on interact alternate action let's listen to this one and when this one happens lets you pretty much exactly the same thing except we're just going to call a different function so instead of interacting let's call interact Alternate which in turn obviously means we need to Define this function so let's go into our base counter so here we are on the base counter we've got the interact and let's make another one exactly the same just different name interact alternate okay that's it and now we are only going to implement this in the ones that need implementation so for example on The Cutting counter over here let's write down so public override and let's override the interact alternate and now here let's check check if there's something placed on here so if there's a kitchen object placed on this counter if so then let's basically cut it and for cutting it the simplest way is really to destroy whatever object is on there and just spawn the slice object so let's handle destroying a kitchen object for handling that let's go over here on the kitchen object script and let's make a simple function for this object to destroy itself so let's go up here make it public return void and for name I like to use the name destroy itself to make it destroy this object and really all we need to do is just destroy and call destroy on this game object however before we do let's make sure to clear the parent so let's go into the kitchen object parent clear it and then destroy the game object okay that's great it's really this simple and then on the cutting counter let's get the kitchen object that is on here and tell it to destroy itself okay so let's raise the object and after we do let's just spawn the slices object so for now just keep things simple let's make a direct reference up here let's make a serialized film let's make it a type kitchen object so and for the cut kitchen object the cell okay so we have this then here in the editor and let's make sure to drag the reference so let's go inside the cutting counter and let's open up the prefab and inside let's assign this one that means we need to create the object so let's actually do that first so let's create a brand new kitchen object to sell let's come out for the tomato slices then if we do this we need to create the prefab so let's once again do the same thing tomato slices make the prefab let's go inside this prefab let's modify the visual so use the tomato slices visual okay and drag the reference for the other kitchen object for the tomato slices okay so the visual prefab is good and let's just go into the kitchen object let's just make sure to drag the prefab reference then let's assign the tomato slices icon and just come with tomato slices okay so we have the kitchen object so now we can go into the kitchen counting counter and over here let's open up and set this one to the tomato slices okay so we have all the references let's go back outside save it and back over here in our code so we have this now we just need to spawn this object so we're really just going to spawn it pretty much exactly like we did over here on the container so we just go into the description object spawn the prefab and set the appearance so let's do exactly that over here we destroy the object then we instantiate the cut kitchen object and instead of getting into the player let's put it on this okay so that's it we should be able to place a tomato directly on top of the cutting counter and it should be able to transform from a tomato into a tomato slices okay so here we are let me pick up a tomato go up there drop it and okay that works now if I press the onton track key press it and if there go it did work the Tomato was destroyed and the tomato slices were spawn and I can pick them up place them anywhere and yep everything works alright awesome so with this the basics are fully working let's just briefly clean up this code we already saw a little bit of code duplication so the cutting counter is going to spawn an object and the container counter is also spawning an object so we're copy pasting these two lines of code in multiple places so instead of doing that let's put it in just one place and actually a good place to put this is on the kitchen object list itself so it makes sense that this one is responsible for spawning more objects so let's put it over here however let us not make it a regular function instead let us make it a static function again just like we saw for The Singletons by making it static it means that the function is going to belong to the class itself as opposed to any instance so let's go all the way down to the bottom of the file personally I like to put settings at the end and over here let's make public make it static we're going to return a kitchen object and let's call it just spawn kitchen object and for our parameters let's receive the kitchen object that so and let's also receive the kitchen object parent okay so that's it and we're going to do the exact same thing so let's go into the cutting counter and copy the code that we're using and over here just paste it in there so we go inside here spawn the prefab and set it on this parent and finally let's return it so let's return the kitchen object over here let's pick it up so the kitchen object we get it and then we do kitchen object set the parent and finally we return the kitchen object all right so that's it here we have a super simple function that we can call very easily it won't automatically spawn an object and set to parents so now let's just call this from somewhere so over here on the cutting counter instead of doing all this let's just go into the kitchen object again remember let's go through the class name itself and not any instance and over here let's call the function pass in the cut kitchen object the cell and for the parent it's going to be this all right so that is now much much simpler and let's do the same thing over here on the container counter so if the player is not carrying anything let's give the player this object and give it to the player just like this as usual when we do some kind of refactoring let's do a quick test make sure everything still works exactly the same okay so here we are and if I go to the counter and pick it up yep it does work to spawn the object now I can drop it in there I can cut it and yep there you go everything does work all right so far so good so with all this basically we have created a brand new counter where we can cut objects however right now there's obviously one huge layering funnel if I now pick up a cabbage and I drop it on the cutting counter and I interact with it that cabbage has suddenly magically turned into tomato slices now that is obviously not intended so for that let's define a proper cutting recipe and let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to create another scriptable object type this one is going to be for handling our cutting recipes so here's our game I can pick up a tomato drop it on the cutting counter cut it there you go slice Tomatoes however if I could pick up a cabbage go there cut it and there you go cabbage turns into tomatoes so we have an obvious issue The Cutting object is currently hard-coded instead of being based on the object we put on top of it so to solve that let's make another scribble object type like I mentioned scribble objects are excellent for storing and organizing data so it's perfect for this use case basically we want a script mode object to hold a reference to the regular object and the cut object so we can then identify the input in order to spawn the output okay so let's build that let's create a brand new c-sharp script call it the cutting recipe so and let's open it okay so now here on let's do exactly that so something extremely simple so instead of modern behavior this one is a script mode object let's add the create asset menu and finally for the fields let's do just an input and output so we've got of type kitchen object so let's go for the input and another one for the output okay so that's really it super simple now here in the editor before we create and let's keep things organized so let's make another folder let's make it for the cutting recipe so and inside let's frequently create a new cutting recipe let's call it tomato two tomato slices and over here let's select the reference so the input is going to be our tomato and the output the tomato slices okay so this is how we're going to handle things so let's go ahead and make actually the final kitchen object that sews so let's make yet another one a kitchen object to sell let's make it for the Cabbage slices and then let's have another one for the cheese slices okay so now let's make these so as usual let's if we get tomato make the cheese slices and another one for the Cabbage slices let's go inside of it and first of all drag the kitchen object as so so this one is the Cabbage slices and let's go modify the visual so instead of this one the Cabbage slices okay so we have this let's save the prefab go outside then the other one we made the cheese slices so let's swap this out let's find the cheese slices and modify the kitchen object as well okay so finally just assign the references so on the cheese slices drag the cheese slices prefab let's assign the icon and call it cheese slices okay so finally on the Cabbage slices so these are the Cabbage slices let's pick up the icon and let's drag the prefab reference okay so far so good we have created our new icons and over here let's just make all of the other cutting recipes so we've got two more so one is going to be the cheese block onto cheese slices and the other one is going to be cabbage onto cabbage slices so we need is just to drag drop the scriptable objects so for this one cabbage let's drop the cabbage on the input cabbage slices on the output for cheese mug that's the cheese Wok on the input and the cheese slices on the output okay great all of our data is now stored in some really nice script mode objects so now let's go here into our cutting counter instead of having a hard-coded kitchen object let's receive a field of type cutting rest BSO except we're going to have multiple so let's actually make an array of this call it the cutting recipe so array now for the interaction this is picking up and dropping things so let's leave that the same for now and over here on the alternate basically we need to find out which recipe we should apply to this so how I didn't find that is pretty simple so we've got the kitchen object that is placed on this object and we've got a list of cutting recipes which in turn has the input so we just need to cycle through all the recipes in order to find the one where the input matches okay so let's go down here make a function to do just that let's make it private we're going to return a kitchen object as so let's come with get output for input so we give it a certain input and Returns the one that matches that one so it turns a kitchen object as so for the input kitchen object as well here on let's cycle so do a for each cutting recipe so in the cutting recipe so right so let's cycle through all these and just check if the cutting recipe so if this one dot input matches the input that we received if so then this is the one we want so let's return the cutting recipe so.output and to make sure that the function Works down here let's return no okay so that's it we give it an input and we get back the output so now here we just need to make sure to do it before we destroy the current kitchen object so let's store a kitchen object as so for the output kitchen object SL and we just get the output from the input and for the input pass in the get kitchen object so that's the one inside of this cutting counter and let's get the kitchen object this out so that gives us the output and then we just spawn that output okay so that's it let's test finally back in the scene let's just go inside the prefab and over here on cutting counter we need to make sure to add all the recipes so let's add so the cabbage then a second one for cheese Mock and finally for the Tomato okay so there are of our recipes let's go outside save the changes and let's test okay so over here let's pick up a tomato go up there slice it there you go got some tomato slices now pick up some cheese go here slice it and there you go got some cheese slices and finally the Cabbage go up there slice it and there you go some cabbage slices all right awesome so everything is working perfectly however now let's say that I want to pick up some bread and bread should not really be able to be cut so if I go ahead and I cut it and there you go there's our air we have no recipe that takes bread as an input So that obviously leads to a known reference exception now here we have two options for solving this problem one option is simply over here when we do the interact alternate we get the output for the input and if this one returns null then we just don't cut it so we don't destroy it and we don't spawn it or alternatively we can actually add some Foundation over here when dropping objects so we can make sure that we only drop valid cutable objects now both approaches are valid and actually we do need to implement both them we'll see why in a bit so let's do both starting off with the validating the drop so first we check if there is no kitchen object on this cutting counter then we check if the player is carrying something and then we drop it from the player on this so over here let's just check if there's any recipe that has whatever the player has as an input so let's go down here make a function to do that private let's return a bone and call it has recipe with input and we're going to receive a kitchen object episode for the input kitchen object lesson and over here lets you pretty much literally the same logic so we have this and if we find a match then let's return true so there is a recipe with that input if not return false so now up here when the player is carrying something let's check if has recipe with input and give it the player get the kitchen object the player is holding and get the kitchen object as so so if there's any recipe that takes whatever the player is carrying as an input if so then we drop it okay so like this let's test and see if we can drop the bread okay so let's pick up some bread go ahead drop it and nope does not work pick up some cheese and yep that one does work however now we actually also need the other validation that I mentioned the reason is because if we place a valid option like for example the cheese there so that works and I can cut it and yep that does work however Now the recipe the cheese moth became cheese slices and now cheese slice is no longer an input to any cutting recipe so now if I try cutting again I've got another no reference exception so we need to validate putting objects on top of it and also actually cutting them Technologic is also pretty simple so let's go down to the interact alternate so we just check if there's a kitchen object on The Cutting counter and has recipe input and let's get this kitchen object get kitchen object as so just like this so we're only going to cut if there is a kitchen object here and it can be cut okay so let's test so first of all the other one let's pick up bread and nope cannot travel okay great now pick up some cheese and I can drop now interact cut now cut again and yep there you go no more errors all right awesome okay so here we have everything working perfectly I can pick up a cabbage go up there cut it into slices I can slice some cheese and I can even slice some Tomatoes everything works perfectly now the one thing missing from our design is we don't actually want this action to be instant we don't want to just press a button everything slices instantly instead we want to have the player press the button a few times in order to actually cut so let's do all that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to add the mechanic for the player to be able to cut multiple times in order to actually cut an object okay so we have our cutting counter I can drop a tomato and press button there you go it cuts it straight away now we want the exact same logic but we want it to take a few Cuts before the cut object is spawned so let's start off by going here onto the cutting counter and basically let's keep track of some kind of progress basically the way we do that is pretty arbitrary it's up to you to decide for example you could use a normalized float however for cutting since this is going to be a discrete action let's actually count the numbers with an end so let's store a private end just call it cutting progress okay so now let's begin by actually initializing this progress so when the player drops something on there let's set this one to zero and then down here when we have the interact alternate we do our logic and when we do let's just increase this by one and now we need to know if the object has been cut so we need somewhere to Define some kind of maximum and for that we can actually do it directly on the recipe so so inside the cutting rest PSO over here we've got the input we've got the output and let's also Define an end for The Cutting progress Max okay that's it and back here in the editor let's go into the Tomato to tomato slices let's say this one takes just three Cuts then for the cheese let's also take three cuts and for the Cabbage let's say it's a bit thicker so let's say it takes five cuts okay so back in the cutting counter here down here we are adding to our cutting progress so then we just need the recipe so in order to grab the maximum so on sectionally go down here and actually make a different function so this one just returns a Boolean this one a kitchen object or so let's make another one this one is going to return a cutting recipe so so get the cutting recipe so with input and we're going to receive as usual the kitchen objects so for the input I'm really going to do the exact same thing that we did up here next time instead of returning the output let's return the recipe itself okay so now that we have this more logical one we can actually get rid of all this copy paste code so over here we just get the cutting recipe so and we just get it and pass in the input so we have this one over here if this one is not no then we're going to return this on the output and if not we're just going to return null okay so we're doing the exact same logic just a bit similar okay and up here pretty much the same thing so has recipe with input let's get the cutting recipe a cell and basically just return if this one is not known okay so we have our three nice sample functions so let's just use this one to get the cutting rest BSO so let's actually copy this and go up here so we do the cutting progress then let's pick it up the one for this input so the input is going to be this one the object currently on the cutting counter and over here we already know that there's going to be a recipe with this input since we've gone through this if so then we can just check if the cutting progress is bigger or equal to The Cutting recipe so and let's grab the maximum if so then yep we do spawn it okay so that's it some very simple logic Let's test so here we are let's pick up a tomato go up there and okay now I'm going to press enter direct okay press once and yep okay so far so good nothing now two times and Alpha press a third time boom any up there you go got the nice slices now for cheese same thing one two three yep it works and finally for the Cambridge this one should be five so one two three four and five any up there you go everything does work perfectly all right awesome so with this we now have progress in our cutting logic although of course just like this it's not very good for the player the player has no way of knowing what exactly is going on so we need some kind of visual feedback so for that let's add a really nice visual progress bar and for doing this we're also going to learn about a really awesome Unity feature these are World canvases so before we make the world canvas on The Cutting counter let's actually set something up over here on the scene itself let's first create a regular canvas we're only going to use this in a couple of lectures but let's first do that one just for now so let's go on the plus button go into UI and let's create a brand new canvas okay so there you go that creates a canvas and an event system like I said we're only going to worry about this in a little bit but for now let's just leave those as is and also since we're here creating some objects let's also take some time to organize our hurricane Unity suddenly doesn't really have any folder objects so you can't organize the hierarchy in any folders however you can use empty game objects essentially as folders so let's make a brand new empty game object let's call it counters and now very importantly for empty folder objects make sure you put them on zero zero zero so nothing breaks so make sure you put it on there before you drag the counters and now let's just drag on the counters inside so all the clear counters put them outside this one also drag it inside and all of these counters put them all inside so there you go now hierarchy is quite a bit more clean okay so now let's make the cutting progress so let's click on the cutting counter and let's go inside our prefab so let's go inside of it now over here let's right click on the hierarchy and we're going to create a UI let's create another canvas now for this one let's give it a name let's name it the progress bar UI and for this one over here on the inspector for the settings instead of being screen space overlay let's make this one a world space canvas basically screen space means that it would occupy the entire screen whereas World space means that this exists in the world in whatever position it is so let's make it World space and over here the fields actually unlock so let's put the positions on zero and for the width and height let's also put it on zero so basically the canvas is going to be exactly over here by the way the shortcut that I just used was the F in order to focus on the object so this useful if you're zoomed out or zoomed in way too much okay so we have this and we want the bar to be a little bit above so let's actually lift it up on the Y by a little bit so over here let's put it on y of 2.5 okay now I said the going with this is to make a progress bar so inside the progress bar UI let's create a new UI image let's name this one our bar let's put it with a width of one and a height maybe of 0.2 so there you go just a really thin bar and for the color you can play round tinted with any color you want now for progress I think maybe a blue or a yellow something like that makes sense so let's go with the yellow kind of like this okay so there's our really nice progress bar and for this let's actually use one really nice trick for making a super easy progress bar the image component has a really easy way of making a slider image however it only actually works if you assign an image over here so let's assign one in order to be able to see those options and for that in the project files there's a texture white one by one this is literally just a one by one white pixel so here it is just a one by one image if only white and as soon as we assign it we do see over here the image type so we see a bunch more options and the one that we want is to set the Sprite as filled this one lets you do some really cool really easy effects for example you can make it radial and look at what happens in there as I modify over here on the film Mount so as I go down look at that it's radiantly filling so for some kind of circular progress bar this would be excellent but in our case what we really want is just a horizontal bar so we're here for the film method instead of Radion let's go with horizontal and if there you go now by playing around this we have a really nice progress bar then if you want you can modify on left to right right and left but yep like this it looks great now in order to modify this visual really only we're going to need is modify over here the film Mount this one is a normalized value so between 0 and 1 so 0 is commonly empty one is commonly full however one issue with this is when the bar is empty then we can pretty much not see so we can see the actual size of the bar we can see what size it should be so with this it's pretty difficult to see how far along we are but something that is pretty simple we can really just add some kind of background so let's duplicate the bar let's name this one the background for this one for the image type we don't want anything so let's leave it on SIMPLE and for the color let's put it on kind of a dark gray okay great and now here's one very very important thing is over here on the hierarchy let's click and drag and place it above the bar the reason why that is super important is because the Sorting order and how it works in unity basically when it comes to UI elements inside a canvas the Sorting order is based on The Horde in the hierarchy basically it renders from top to bottom so the bar on top the background this is going to render first and then the one below it the bar is going to render afterwards which means it's going to render on top so for the background we want to be behind so place it above on the hierarchy and that way it renders the background and then renders the bar also by the way for 2D Sprites Unity has another different sorting method it's all based on sorting layers and sorting orders I have video on that topic if you're interested in 2D games okay so with this we have the background and then we have our film bar this way we can see if the progress is being filmed or not also one more tiny thing that I like to add is Unity has some really nice really easy to add effects so you can go into that component and let's search for a shadow this one does exactly what you expected as a nice drop shadow over here on the effect distance let's put it on 0.1.1 in order to see next one let's not do it on this one we'll do it on the background so let's get rid of this instead of going to the background over here let's add the same shadow so if you put it on point one and minus point one you better go a nice simple and drop shadow or the other one that I prefer so instead of the Shadow let's add a really nice outline once again for the effect distance 0.1.1 or maybe actually 0.05 just to be just a tiny bit and let's raise it on the alpha so there you go nice little outline tour bar this is just a visual thing so you don't have to add this but personally I find that it looks pretty good so with all of this we have our Visual and perfectly set up we've got our nice bar all we need to do is play around the filament in order to fill it so now all we need to do is to connect this to the logic but as usual let's make sure to write some good clean code so we do not want the cutting counter to directly touch on this image instead let's make a script to handle on that so let's right click create a new c-sharp script call it the progress bar UI and just personally as a rule I like to open the UI to any UI script you don't have to do that it's just a rule that I personally find helpful to follow that way just by looking at these scripts I can immediately see this one is a UI this one is script and logic and so on so on the progress bar UI on the main game object let's attach the script and let's open it okay so now here we're going to need a reference to our image so let's add a serialized field private and we're going to need the image type and importantly this is inside using Unity engine.ui so let's go up here using Unity engine dot UI so we have our image component okay great let's call it the bar image so we have a reference and now with this obviously we need to have some kind of reference to the counter so we know when the progress changes so it's really the same thing that we've already done so many times throughout this course so let's set a film up here serialize film private cutting counter for our cutting counter then over here in the editor let's write new references so drag the reference to The Cutting counter and another one to the bar image okay great now we just need some kind of event to update the bar image so let's go over here into our cutting count script let's make an event to spawn that so public event let's use the event handler the default standard let's go with on progress change and let's also make a nice event artist to be able to send the current progress amount so let's make a public class on progress changed event arcs and let's extend event arcs and then inside and let's put the current progress however let's also pass in the progress as normalized since that's the what the bar will use so public Cloud progress normalized and we're going to make this event of this type okay great so we have our event now whenever we modify the progress we just need to fire this event so over here when resetting the progress let's fire it so let's invoke pass in this instantiate our event args and pass in the progress normalized and to get the normalized progress sectionally very simple basically we just need to divide the current progress by the maximum so cutting progress divided by cutting progress Max which is actually inside the rest BSO so we need to pick that one up so let's go down there to pick up the cutting progress recipe so we picked this one up and we go in there and get the maximum however over here we also need to be very careful because there is one sneaky issue here this has to do with how c-sharp works and how instar divided with other ends for example if we had a cutting progress of one and cutting progress Max of five you would think one divided by 5 would equal 0.2 however if we actually did that over here we would actually get a zero and the reason for that is because we are dividing two ends cutting progress is an end cutting progress Max is also an INT and if you divide an end by an end then the end result will also be an end since you cannot Define 0.2 in an end the decimal gets cut down and you end up with just zero so that would not be correct in order to get the right value from this calculation we need to make sure to convert one of these values onto a float so that's really simple we just cast one of them so just cast this one to the float just like that basically now this one will first be cast to a float and then we're going to have a float divided by an end and the end result won't be afloat so if you ever do some math and you get some weird results always make sure to check the type of your numbers okay so here we are correctly firing the event and then down here when adding our progress let's do the same thing let's also fire on the event so now we can go back into our progress bar UI and over here let's listen to the event and again remember that if we're accessing an external reference let's do that around start and not an awake so cutting counter listen to the on progress changed event when that happens let's just go bar image and set the fill amount to what we received from the event so the progress normalized okay so that's really it and also appear on start let's initialize it as 0f so the bar is nice and empty okay so let's test back in the editor let's just go back into the scenes make sure the prefab has been saved and let's head on play and right away yep we do see the bar yep it is empty now pick up some cheese drop it and if I cut and if there go add a little bit of progress now a bit more and there you go there's our cheese okay great everything does work now let's add just one more tiny bonus thing we can add some extra logic in order to hide this visual if the bar is either completely empty or completely full that is actually pretty simple over here on the progress bar UI script let's just make some basic show and height functions so private void show and then we're going to have a private void Hind on these one just game objects that active this one set it to true and this one set it to false now on start we subscribe to the event and then let's hide it okay also here it's very important make sure you hide it after you listen to the event if for example You Can't Hide on awake that would disable the game object and the start would never run so it would never listen to the event so if you have reset the game object as inactive make sure you do it only after you're listening to whatever events you want so we have this that's great and then when the progress changes let's just do a basic test so if e dot progress normalized equals zero f or if the progress normalized equals one F so if the bar is similarly empty or completely full if so then let's hide it and if not then let's show it okay that's it let's test okay and yep by default starts off hidden let's pick up the Tomato go up there and yep still hidden now I cut and there you go there it is cut again and yep there you go it hides itself okay great so we've got a nice little visual let's do just one more final thing let's add a really nice animation if we go inside the cutting counter and we'll look at the cutting counter visual over here note how it already has an animator just like we did for the container counter it's all very simple so basically just has a cut parameter when that happens it just cuts the counter so just plays a simple animation since it's going to be pretty much exactly like the container counter and let's actually duplicate that script so let's go down find that script so the container comes to visual let's duplicate this so Ctrl d let's rename this to The Cutting counter visual okay let's open and over here let's rename the script so the cutting countervision okay great then for the parameter let's rename this instead of open close is going to be called cut and for the string it's cut again make sure you write it case sensitive make sure it's all correct then instead of having a container come through we've got a cutting counter and a cutting counter and finally we just need to listen to the correct event so technically we couldn't listen to the unprogressed changed however that one also gets fired over here when the cutting progress is zero we don't want the current mission to play when this happens so let's just make another simple event so a public event event handler let's call this just on cut okay and then down here when we have our cutting progress so we cut and let's just invoke this event okay that's it super simple so now on The Cutting counter visual let's go into the cutting counter and into the uncut event let's listen to this and we're going to set the trigger example like this so get rid of the container counter like this okay there you go a very simple script so now here back in the scene view inside the container counter prefab let's just go inside the visual let's attach The Cutting counter visual just need to drag The Cutting counter reference and that's it let's exit the prefab save it and let's play okay so now let's pick up a cabbage go up there drop it and aren't interact and if there you go we've got a nice little animation all right awesome so I can drop things I can cut them and everything works perfectly all right so here we added a cutting progress to our cutting counter and we also learned about yet another very useful ENT feature called World canvases and at the same time you might have also noticed that the canvas is looking at the camera in kind of a weird way basically just pointing straight forward this can sometimes make it difficult to see so let's work on that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to build a very simple but very useful script to make an object look straight at the camera with various options okay so we previously made the cutting counter and when I placed something yep there's a nice progress bar so now that this is working let's do one more thing right now look at how the bar is oriented it's looking quite a bit slanted that's because we have a perspective camera and it's looking from top down now this is one of those things that is kind of personal preference so maybe you don't like it just like this but a lot of the times you want these World UI elements to face the camera just like a regular UI one example of this problem is for example let me pick up the cutting counter duplicated and let's put one down here so rotate it upwards okay let's put it on 4.50 and minus 5. now if I place something on there and I cut it yep like that the bar is Now inverted so let's make a simple script to solve this problem let's go into our scripts create a new c-sharp script call it look at camera let's go on to The Cutting counter prefab let's open it up go inside on the progress bar let's attach the script so the unlocked camera okay now let's open so from here let's use an interesting function so let's use a private void late update so not update we have the late update so if this is the first time you're hearing about this like the name flies this one is going to run after the regular update so every single update and all the objects is going to run and then on the late updates so kind of like you've got awake and start you have update and late update why this is useful specifically for this script is because for this element you really want us to run the orienting logic you want that to be done after whatever that object does in the update in this case this object will never move so it's not really an issue but for example if you had some kind of moving vehicle with a warm cameras on top if you have that you would want to set the Warren canvas and location to unlock the camera after the vehicle had moved otherwise the canvas would not look perfect so anyways because that here we're doing on late update and now we can just look straight the camera so we can just do transform dot lookup and for the Target passing the camera Dot main.transform this function makes this transform look at another transform or another point so this will make it look straight at the camera also by the way one quick note here in some other tutorials you might see people telling you not to use camera.main the reason for that is because this field did not used to be cached so every time you use this it would cycle through every single game object in the scene until it found the main camera so that was obviously really bad for performance but nowadays this field is now cached by default on the ENT backend so you no longer need to Cache it yourself accessing it directly just like this is now fine okay so with this let's test just make sure to save the prefab and let's hit on play let's go ahead pick up a cabbage put it up there and if they're young look at that how it's looking straight at the camera and for this one down here same thing cut it any up there you go both of them are looking straight at the camera okay so that's great you can also see exactly what it's doing if we try to move the camera again we're using cinemachine so let's move the virtual camera so over here if I just play around with the position.x look at that look how as I move the camera yep the objects are perfectly looking straight at the camera so that's great that's what we want but also you might notice one thing notice under the bars are actually inverted instead of going left to right they're actually going right and left basically this has to do with how the canvas by default assumes you are essentially going to look at it from behind instead of looking forward so that is why when this game object is pointing straight at the camera it's essentially inverted so to sum this is actually quite simple we basically just need to look in the exact opposite direction but at the same time sometimes we might want this exact Behavior having something looks right at the camera maybe we do want it to be inverted sometimes so for that let's make a nice complete script with all of our possible options and for the finding options it's also an excellent way to learn about one more thing which are c-sharp enums enums are an enumeration meaning a fixed set of options that you can have of something so these are really useful when you have a fixed set of something like for example maybe a fixed number of options so for example up here let's make it private make it an enum and let's call it mode and then inside we can Define all of our options so let's say we have the regular look at it and then look at inverted okay so we have these two options in our enum now let's do a field of this type and expose it in the editor so let's make a serialized film private of type mode and call it mode okay let's save this and look what this looks like in the editor and if we go inside the cutting counter and we'll look at the progress bar even look at that the mode shows up and it shows up as a really nice drop down menu so since we have a limited number of options we've got a really nice menu where we can choose each round if you want so that's really awesome that's one of the benefits of enums they are really easy to use over here in the editor now back in the code here and let's decide which one to use so on The Late update let me just do a switch on our mode in case we are on the regular look at mode then let's see exactly this let's simply look in in case we are on the look at invertent for this we just want to look at the inverse position so that's actually pretty easy we just calculate the direction Vector from the camera to this object so a vector 3 call it deer from camera and to get direction from the camera we start from this object so this transformed that position subtract the camera dot main transform position so this gives us the direction pointing from the camera and then just to transform down look at and instead of looking at the camera let's look at the opposite position so let's look at transform that position so our current position points the direction from the camera so we're going to be looking at the exact opposite point okay so that's it let's test and right now by default we have the regular look at so let's just see it let's just play some objects okay so right now it's still inverting and something real nice is you can play around the enums even as the game is running so let's go inside the cutting counter on the progress bar UI for this one let's swap from Lookout to unlock inverten anything like that that one is now looking perfectly so this one is using Lookout and this one using look at inverted okay great it's all working however yet another thing that is all about personal preference note how the visual has a slight slant this is due to how the visual section looking directly at the center of the camera so you can really see it if I move the camera left and right how it Slants going left or going right again the Zone personal preference it's just a visual so maybe you do want this look but let's see another method so over here in our modes let's add two more let's add camera forward and Camera forward inverted and then down here on our late update let's add those so the camera forward and then we have the camera forward inversion so for this one for the camera forward super simple let's just take this transform use the forward which again you can get or you can set it and let's set it to the exact same one as the camera Dot main.transform.4 and for the inverting example the same thing X7 set of four do we do minus four okay so let's see what this looks like okay so here's the game with both counters they're both currently using the unlockit mode now if we put a look at inverting yep that one goes left to right okay great now if I put camera 4 in give a look at that now that one is perfectly straight so even as I move the virtual camera on left and right look how that one is always perfectly facing the camera as if it was a regular UI owned and for the inverter does the exact same thing but invert and so just like that so that's it these are the four modes again these are all just visual elements so pick whatever you prefer for me I'm going to be using this one the camera.4 so that everything is perfectly horizontal so I'm just going to make sure to go inside the prefab and on the prefab itself modified and set it as camera.4 and now if I add the cheese there yep looks great and if I had a cabbage here and yep it also looks right all right so here we created a really nice useful generic script to make an object look straight at the camera in various ways note how this one has nothing to do with canvas or a progress bar or anything it's really a generic script to look at the camera so you can apply this to anything where you want it to look at the camera okay so with that the cutting counter is fully done now let's handle the trash counter in the next lecture hello and welcome I'm your code monkey in this lecture let's create the trash counter this one is actually pretty simple it's how we're going to drop something and just destroy it okay so making the trash counter is going to be super super easy once again going to be another great practical example of the power of writing good clean code and having good organization in your project so let's do the same thing that we've already done a bunch of times so first of all let's make the prefab variant so let's right click on the base counter and create a brand new prefab variant come with the trash counter okay let's go inside and first of all let's drag the visual so find the visual prefab on the trash counter okay then let's duplicate it to make the selecting so let's rename this to selected let's add the selected counter visual let's add the visual inside of it and on the visual let's select the other material so the counter selected and finally on the selected put it one percent bigger 1.01 and start off with visual disabled okay so that's the basics just like we've already done so many times now let's make this script to run this so let's frequently create a new c-sharp script call it the trash counter and by the way here we're already starting to have quite a bunch of scripts so we should probably organize the scripts folder so let's make a new folder let's come with counters and let's make another one and call it scriptable objects so on the counters let's drag the base counter clear counter the container the container visual The Cutting The Cutting visual then down here the trash counter okay let's drag them all onto the counters folder and on these critical objects let's put the cutting recipe and the kitchen object as so okay now our phone there is a bit more organized so let's open up the trash counter and over here as usual let's begin by extending the base counter okay great then let's implement the regular interaction so override the interact and on this one again it's going to be super simple we just check if the player is holding something and if so we destroy it so just check if player that has kitchen object so if the player is holding something go into the player get the kitchen object the player is holding and simply call destroy itself and that's it it's this simple back in the editorial let's just attach a script let's make sure to drag the countertop Point reference and on the selected drag the base counter reference okay with this it should be working so let's exit the scene let's save the prefab and let's drag it over here onto our scene so let's drag the trash counter and put it maybe somewhere over here on the corner so let's put it here on an X of 7 y 0 and -3.5 then let's also fill out these spots down here so let's duplicate the clear counter put one in there put another one in there let's put another one on the side and for the crash counter and let's align it so let's put it a bit more to the side so on 7.5 okay great and let's put it inside the counters and now we can test okay so let's see if we can interact with it and yep as I approach yep I do see it highlighted okay great and if I interact obviously nothing happens since the player isn't holding anything now if I pick something up let's say a tomato and I don't want this tomato so I want to trash it and if there you go it does get trashed all right awesome so this is literally it like I said this is once again another excellent example of the power of writing good clean code this was super simple to implement because we have a really nice structure for how all of our Counters work also because our interaction system is very well built also because the kitchen object system is very well made it's because of all of that great very clean code that we were able to implement a brand new counter in literally about 60 seconds so once again I hope that by following this course you know understand why I'm always talking about the importance of writing good clean code it's exactly because this if you write your code correctly it makes developing the game so much easier at first it might seem like the quick and dirty approach is faster and usually in the beginning it is faster but as soon as you add some complexity the quick and dirty approach suddenly won't scale whereas the well-built clean code approach this one will continue scaling very well so here we have a fully functional trash bin so we can dispose of unwanted objects next let's build a much much more complex Hunter let's build a stove counter which also requires building a really nice State machine so let's do that in the next lecture hey again another quick intermission you're past the halfway point so congrats again by now I really hope you've already learned a ton from the course we've already covered lots of topics and built a ton of systems I hope you've been following the website as you go through the lectures and I hope reading the frequently asked questions that I sent you in some way let me know in the comments how you've used the course website did you just read the FAQ or did you also download some project files let me know I'm curious to know if you enjoy my teaching song also look at my other courses after finishing this one especially the turn-based strategy course that one is an excellent follow-up for this one okay there's still quite a bit more for us to build and learn so let's continue in the next lecture hello and welcome I'm your code monkey in this lecture we're going to build the stove counter so we want to place some uncooked meat then we wait for a bit for it to be cooked however if we weigh too much it's going to get burnt so let's Implement that alright so as usual let's first begin by making our counter so let's go inside the prefabs the counters let's right click on the base counter and create new prefab variant call this the stove counter and as usual let's go inside of it let's find the visual so inside the prefab visuals it counters visuals here is the stove counter so let's drag it then let's duplicate this rename this one the selecton let's set the component the selected counter visual then let's go inside on all of these and by the way this visual actually has some nice visuals that we're going to implement in a little bit but for the selected we really just want the static objects so let's pick up all of these and let's select the counter slide visual okay nice and white then let's lock over here the parents so I can select all of these and drag all of them okay great and start off with all of them disabled okay so that's the basic setup as usual just for the Counterpoint since this one has a nice little sub on top let's lift it up by a little bit so put it on a y of 1.456 okay that looks pretty good just move it a little bit to the center okay great so now let's make our script so let's go inside our scripts folder we've got our counters so in here let's create the brand new c-sharp script for the stove counter let's wait for it to compile let's attach the script and open okay so here as usual let's extend the base counter now like I said the going for this one is to be able to cook our meat and for that it's going to be based on a timer and to actually cook the meat we're going to need to know which one is the uncooked meat type and which one is the cook me type so for that we really want the exact same logic that we did for the cutting action we want some kind of place where we can store an input and output as well as a cook timer so for that let's actually just duplicate so let's go inside our scribble objects for The Cutting recipe and let's duplicate this one so Ctrl D and let's name this one the frying recipe so okay let's go inside and over here let's rename the object then we have an input we have an output and then a set of progress let's have the frying timer Max and since this one is a timer instead of an in let's make it a float okay so that's it pretty simple then back here in the editor let's create our script mode object so let's go inside let's make a nice folder so a folder for the frying recipe so and inside let's create one so let's create a brand new frying recipe so for this one let's call it meat Patty uncooked into meat Patty cooked then for the inputs let's choose the meat Patty uncooked now we have to make the other one so let's go ahead and make that one let's duplicate this one rename it to the meat Patty cooked and the object name meat Patty cooked let's select the different Sprites so this one is going to be the meat Patty cooked okay and finally for the prefab let's also make it so for the meat Patty cooked let's go inside of it and also make sure to save changes on our stove counter it's okay now in here let's get rid of this Visual and use the other visual so we want to meet Patty cooked and let's make sure to drag the script monk object okay so it's all good here and let's go back outside save it and finally over here on meat Patty cooked let's just grab the prefab reference so there you go that one okay so this one is working and since we're here and let's actually make the other one right away so let's make the meat Patty burned so the prefab and let's also duplicate this to make the meat Patty burned then on the text let's rename this to Burnt let's choose the burn icon and for the prefab let's go into our meat Patty burned and swap it out for the burned one so there you go nice and charred and over here swap it for the meat Patty burned okay let's save it and finally down here just make sure everything is correct object the transform prefab just like that okay so all of our burn references over here all of our cooked and over here all of our uncut and again when going through this process always make sure that you match all the references on the certain objects and also over here on the kitchen objects so meet Patty burn yep meet Patty burn for the uncooked the uncooked and for the coke there it is okay everything is good great so now we can go back over here into our frying recipe so and for the output let's output the meat Patty cooked and for the frying timer let's put it on three seconds okay so that's it great now back in the code here on the stove counter let's add an array of our frying recipes so a serialized field private it's going to be an array of frying recipe so frying recipe so array make omelette frying recipe so a ring okay great then back here in the editor let's go inside the stove counter let's make sure to drag that so let's drag the mid Patty from uncooked into cut okay let's also drag the counter top point and finally since we already made the script over here on the selected we can also drag the selector okay so our stove prefab should be working okay let's go outside make sure to save the prefab okay now let's continue with the rest of the script so let's make our override so override the interact action and when we interact with it let's validate dropping the object just like we did on the cutting counter so let's go over here into our cutting count script and let's just copy pretty much the exact same thing so let's copy all of this interact code let's go over here in the stove counter and just paste it now we also need to copy in our recipe so over here on the cutting counter let's copy paste those functions so these functions go into the cell counter and over here on let's face them they're going to work pretty much the same thing so we get an input except instead of being a cutting recipe so we're going to have a frying recipe so so let's replace all the cutting recipe references with frying recipe reference then for the array this one is the frying rasps array and obviously let's rename these so Ctrl R to rename all of them into frying recipe so let's also rename the function instead of get cutting rest BSO it's the frying recipe so okay so there's no more mentions of cutting over here so let's use this function up here and up here and just make sure to rename these the frying recipe as so and down here on same thing so the frying recipe so okay so down here we have no more mentions of any cutting let's just go up here and solve all these problems so first we check if there's no kitchen object here and if the player is carrying something then we see if what the pointer is carrying matches any kind of frying recipe if so then the player is carrying something that can be primed then we set the parent and for now let's not worry about the progress so let's just get rid of all this just like this okay so with this we should be able to drop but only in uncooked meat so back in the afternoon let's just set up our scene so let's drag a stove counter onto our scene let's put over there on X of 6 y of 0 and 3.5 alright so let's test okay so now if I pick up some cheese I go up there and I drop it and nope doesn't work okay great but if I pick up some uncooked meat and I go and I drop it and yep that does work okay great so it works and I can only drop the actual objects and matchy recipe now unlike the cutting counter this one will not be based on a player alt interaction and actually over here and let's fix this minor issue basically we added this debug.log error to the base interact because pretty much every single counter is going to implement this interact function but not all encounters are going to have the interact alternate action so this one lets us do nothing let's not spawn error okay just a quick fix so like I said the stove counter this one is going to be based on a simple timer and for making some time based logic basically we have two approaches one approach is to use a simple foil timer or you can also use a co-routine now a lot of tutorials will teach you how to use a co-routine and that's not necessarily a bad practice it does work it does achieve desired result so to do that you would just make a function like Freight timer so you'd make a private you have to return I in numerator then call it something like handle fry timer then inside you can do a yield return and return a new weight for seconds and to start this co-routine you would do maybe on start you would call start Co routine and start the handle for right hammer so this one approach this is definitely perfectly foundly timer code however personally I am not a fan of co-routines it's not because of performance or anything it's simply because I don't like the pattern that they force you to use I don't like being forced to make a function that returns I numerator I don't like using yield return I don't like having to use the start core routine function I don't like being forced to use this on a monobehavior object those are all requirements for making a CO routine work and personally I find those are way too many requirements that create a very strange pattern that I really don't like so that's really the only reason I don't like Co routines because I find this pattern to be quite a lot convoluted so instead of core routines what I like to use are simple basic flow timers so just make a simple and private void update then we just need to keep track of a certain timer so for example a simple private float frying timer then on the update let's first check that we have an object so it has a kitchen object if we have a kitchen object then let's increase the timer by time dot of time by the way here when working with a timer you can increase or decrease it's pretty arbitrary both ways work the obvious difference is only if you test if it's above the max or if it's under zero in here for frying it does make sense to start at zero and then the defraying timer Max so either that and if the frying timer if it is bigger than the maximum so let's get the frying rest PSO frying recipe so let's get the frying recipe so with input so let's get this kitchen object and get the kitchen object itself okay so we go into the frying rest BSO and we get the frying timer Max okay so if it's above the max then this one has been fried so here I'll let you see what we did on the cutting counter so let's get this kitchen object and tunnel to destroy itself and then let's go into the kitchen object class in order to spawn another kitchen object let's go into the frying recipe and spawn the output and we're going to spawn it inside of this counter right so that's it this should already be working we don't have a visual yet so let's add a debug log so here just say debug.log on the frying timer and up here let's also just reset the timer so frying time now let's put it on zero f and let's also do a debug.log and say fried however like this you might already be guessing that we're going to have a bunch of bugs but still let's just test it just like this okay so over here I can move around I can pick up some uncooked meat I can drop it there and after a little bit there you go there's the timers and if there you go it did work you can see the timer increase until three then it was fried then it was reset and then we've got a known reference exception basically this is the exact same problem that we had on the cutting counter where first we put an object like tomato and that is indeed an input for a recipe so we cut tomato into slices but then the slices are not an input for any recipe so over here we put some uncooked meat so that's great we frying which means we destroy the uncooked meat and we spawn the cooked meat but then next time the cooked meat is not an input for anything so obviously this one is going to return no one thing we can do to sort of solve this problem which is also going to be beneficial in terms of performance is simply caching this field so let's go here to find a frying recipe a cell frying recipe so instead of constantly getting it on every single update which might be a bit costly in terms of performance instead of this let's just get it over here when the player drops something so the player drops something and we assign the Frank rest BSO so we sign it cache the value and then do this okay that should have fixed the non-reference problem but we still have a bunch more problems but still let's test it out okay so here let's pick up some meat put it there and let's look at the timer and if there you go everything is cooking great any of their yo it finished it cooked and the time was reset and now it's finishing it's cooking and so on so this is obviously another pretty serious problem basically it's constantly frying the meat and spawning more and more objects instead of constantly spawning from the same recipe what we want is for the stove to First fry the object but then if the object is fried then we want to burn it so really that means that we want the stove to have multiple States meaning that we're going to need to make a simple State machine so let's do just that now if you're a beginner the concept of a state machine might seem daunting at first but it's actually extremely simple at least to make a very basic one all we need is really just a bunch of saints so to define those States let's go up here and make a simple enum so let's make a private enum call it state and now let's put all the states for our state machine now for the server let's say we have idle when there's nothing on top then let's say we have a frying state for when the ingredient is actually being fried then we have fried for when the ingredient has already been cooked but it's still getting some heat and finally if we leave it too long in that state then everything ends up burned okay so these are all of our states for our state machine and how to make the actual stick machine it's actually quite simple first of all we just need to store the current state so here make a private of type State and sort the current state and then on update let's just do a switch on the current state okay now here basically we're going to do different logic depending on the state that we're at so let's say if we're I don't we do something then if we are frying we're going to do something else then if we are on the front also something else and finally if we are on Burn do something else so here are all of our states and the logic that we did down here this is the frame logic so let's actually just copy on this and let's face it inside the frying logic and for the seed machine we're only going to run any of these states if there's a kitchen object inside of it so it's actually put that switch in there just like this okay so that's it so when I don't we're not doing anything and when frying we're going to run our frying timer we're going to fry the object let's also get rid of the low we no longer need this then we destroy the current object and we spawn a brand new object now what we need is to handle over here the State field we need to modify this winching in Saints so first of all let's handle the start so let's make a private void start and on start let's begin with the state on state DOT Idol okay great then down here when we interact when the player drops something when the player drops something that can be fried over here on let's set the state and put it on state DOT frame and over here we should also probably reset the timer so let's set the frying timer back into zero f okay we set the timer and we reset the state finally up here let's not reset the timer since we're resetting the timer down there since it makes more sense down there so we do the frying the frying timer we end the frying and then obviously we need to modify the state so modify State and put it on state DOT fright okay so that's the basics of our state machine with this everything should be working just the same as previously except we're only going to fry once so let's actually just put them out here debug the hog object Pride and let's put one down here outside of the save machine just do a debug.log on the state okay like this let's test okay so here we are let's pick up some meat and drop it on there and there you go it goes from idle directly into frying and then it's fried and after you go now it stays on fried so it no longer goes on frying and it's no longer spawning any more objects it went from frying into fried and yep everything worked alright awesome so we have the Frank State working perfectly now let's handle the burning in terms of logic it's really going to be the exact same thing we're going to have a frying timer so let's copy this code and paste it down here now technically we could reuse the exact same float timer but that would be a bit confusing so let's keep our code as clear as possible and really just make a different timer with a more descriptive name so pure a private float called The Burning timer then let's initialize this timer so when we go into the fried State let's set the timer the burning timer into zero then down here let's use this Burning timer okay great when timers and lapse and the object is spawn let's go into the Burnside and obviously we need another recipe so let's make another scriptable object back in the editor let's find the frying recipe so let's duplicate this call it the burning recipe so then over here let's modify the name instead of frying timer Max let's call it burning timer Max okay great so now over here on the stove let's use pretty much the exact same thing and let's make over here private of burning recipe so the burning recipe so then down here we just need a function to get the burning recipe so so let's copy this and paste it over here this one's going to return a burning rest BSO so let's replace this and this rename this into burning recipe so we're going to need an array and over here let's just change the name instead of frying recipe so the burning recipe so let's just find a new array so let's go all the way up here make another array an array of burning recipe so and this is the burning recipe SL ring and finally if we go down here let's use this array okay that's it so now let's use this function to set our burning rest BSL so when we set it to find let's set the burning recipe so and let's get it with the input and the input is going to be the object that is on here so the kitchen object dot get the kitchen object.so okay so we're initializing our fright State and setting up the burning recipe so and over here we use that one dot Max and we get into that one and use the output so over there object frying over here object burned all right so that's pretty much it we modified everything to say burning timer over here we are correctly initializing so we go through the burning timer through the burning rest PSO which we are grabbing up here then we spawn the output on the burning rest BSO and we go into state.burn okay so all that's left is just filling in this array so back in the editor over here on let's make the object so let's make a brand new folder for the burning recipe and so and now inside let's create a new Burning recipe so call this one the meat Patty cooked into meat Patty burned and over here let's set the input so the meat Patty cooked onto the meat Patty burned and for timer let's make it take a bit longer to burn so let's say five seconds okay that's great let's just drag the reference so let's go into the stove counter and let's make sure to open up and go inside the prefab and over here on the prefab just write the burning recipe okay that's great let's go outside save the prefab and let's test alright so here we are let's pick up some meat drop it on there and look over there it's frying and after a bit yep it's right there you would spawn that one and now if we wait for five seconds it should go from frying to burn any up there you go that one is charred everything is burned everything is great all right awesome so everything worked as intended with this song of our logic is working now let's handle on picking up objects from the stove now technically it's already working so I can approach yourself and pick it up the object and there you go drop it in there so that does work however if we look over here in the log the state machine is now in the wrong state so over here let's do a quick fix let's go down into the interact action okay so here it is so if there's no kitchen object then the player places it okay that's good but if there is a kitchen object so if there's something on the stove counter when the player picks it up let's also manually set the state and put the state back into idle just like this okay that's it so let's test okay so over here let's pick up some meat put it in there it's cooking and let's wait until it gets finished yep there you go it's done pick it up and there you go out now if I want I can put another one and if there you go the logic is reset and everything is back to normal okay great so often logic is working perfectly now let's just get rid of our logs so we don't need this so let's get rid of that debugging log this one and this one okay great everything is nice and clean and now let's add some nice fun visuals so if we go inside the stove counter and over here is the visual and I include these two prefabs inside the visual so one of them this one the stove on visual this one is just a glowing red square now again there's a weird bug on this specific empty version so post processing isn't showing over here on scene view but if I leave it enabled and I go back outside and now from work in the game view if there you go there's a nice glowing red square if you don't see glowing make sure you add the balloon post Crossing effect so if you missed something you can go back into the post-processing lecture and make sure everything is set up correctly so there's a nice glowing red square and there's also a bunch of particles so you can name on this one press on restart and there you go just some nice particles just jumping up this was made with the unity particle system so for example on the hierarchy you can right click go up here into effects and you can create a particle system so that's what this is it has a particle system over here you can see all of the various settings for these particles they just jump up and fall down so for jumping up that is the emission you can actually see a visual over there of the cone that is the spawning cone which you can find over here on the shape so in the shape it has the shape of a cone then you can see the radius radius thickness and so on so that is from where the objects are being spawned then up here you can see the lifetime of each object so each particle is going to last for 0.7 seconds you can all see the speed so that's speed at which they come from there the start size that's how big they are on start and note how the particles are spawning jumping up and falling down so that Falling Down is over here the gravity modifier if you put it at zero then they just keep going up and if you put a two yep they go up and they fall down next down here on the emission this is how many are being spawned so if I put this on 200 there you go tons and tons of particles next is over here the size of our lifetime so this one has just a basic curve so they started off on font size and over the x-axis this one is in a lifetime so as the particle goes from the beginning until the end their life they basically go down on size so that is why they become quite a bit smaller also by the way this one down here this one is called an animation curve this is another really useful ENT feature I have a dedicated video on animation curves and finally down here just have the renderer so it's just using some basic particles so we can inspect the material simple in the assets and there you go we're just using the default particle material just with the alpha on half and that's pretty much it so as you can see just a very basic very simple particle system now all we really want to do is just for both of these we want to enable or disable them depending on if the stove is on or not so let's make a script to handle the visuals so let's go down and create a brand new c-sharp script let's go with the stove counter visual then let's go into the stove counter Visual and let's attach the script so here it is attach it and open right so now here we just need references to those two objects so as usual let's make a basic serialized film let's make it of type game object for the stove on game object and the other one is the particles game object okay let's save and back here in the editor let's drag the references so the stove on Visual and the sizzling particles okay great so now all we really need to know is know when to turn these on or off and for that is really going to be based on the state over here on the stove counter so if it is on the state frying or fried then we want to show them if it is on idle or burned we want to hide them but as usual we don't want to mix the logic and Visions directly so let's do that through a really nice event let's make a public event let's use a standard event handler let's call it on stay changed and let's also include the state on the event Arc so let's make a public class call it on state change event args and let's expand event arcs and then in here let's just put a public state for our state however here we also have a really nice error so this one is telling you there's inconsistent accessibility basically that's because we made this one public so any class link for his Mr visual class can indeed see this class however from outside that class cannot see the private state so that is why we have inconsistent accessibility we cannot have something public which inside has something of a specific type which is private so in order to make this work we need to modify this state and make it public so that the other classes can see it okay so that's great now let's just fire this event whenever the state changes so over here when you go into the frying State let's go and invoke and as usual just this and I actually forgot to add that so let's go up here let's use the one with generics so the on state change event arcs okay great so then down here we invoke the event let's create of this time and inside passing the state equals this state okay so this one we need so then down here go into the burn State let's fire the event and down here frying fire the vent and on idle fried event alright that's it so we have all of our state logic and over here on the stove counter visual obviously we need a reference to the counter so let's add that so a serialized field private maker of type stove counter for the stove counter and then we can do an as usual for accessing external references let's do it on start go into the stove counter and let's listen to the on say change event and over here it's going to be very simple we just want to show if it's on the state frying or fried and if not we don't want to show so let's define a bone called show visual and this one is going to true if the E dot State equals the state DOT frying or E dot State equals the state DOT fried so if it's either of these then this is going to be true if not it's going to be false so then let's just go into the stove on game object and constant active and pass in this and same thing for the other for the particles game object okay that's it super simple let's just drag this reference so over here inside the prefab just drag the reference let's leave the prefab save the changes and let's hit on play and all right so it starts off disabled okay so there's no visuals now if I pick it up and I drop it and there you go a nice visual so the glowing red hot and the particles and now it's running and if I leave it until it burns when it burns and it's going to turn it off and if there go turns off all right awesome so now if I pick it up wait until it gets cooked so let's go pick it up and the other you go turns it off all right awesome we've got a really nice visual all that's left is to have a proper visual progress bar and with this we actually have another interesting clean code question right now the progress bar that we made over here on the cutting counter that one is great so we would like to reuse that however if we look over here on the progress bar UI we can see this is only working with the specific type cutting counter so by default this will not work with a stealth counter so as usual we have multiple approaches to solving this problem one option would be to Simply commonly duplicate the script then we would make a completely different progress bar UI class that would work only with the stealth counter so that's one approach that would work and that approach might be good if you want the progress bar to behave very very differently but over here I want both of them to behave exactly the same so instead of having some code application we can write some good clean code but doing exactly what we did with regards to the kitchen object parent meaning we can use a nice interface we can then Implement on anything that has some kind of progress so let's do exactly that first of all let's actually go inside the cutting counter so let's go inside the prefab then over here we've got the progress bar and this one is just a regular game object but since we're going to reuse this let's make this a proper prefab so let's find over here all of our prefabs and just drag the progress bar UI inside the prefabs folder okay great so this is now a proper prefab now let's define our interface so let's create a brand new c-sharp script as usual interface start with I so let's go on I and for this one we wanted to represent anything that has progress so let's just call it literally has progress personally I like to use the word has to indicate that a certain object has certain Behavior so in this case objects that implement this interface will have some kind of progress Behavior so now over here for the interface let's first make it so this one does not extend amount of behavior instead of a quest this one is an interface okay great so now for the functions that we're going to need if we look in the progress bar and we'll look at the cutting counter references we can see the only one is literally just this so we just have to listen to the event and then the rest of progress bar Works inside of it so real and interface is the only thing we need to Define so let's actually go inside the cutting counter so here we have the unprogress change event and then we have this so we can literally just copy this go into the I has progress and let's put exactly this okay that's it that is literally all we need now if we wanted we can also make a function to expose the progress amount but since we included over here on the event then we really don't need it just this is enough now let's go over here on the progress bar UI script instead of working with the type cutting counter instead let's work with a type that has I has progress so let's rename this Q has progress and it's going to have the exact same event the only difference is over here instead of the event RX being the one inside the cutting counter is the one inside the eye has progress so let's make sure to change this I has progress okay so the signature matches let's just obviously rename this so let's rename instead of cutting counter let's rename has progress on progress change and that's pretty much it we don't have any more errors so everything over here is now working nicely with our interface and back here in the editor once we're still inside the cutting counter suddenly interfaces do have one downside when it comes to Unity if we look in the progress bar UI down there we can see the progress bar UI and previously we had the counter field exposed in the editor however now by changing into an interface there we have the issue the film does not show up here interfaces do not show up in the editor because Unity basically has no way of knowing that the interface won't be implemented by some kind of game object so sadly this is the one thing that doesn't work very well with unity the solution that I normally do is actually pretty simple instead of exposing the interface which does not work and said let's just make this a regular private field and then let's make a serialized film and for this one let's make it a type game object and let's call it has progress game object okay so like this we have a regular serialized field with a regular game object so if you look here yep we do have that field so now we can indeed Drag The Cutting counter reference and then over here in the code in order to get the has progress that is super simple has progress we just go into the hash progress game object and get component of type I has progress okay so that's it now our code does work however of course one big potential issue with this is that over here we have a field of type game object meaning that we have no guarantee that this field does have a component that implements the interface so we cannot make sure that we drag the correct reference we can drag any reference doesn't have to have our progress interface so in order to keep our sound safe let's add a nice safety warning so over here if has progress equals no so if this one is known that means that that game object does not have any progress interface if so let's do a debug download error and let's say the game object and let's pass in this game object does not have a component that implements I has progress so this way if we make a mistake we won't have a nice error message basically this is the one workaround that you need to use since Unity does not support dragging references in the editor if they are interface references okay so with that everything is good so all of our progress bar UI this should all be working perfectly we just need to go over here into our cutting count script and let's make it so that we Implement our interface so I has progress and we got an error just because even though we did Define that interface remember the on progress change again keep in mind that the types depend on not just their name but where they're at so this type that we have here is the one that we Define here which is not the same one that we have here so even though they have the exact same name because they are in different places they are actually different types so we need to make sure to use the type in the interface over here let's just go into the I has progress and use that exact type and get rid of this one okay so that's it that's the change we need and down here when firing let's just fire with that type and down here the same thing with that type okay great so like the this The Cutting counter should still be working exactly the same as previously again when refactoring any code always do a quick test and let's do that let's make sure to save our counter save the prefab go back outside head on play now let's pick up some cheese put it there cut and there you go the progress bar still does work okay great now let's apply it to the stove and that is actually going to be very simple first let's go inside the stove so let's find the stove counter let's open it up go inside the prefab and over here let's drag the progress bar UI prefab so let's drag that then down here we already have the has progress game object so let's drag the stove counter and that's it there's nothing else we need to touch here we just need to go over here into the stove counter and as usual let's implement the interface so the eye has progress and now let's implement it pretty much just like we did on the cutting counter so we can actually just copy this so we just need to implement the event so that's it and now for firing the event let's go down and see where we are modifying all of our timers so let's go down to when the player drops something so we do the on say change and now let's invoke this event so this and for the progress bar for the progress normalize this one is very simple so just frying timer divided by the frying recipe so dot frying timer Max okay that's it we are modifying the progress now let's go up here when we are in the Frank State and when we do let's fire off the on progress change event okay great and finally down here when we have defined over here let's also fire except obviously we have the burning timer and the burning timer Max and then just to make sure that the bar actually hides itself when we go into burned let's also find an event this one doesn't have a timer so let's just put it on xeraf okay that's really it we don't need to touch the progress bar UI at all Let's test this just make sure to save the prefab let's go back outside and hit on point and right away yep the bar is indeed hidden now if I pick up some meat and I drop it and there you go got a really nice bar going up any up going up on the burning site and let's get to the end let's see if the bar hides so it gets to the end and you have to go the bar that's high all right awesome and if I pick up something actually this was the one event that we forgot so let's fix that so let's just copy the one where we set the progress normalized to zero and over here if the player picks up something let's add the progress back into zero so here we are let's pick up some meat drop it on there okay let's wait for it to be cooked okay it's cooked now before it burns pick it up and there you go the bar is gone all right awesome okay so here we have again another example of the power of writing good clean code we made a nice generic progress bar and we very easily made it work with a completely different counter which of course would also work with literally anything that implements that interface doesn't have to be a counter now let me make one note here basically I showed you how to make a generic progress bar and reuse it but let's say you want to do something specific just for the solve well one approach like I mentioned is to duplicate the code and make a progress bar that works only with the solve but another approach is to Simply add more elements on top for example during the Polish stage we're going to do exactly that we're going to add an extra UI element that won't show up to one of the player when the food is about to burn so I just want to point out how you can mix and match both them you can have both generic components coupled with specific components but for now our progress bar everything is looking pretty good so let's leave that burn warning just for the police age now the next very important thing we need is some points so let's do that in the next lecture hello and welcome I'm your kudmaki in this lecture we're going to create the plates counter this one is just going to spawn some points which we can then pick up to grab some objects okay so let's begin making the counter as usual so let's go inside our prefabs inside our counters right click the base counter make a new prefab variant called the plates counter let's go inside and let's drag the visual for the plates counter let's go into scene view so we can see it okay let's duplicate this make this the selected let's go inside and we can actually hide the Eternal Sprite we only need this one so on this one let's modify it for the counter selected on the selected let's make it just one percent bigger and let's add the selected counter Vision okay then inside obviously drag the reference for the kitchen counter okay that's our basic setup now let's make our script to run this so let's create a brand new c-sharp script for the plates counter let's attach the scrub to the plates counter and open okay now here as usual let's extend our base counter and then first let's handle the spawn timer logic so basically we want to spawn some plates every once amount of time somewhat sorry simple float for the spawn plate timer then let's make a simple update on timer let's increase the spawn point timer by time dot of time and then just check if it's above a certain maximum so if it is above something in this case we're going to have a fixed value but still like I mentioned in the very beginning of this course let us not use magic numbers here you should never use magic numbers instead if you wanted to make it edible you could also make it up here as the serialized field but in my case for design that I'm going for I'm perfectly content with having a fixed value so just appear pretty simple the spawn complete timer Max and let's define it to 4f and let's use it over here okay great so this is what we want however for spawning it's actually going to be a bit tricky the plate is supposed to be a kitchen object the player should be able to carry the plate and right now for design that we Define is that each kitchen object can only have one parent and each parent can only have one object but over here we want to spawn multiple objects now let's quickly see what happens if we try spawning multiple as usual so let's just go into the kitchen object spawn a kitchen object which means we need the plate so so let's do it up here as usual a serialized film private kitchen object so for the Plate Kitchen object SL so we're going to need to make this and then we're just going to spawn this object on this okay so this is going to throw an error but so let's see let's first create the object over here let's go inside our objects our kitchen objects let's create a brand new kitchen object call it just the plate for the object name this one is a plate for the Sprite let's go with the plate Sprite and for the prefab let's make it so let's duplicate one of these called the plate let's go inside it and obviously make sure to change say the changes then over here let's drag the plate visual get rid of the tomato and on the plate let's make sure to assign the plate and finally let's exit this let's make sure to save it and on the plate let's drag the plate prefab okay so we have the kitchen object so now let's just go inside our plates counter and over here let's drag the reference so the reference to the play kitchen object let's also drag the reference to the counter top point then on the selected drag the reference to our base counter and finally start off with a selected disabled okay so this should be working let's just add a plate counter over here onto our scene so let's pick up a police counter and put it somewhere in here over there on the side so on an X of 7.5 then 0 and let's say on zero Maybe let's make sure we have space for one more counter over there so let's duplicate this empty counter and let's put it over there pointing to the side so this one is on 7.50 and -2 okay so now let's just make sure that they perfectly match so let's put this one on a set of minus 0.5 okay so let's test all right so here we are and look at that and after four seconds if there go it spawns the object and then it immediately tried to spawn another one and there you go we have the error kitchen object parent only has a kitchen object basically the way we designed our game and set up the code assumes that a single encounter will only hold a single kitchen object so we cannot have multiple plates on the same counter now when solution for this problem is actually quite simple when we spawn the plates instead let's not spawn a kitchen object instead we're just going to spawn a dumb visual then when the player interacts with the counter that is when we're going to spawn the proper kitchen object so let's do that although again let's keep the logic and division separate so over here let's first just handle the logic so we just need to keep track of how many points respond so for that let's start up here you private end for the plates spawn amount and let's also do another private end for the plates Pawn amount Max and let's say we can spawn at most four plates okay so over here instead of spawning the object let's first of all actually reset the timer so let's put it back to zero zero and on the plate spawn the mount let's check if this one is under the plate spawn Max and if so let's go into the plate spawn amount and increase it by one okay so that's logic super simple now let's send the visual so let's first make our script so let's create a brand new c-sharp script for the plates counter visual now let's make sure that the visual so let's go inside the prefab and over here we've got the visual let's attach it okay open now here basically the first thing we need is we need to know where to spawn the visuals so let's actually add a reference to our counter top point so let's add a serialized film for private transform for the counter top point then let's also add a reference for the prefab we're going to spawn so let's call it the plate visual prefab then here in the editor let's drag the references so the countertop Point Place it in there and for the plate vision prefab let's go a pair and find the visuals for the kitchen object so these are just the visuals and let's write the plate visual so the plate visual not the Plate Kitchen object okay now back in the code here we obviously need to know when I play this Bond so let's go into the plates counter and make a nice event so fun week event event handler as usual on plate spawned and down here let's just find the event so we just invoke with this and eventar is not empty okay that's it very simple and then on the other script over here let's just listen to it which also means that we need a reference to our counter so let's add up here the plates counter for the plates counter so we're going to need to drag the reference and then on start let's listen to the on plate spawned event and when that happens then let's spawn so let's call instantiate on the plate visual prefab let's put it inside the counter top point so this is the transform for the plate visual transform and that's pretty much it okay so unlike this it should be working when the plate is spawned we should be spawning a brand new visual back in the editor we just need to drag the plates counter reference like that let's exit save the prefab and let's test okay so here we are and if we wait for four seconds we should be able to see a play spawn yep there you go and if we wait for a little bit more we should also be able to see some more play Swing spawn except we can't really see them that's because we're spawning them on the exact same spot every time but if we pause the game and over here I'm looking the hierarchy and find the plate counter and inside the counter top Point yep we do have four visions and if we wait for longer then nope it's not going to spawn anymore it's only going to spawn four plates okay great so some of the visual let yourself set them by a tiny bit to know how much we shouldn't offset let's keep track of how many plates haven't spawned so let's store up here on the visual script in list of Game object call it the plate visual game object list let's also make sure that you initialize this so it lets you on awake let's initialize this list and then when we spawn them okay so here we have the object that we spawned now basically we just need to modify the low composition and let's put it on new Vector 3 on the X so let's put it on zero then on the Z we're also going to have zero and then over here on the one let's offset it by a certain amount and basically it's going to be based on how many plates have been spawned so let's define up here a float for the plate offset y let's put it at save 0.1 f and over here we're going to offset it by this much multiplied by how many plates have been spawned so we can go into our visual list account so you can delete this and then we just need to add it to the list so let's add this plate visual transform.game object okay so now each game object should respond at a different height so let's see so here we are and if we wait for four seconds we should be able to see a plate and there you go and now after four seconds we should be able to see another one placed slightly above and yep there it is okay great so everything is spawning perfectly both in the logic as well as the visual now let's actually pick up a plate so on the plates counter as usual let's implement the interact so let's do a public let's override the interact function and now for picking up let's first see if the player is actually empty-handed so if and we check the player has kitchen object so if the player does not have a kitchen object then the player is empty-handed okay great then let's see if we have a plate that we can give them so if the plate spawned the mount if it is bigger than zero then there's at least one plate here and if so let's give it to the player so how we do that is one over here for logic let's just increase it by one then let's actually spawn the object so on the kitchen object let's spawn the Plate Kitchen object so and spawn it on the player and finally we just need to update the visuals so let's make another event so up here on plane spawn and on plate removed okay we have this event and then down here on let's just whenever the player picks it up let's invoke this with this an event RX dot empty okay great so now the visual let's listen to this so we're here on start for the plates counter listen to this event and when this event happens we just want to destroy the very last plate so let's grab the game object for the played game object and recently just going to go into our list so the plate visual game object list and let's pick up the very last one so let's go into the list.count minus one so this is going to be the very last element of the list then let's remove this one from the list so Point dot remove this one that we just grabbed and then we simply call destroy on this one all right so that's it super simple so we're here on the plates counter we do all of our checks we cut it down by one we spawn the actual kitchen object then we fire the event and over here the event listens and updates a visual okay let's test so here we are let's wait for a play to be spawned and when this phone there it is I'm going to pick it up and if there go the player is now carrying a plate let's drop it here and there you go there's another one now let's wait for a bunch more to be spawned okay so the plates counter is full now if I pick up it should only eliminate the last visual pick it up any of there you go it'll eliminate that one now I can drop it in there any other ones one all right awesome okay so that's really it for the basics of the play counter it periodically spawns some points which the player can then pick up now in the next lecture we're going to add the ability for the player to be holding a plate and pick up another object onto the plate hello and welcome I'm your code monkey in this lecture we're going to add the ability for the player to be carrying a plate and pick up objects onto that plate okay so here we already have the plate counter working it has some basic logic after a bunch of time it spawns a plate it spawns up to a certain maximum and I can pick up a plate and if the player is carrying a plate so I can put it anywhere then I can for example pick up some Tomatoes slice them and pick them up however now I am not able to place the tomatoes on the plate so let's add that logic let's begin over here on the clear counter script first we're testing if there is no catch an object here and the player is carrying something that the player drops something in there but then we're testing if there is a kitchen object here and if the player is carrying something so it's over here that we want to check if there's something that the player is carrying if it is a plate now our plate is also going to have a bit of custom logic so to help both identify and hold that custom logic let's make a proper script to handle it so back in India let's create a brand new script currently the Plate Kitchen object and let's open this now over here on this one instead of extending Model Behavior we're going to extend kitchen object so the plate is really just a more specific type of a kitchen object again like I mentioned quite a while ago you want to be very careful with inheritance you need to have a very good reason to do it here we want the play to behave exactly like a kitchen object just with a tiny bit of extra logic so in this case it makes perfect sense let's just go ahead and save this and wait for ENT to compile and over here let's find our kitchen object with the plate so here it is the prefab as you can see we have a kitchen object now instead of having that one let's replace that with the play kitchen object and since we are extending kitchen object we have the same Fields so let's make sure to add the kitchen object as so and get rid of the other one okay great so now back here on the on your counter when there is a kitchen object here and the player is carrying something we can check if the player is holding a plate and for that we can check the type so if let's go into the player and let's get the kitchen object the player is holding and we test if this object is of type Plate Kitchen object if so then that means player is holding a plate and if that is the case then we basically want to give the player whatever object is over here we want to add it to the plate so let's go into the plate script to add that function so over here let's make a public Point let's call it add ingredient as a parameter we're going to receive a kitchen object as so we really only care about the type we're going to destroy the actual kitchen object like we've been doing when creating different types so the plate is really just going to store in list of types so here let's store a list of kitchen object a cell for the kitchen object that sell list then when we add the ingredient let's just add it to the list so this kitchen object is so let's also make sure to initialize the list so let's see what I'm awake let's initialize our list and now from the other side we just need to call this so over here on the clear counter if the player is holding a plate let's first get the type of plate so play kitchen object or the Plate Kitchen object we go into the player to get the kitchen object and we cast this as a plate kitchen object okay so we have this and then over here let's call add ingredient and let's add whatever is currently on this counter so let's get the kitchen object and get the kitchen object itself okay so we're adding it to the plate and then let's destroy what is here so get kitchen object and destroy itself okay so that's it so if there is something here and if the player is holding something and that's something the player is holding as a plate if so we're going to add that ingredient to the plate and then destroy the object in here so let's test okay so here let's pick up a tomato let's slice it let's put it on a clear kitchen counter because that's the only one where we added logic so on this one let's pick up a plate and now whilst I'm carrying the plate and if I approach and I interact with it and if there you go it does work the object vanished from the counter and supposedly was added to the plate again we can use a really nice debug inspector to see it so let's pause the game Let's select the plate let's see the play kitchen object so here it is this one and let's change the inspector into debug mode and down here yep we do see the kitchen object that's on list and it does have some tomato slices okay awesome so with this here we have our basics we can have some ingredients and we can basically pick it up from a plate now one thing about our plate this is where we're basically going to carry the final recipe that we're going to deliver to the customers and based on the design that I defined I want something pretty simple meaning for the design that I'm going for there won't be any kind of double burgers or double cheese so each final recipe will only have at most one of each ingredient so let's add some basic logic just to prevent adding duplicates over here on the Plate Kitchen object when we add an ingredient since the function will now not necessarily succeed every time let's actually rename this and again use a very useful Visual Studio shortcut so you can press Ctrl RR or right click and let's rename since this function will no longer succeed we're just going to try to add an ingredient so try add ingredient and then let's also make it return a buoying basically for any function where you're not sure if it won't succeed I like to add try and make it return ball so this way it works pretty much exactly like the try again component that we've already seen so many times so it tries to do something and returns whether it succeeds or not so over here instead of always adding the ingredient let's see if this one is a duplicate so let's do an if and let's go into the list and check if the contains and if the list summary contains this kitchen object as well if though then already has this type so let's return false and if not then that means it's a brand new ingredient so let's add it and return true okay so that's it now let's go over here onto the clear counter so we try to add the ingredient but then we only want to destroy if this one succeeds so let's put this one inside an if so if we do manage to add the ingredients then yes let's destroy itself if not then we don't destroy anything okay so let's test so let's go ahead and slice two tomatoes so one slice it put it here then another one slice it and put it here now let's pick up a plate go up here try to pick up this one and yep it does work now for this one and I hope it doesn't work okay great now one more thing in our logic we only want to pick up certain things like I said only things that won't be used in the final recipe for example no customer is ever going to request a full entire tomato the recipes only have sliced tomatoes so we should not be able to drop a foam tomato directly on top of a plate so let's change that so over here on the plate script let's basically just create a list of our valid ingredients so let's make a serialized film private make it a list of kitchen object SL ope and call it the valid kitchen object SL list okay so we have this list and over here in the editor let's just write the ones that we want so let's first of all select the plate object okay here is the flight prefab and over here we've got all of our kitchen objects so let's just write the ones that we want to add to the point so the final recipes will have some bread yep but they will not have entire cabbages they will only have cabbage slices same thing no cheese only slices for the meat we're only going to be able to add meat cooked but also meat burned then we're not going to be able to add a plate onto a plate of course not and finally inside of a tomato just tomato slices okay that's our Vellum list and over here again it's very simple so we can just go if the evaluate kitchen object that's on list if this one contains the one that we want to add then we can add it but if not then let's return phones not a valid ingredient okay so let's test alright so let's pick up a tomato and also some tomato slices and now if I pick up a plate and I go into the Tomato nope doesn't work but the slices yep it does work okay great so here we have all of our basic plate rooms everything is working perfectly but it's only working over here with the clear counter so let's do a little bit of code cleanup and then let's add this logic to all the other counters so first to clean up this cone over here we are testing if this is a plain kitchen object then we cast to an object and then we count the function so let's simplify all this and let's do it just like yinty does with their try and get the component function so let's make a custom function that takes an output parameter the best place to put it is on the kitchen object so here we've got the kitchen object script okay great let's scroll down and make a nice function here so let's make it public we're going to return Boolean in case this succeeds or not let's currently try get plate and over here let's make an out parameter so don't forget the out keyword let's return of type Plate Kitchen object for the play kitchen object then over here we do examine what we did so we test if this object is a plate kitchen object if so then let's set the play kitchen object equals this as a play kitchen object and we return true but if not then this is not a plate so let's return false and one thing when working with output parameters you always need to make sure to set the output before you exit the function so over here that's the error that it's telling us we must assign it to something when we return so over here we don't have a play kitchen object so to solve this we just set this to no okay great now over here on the clear counter instead of doing all this basically let's ask the player if this is a kitchen object so let's try to get the plate out Plate Kitchen object for the Plate Kitchen object so you try to get it then we try to add the ingredient and so on now obviously we could further simplify things by making a function that would try to get the plate and try to add the ingredient that could work but since some counters are going to have a bit more custom logic I think keeping them separate like this makes more sense so first we try to get the plate then we try to add the ingredients so let's apply the same logic to The Cutting counter so over here on the cutting counter let's scroll down to where there is a kitchen object here and the point is carrying something so on the earlier counter we just want to copy all of this so let's go over here and we do the exact same thing okay that's it and the other counter from where we can pick up things is from the stove counter so here we are on the stove let's scroll down until we find the interaction okay there's something here The Player's carrying something so it's over here let's do that and do the exact same thing except on the stove again let's remember that this is using a save machine so when we pick up something let's do pretty much the same thing that we did here so let's make sure to reset the State Fire the events and so on okay so those are the only counters that we need to implement we cannot drop things on top of a container we cannot drop things on top of the plate counter or the trash so these are the only three types that we need to implement so with this let's test okay so let's begin with some meat so let's pick up some meat put it on the stove let's pick up a plate wait for it to cook pick it up any up there you go it does work now it says the cut encounters and let's pick up some cheese and let's slice it pick up some plate and go any up there you go it does work and again if we inspect we can make sure that it is indeed working so let's get into the plate and let's put this on debug inspector and if there we do see this one has a meat Patty cooked and some cheese slices okay great now the last piece of logic that we need is pretty much the opposite so right now it works if there's a sliced object on the plate and the player is holding a plate object but now we want the opposite so let's say there's a plate in here and we slice some cheese and now I want to drop the cheese on the plate so let's do that and basically for this one this one is only going to happen on the clear counter that's the only counter type that can have a plate on top of it so over here on the clear counter then we check if there is no object there but that's not what we want we want if there's a plate on the counter so if there is an object there and if the player is carrying something then we check if the player is holding a plate but if not so if the player is not holding a plate so player is not carrying plate but something else over here we need pretty much exact same logic except just testing for the object on this counter so let's do if let's get the kitchen object on this counter this one try to get the plate so out play kitchen objects for the Plate Kitchen object so if so if so there's a plate over here that means the counter is holding a plate so then let's go into this play kitchen object let's add the ingredient and we're going to try to add whatever the player is currently carrying so the player dot get kitchen object and get the kitchen object as so so we're going to try to add this and if we can add then we're just going to destroy whatever is on the player okay that's it and over here we've got a nice error just because we've defined it with the same name appear so up here we're already defining the variable and over here we're defining the same variable with the same name so we can either give this a different name or just not Define a brand new variable here so just it's a fine up here and we're using it here okay so while logic is working now here make very sure that you're not mixing references keep in mind when you're referencing the kitchen object on this counter and the one on the player those are two different things so over here if the player is not carrying a plate but something else then you check the kitchen counter so over here you're not checking the player but checking the counter then you go into that point and try to add the ingredient and you try to add the one that the player is carrying and then you destroy the one the player is carrying so again be very careful here make sure you don't mix references so with this it should work so let's make sure to save our script and let's test okay so here we are let's first pick up a nice plate let's drop the plate in there pick up some bread drop the bread any of there you go it does work alright so now we can do a bit more natural interactions so for example let's pick up some meat and put it on cooking and there you go the meat is fried so now I'm currently carrying just some meat so I place it there then I pick up some bread and put some bread on top of the meat and yep everything does work policy okay so here we created the plate and we created some custom logic to Define what the plate can and cannot account no that's left is actually being able to see what is on the plane so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to add a nice visual to our plate okay so right now we can already pick up ingredients under the plate so if I pick up the plate and I pick up some cheese there you go there's some cheese on the plate but we cannot see it so let's solve that and we were going to do that it's actually in a very simple way if you look in the included assets inside the prefab visuals there's this nice plate complete visual that I built basically it's a foam burger that contains all the ingredients what we're going to do is actually very simple we're just going to enable or disable these game objects that's it so let's do example that let's make a new c-sharp script quality plate complete visual let's attach a script over here and let's also make sure to put this one inside the plate so let's save this prefab let's go inside the play prefab so inside the prefabs here the kitchen objects we've got the plate so inside of the point let's drag that let's drag the plate complete visual okay great so now let's open up this script over here on let's first have the reference to our Plate Kitchen object film private for the Plate Kitchen object for the Plate Kitchen object back in the editor let's drag the reference okay great so now here basically we need to update this visual whenever the plate gets any ingredient added to it so let's go over here into the point script and basically just need to fire off an event when that happens so let's make a public event event handler and let's call it on ingredient added okay and for this one let's also make an event RX to contain the data of what object we added so let's make a public class on ingredient added event args let's extend event args and inside let's make just a kitchen object a cell kitchen object as well okay great and let's make the event of this time all right so now let's just fire off this event so down here when we try to add an ingredient if we do add the ingredient let's fire off this event so let's invoke with this and let's create a brand new one passing the kitchen object as so as this kitchen I'll take this off okay so we have our event correctly being sent now we're here on the play complete visual let's listen to it again as always let's make sure to do it only on start so the play kitchen object on ingredient added let's listen to this event and over here we just need to either enable or disable the visuals that relate to the kitchen object inside over here the event arcs however of course the question is how exactly do we find them the point complete visual has all these game objects how do we know which one belongs to that kitchen object now technically one way would be to do a simple transform find and find the channel objects by name technically that would work but like I mentioned in the beginning of the course strings are a horrible way to identify things they are very air prone so let's not do that instead let's use a proper approach where we can Define some kind of link between a kitchen object a so and a game object and we can do this very easily by justifying a struct so here in our script let's do exactly that let's define a public make it a struct and name it kitchen object so underscore game object then inside it's very simple we just have a kitchen object so field and then also a game object field that's it super simple by the way if you don't know what is a struct basically it's very similar to a class except it's stored in different places in memory and behaves somewhat differently I have a very very important video on that subject what is the difference between value types and reference types classes are reference types so when you pass in a class into a parameter you are passing in a reference to that object whereas struts are value types so when you pass in a struct onto a parameter you are passing in a copy it's a bit of a tricky thing so definitely make sure you go watch that video for more details so you don't get confused in the future here I Define that as a struct simply as kind of a teaching moment but also because it just makes sense that if I just want to store some data without any logic then it should probably be a struct and not a class although in this case the class would work just as well anyway so here we have a struct inside the struct we have a field of type kitchen object so another one of type game object so now let's just make a list of this type that we can expose in the editor so here a serialized film private let's make it a list of kitchen objects so game object and call it kitchen object so game object list okay that's it super simple so let's save and make sure this compounds so actually let's just comment this out just make sure our code compounds okay and over here in the editor we see the tricky thing when it comes to using fields of custom types if we look in the inspector no we don't see anything so we cannot see our custom type in the inspector if you make a custom time like this front and you want to show it in the inspector then you need to add the attribute serializable which exists inside system so let's go up here using system and let's say the attribute serializable just like this okay so do this save and let's look and if there you go now we do see our custom struct so we've got a list then we can click on the pause icon and there you go we've got an element and it does have a film for a kitchen object so and one for a game object so that's great with this now we have a really nice place where we can link one object to another so let's just do exactly that so for example let's put the bread over there and let's assign the kitchen object as so for the one with bread let's do the same thing for all of the others so let's add a whole bunch more Okay so we've got the bread then we're going to have the meat Patty cooked then the tomato slices then we have the cheese slices the Cabbage sliced and finally the meat Patty burned so I've got number zero through five so you have six elements and over here yep we do got six so we have all of them we can get rid of these last two okay great and now let's assign the proper objects so this one for the meat Patty cooked then we've got the tomato slices then we have the cheese slices then the Cabbage slices and finally the meat Patty burned okay great so all of the references match now back in the code here so we have this List fully filmed out and when we have this really very simple we just cycle through the list to find the right game object it's similar to a 40 inch of type kitchen object so game object in our kitchen object so game object list and we check if this kitchen object is so dot kitchen object matches the one that we received in the event if they do match then go into this one grab the game object and set active into true okay so that's it some very simple logic and also we can start with them disable them by default in the editor or just over here just use something very simple just do a for each second through every single one of them and set every single one of them to false so that they are hidden okay so with this on the ingredients on the plate should be visible so here in the editor let's just make sure all the references have been set let's go back save the prefab and let's set on play okay so here we are and by default like that an empty plate and yep it is empty and now let's slice some cheese now let's Place some cheese on there and there you go we've got some cheese now let's pick up some bread drop some bread and there you go got some cheese and some bread then let's cook some meat so let's cook it and let's pick it up with a plate and as soon as I go boom there you go I've got a nice cheese butter all right awesome so wait a second I'll do a complete Burger so let's finish it let's just add some more tomatoes so slice them and add the tomatoes and finally some sliced cabbages slice them put them there and there you go here we have a fully complete Burger okay so that's great all of our vision logic is indeed working however this visual is a bit hard to see it's not very clear to the player so just looking at it from this distance does that have a tomato or not there's a tiny sliver of red in there but you can't really see it so we should probably add some nice clear icons on top to clearly indicate what exactly is on this plate so that's exactly what we're going to do in the next lecture hello and welcome I'm your code monkey in this lecture we're going to add some really nice icons on top of our plate so we can easily see what is on there okay so for the icons let's do the exact same thing that we did for the progress bar meaning let's use a warm space canvas so let's go inside our play kitchen after prefab and over here on let's right click let's create a brand new canvas let's name this the plate icons UI then for the settings let's make it World space put it on zero zero everything width and height also on zero then let's lift it up a little bit so put it on a y of one okay like that now inside let's define an icon so let's start by making an empty game object call this just the icon template let's put it with a size of 0.3.3 it's okay something like that then inside let's add a new UI image name this the background and make it stretch to film The appearance so put 0 on everything okay there's our background for the background image instead of a square and let's actually go with a circle for that Unity actually has a bunch of built-in Sprites that are tatted in the last versions however it's not actually over here by default in order to see those default Sprites we need to install the 2D Sprite package so let's quickly just go into window package manager let's make sure we are in the UNT registry make sure we aren't looking at all and over here let's find the 2D Sprite package okay so let's install this okay there's the package so now if we go into the background and we search for a Sprite and over here make sure you click to actually show the assets from the packages and now we see a bunch of default hexagons a bunch of isometric tiles the square so on and if we search for Circle yep here we've got a bunch of circle so let's use this one over here on this path so let's use it there you go we have a nice circle now let's duplicate this image and for the second one let's name it icon then for this one let's assign just a random Sprite so let's say the bread and again remember how the Sorting order on the UI this one is based on the ordering the hierarchy so make sure that the icon is underneath the background the hierarchy that way it shows up on top okay so we have our icon template that's great of course we're going to dynamically generate all of this through code we're going to have multiple icons and for positioning them Unity actually has some really useful components let's select the plate icons UI and over here now let's add a component now for example a built-in component is the grid layout group this basically helps you position all the charm objects so let's put the size of the canvas over here on 0.9.9 okay so there you go a nice Square window then over here on the settings for this for the cell size let's put it at 0.3.3 and if there you go already shows up over there on the corner and we can see what it will look like if we just duplicate this object so let's make a bunch more templates and if there you go that's what it looks like so as you can see this component is super useful for automatically positioning all of the challenge objects now if we want we can play around all of these we can add a little bit of spacing on the XR on the Y but let's actually leave both those with zero let's leave everything on defaults just over here on the channel alignment let's put it on middle Center okay so there you go that looks pretty nice so you can see how this built-in component is super useful there's actually two more so this one for the grid layout this is great when you want to put things horizontally and vertically but if you just want horizontally then there is the horizontal layout group and if you just want vertically there's the vertical layout group so all of these components are really awesome really useful okay so with this our objects are placed and note how I named this an icon template basically a template is just what I call something that is kind of like a prefab but not really a prefab through code we're going to duplicate this template and dynamically modify the icon so we're going to use it very much like a prefab we could actually make this into a proper prefab so I could just drag it over here onto the project files and make a regular prefab that could work and the only reason why I prefer this method of not using a prefab he's just because this object this template stays here on the object as opposed to cluttering over here your project files if you have tons of single-use UI elements with tons of objects you need to spawn you can end up with tons and tons of prefabs and you might not even know where each of those is used whereas with this method the template says exactly where it's used and does not take an asset slot over here on the project files so personally this is just approach that I prefer for spawning UI elements but like I said prefabs work as well so if you prefer using prefabs go ahead and make it okay so let's make our script to run the plate icons UI so let's go into our scripts and on the scripts folder let's create a brand new c-sharp script for the plate icons UI over here let's attach a script and open it okay so now the first thing we need is a reference to our plate so let's begin by making a serialized film private for the played kitchen object for our play kitchen object okay let's save it and drag the reference so over here there's the point icons let's just drag the plate reference okay great now on the plate we already made this event when an ingredient is added so basically we just need to listen to this in order to add the new icon so over here on the UI let's do as usual private void start and on start let's go into the Plate Kitchen object and listen to that event and when that happens let's spawn an icon although here let's actually use a different method from the one we used on the plaint visual over here on the plate visual whenever we had the event we really just modified the object that was added so over here the equivalent would be to spawn a new icon whenever that one was added but instead of doing that right now let's listen to this event and when this happens let's update all the icons in this display basically this other method is useful when the contents can be added as well as removed now in this case they are never going to be removed so in this case both methods were fine but still I want to show you the second method just so you can use it when you need it so for that method we just need to know exactly what is on the plate so over here on the Plate Kitchen object we just need to expose the kitchen object as some list so let's do example that so fun week we're going to return a list of kitchen object SL let's go and look get the kitchen object the sewn list and we just return the kitchen object that's always okay very soon then over here on the planet icons UI let's just make a function to update the visuals so private Droid let's call it update visual and when we have the event let's call our update visual okay so now here let's basically just cycle through all the ingredients so let's do a 40 inch kitchen object so in the plate and get the kitchen object the sewn list okay so we're cycling through all the ingredients on the plate and then we want to duplicate our template so that means we need a reference up here so let's add a serialized film private type transform complete the icon template okay and let's save the code and over here in the editor let's drag the reference so let's drag the icon template by the way I'll have the others over here that's not a problem since these are going to be destroyed those we're going to see in a little bit the only one that matters is the first one okay so here we have the icon template so to spawn it we do it just like we do with any preform so we just call instantiate pass in the icon template and then transform parents so let's put it as a child of this object this part is important we need to make sure the object is spawned as a child of this object if over here you put something like no then the template won't be spawned as a mobile object so it won't be somewhere in the world so in order to make it positioned properly let's make sure to use transform to become a child of this object okay and then since we're using the other script the green layout group this is already going to be automatically positioned so just like this it should be spawning the icon and with the icon spawned all that's left is really just setting the image and now again the quick and dirty approach would be over here when we spawn let's say we pick up the item transform and over here we could go inside and do a find in order to find the image in order to get the component of Type image and so on so that is one approach that would be the quick and dairy approach but again we want to do things properly so let's do it the proper way instead so instead of this let's make a proper script that we're going to run on the icon template so let's create a new script so a new c-sharp script come with the plate icon single UI so this one represents just a single icon let's go ahead and attach it to the template so over here let's drag it and now when using this template method really the only one we need to worry about is this one the other duplicates we can just leave them they don't really matter but don't just avoiding confusion I'm actually going to delete them it's okay we just have one icon template okay and it has our script okay let's open now over here let's basically just make a function to set a kitchen object or so so public void let's go on set kitchen object so we receive parameter of type kitchen object that so okay great so then we need to set the image so let's just go into a serialized film private of Type image which is inside the unity engine.ui so for this one for the image we have a reference and then we set the image.sprite go into the kitchen object and grab the Sprites okay so we need to do is drag this reference so over here in our template let's drag the icon image okay great so now back here on the plate icon Ty so we spawn it that's great then let's we get component in order to get our script so the plate icon signal UI okay and then we just call set kitchen object so and pass in this okay that's great this is much better now again you might be thinking that this method is a lot more verbose than just setting the image Sprite here we had to create another completely new script we had to write this logic and over here get it and use it the quick and dirty approach would indeed be quicker but remember that while the equationary approach might be faster at first it will mess you up over time so just take a few extra seconds to do things properly this approach is much more scalable let's say for example on this function you want to change not just Sprite but also trigger some kind of Spawn effect or animation with this it's very simple we've got this function right here we receive the kitchen object of so and we can do whatever we want with it so like this we have this grip that is responsible for anything related to the single template and if you've got the general one which just spawns him and just gives them the kitchen object so so all of our logic is nicely separate okay so just like this it should already work however like this you might already be thinking want to spawn way too many icons and yep it will basically every time we add an ingredient we're updating the visual where we're cycling through every single one and spawning all of them so with this we're constantly going to spawn more and more items this is not what we want over here on the update visual we do want to update and spawn all of the icons but before we do that we actually need to clean it up we need to clean up the icons from the previous event so before we do that let's just cycle through all the children on this transform so that's pretty simple you can just do a for each transformed child in the transform so this way Cycles through all the children and then just call destroy on this channel that game object so that won't work that won't destroy all of the previous children however of course we also have one issue the icon template itself is also a child so if we do this we're going to destroy the icon template which then over here we're going to have an error because we're going to instantiate no so we want to destroy all the children except for the template so over here that's pretty simple we just check if the child equals the icon template if so then let's just skip it so we can just call continue and there you go it skips okay great so just one more final thing if we leave the template like this meaning the game object is enabled like this the template will always be visible plus whatever ingredients we have we don't really want the template to be visible this is just meant to be a template that we can instantiate so that's pretty simple to fix let's make a private void awake and on a week let's grab the icon template grab the game object set active into false okay so now the icon template won't be disabled so it won't be visible and then over here when we are instantiating the instantiated ones will also be disabled so let's make sure we go in there and enable these all right that should do it so all of our logic should be working there's only one more tiny thing we need to take care of this one is a world canvas so like we saw with the progress bar we need extra logic to make it look towards the camera and thankfully we already wrote an excellent generic script to do just that so let's go into the point icons UI and let's add a component and let's add our very nice look at camera something like this and let's set the mode the same that we use so let's put it camera.org okay so everything is great everything should be perfect so let's finally test let's leave the scene save the prefab and hit on play all right so let's go pick up a plate and there you go there are no icons visible okay that's great now I'm going to place a bread on top of the plate and there you go I've got a nice bright icon okay great now let's make some meat cook it and as soon as it's done going to pick it up and there you go I've got a bread and some meat now let's put some cheese slice it put it there and there you go now I can easily see that plate has some bread some meat and some cheese now let's just add the rest of the ingredients to make a foam Mega Burger so let's add some tomatoes and add some nice cabbage slices any of there you go it works perfectly so here we have a complete burger with everything and we can easily see on the icons everything this contains alright awesome okay so here you'll learn how to make yet another Super useful element that you can easily add to all of your games personally I use this kind of logica ton in all kinds of UI things for example in my upcoming steam game total warm Liberation the items in the inventory they're all added using this method so there's a template and I duplicate that template same thing for all of the action buttons all of those are based on having a template and duplicating it it's a really easy way to do this kind of thing with all that here we have a phone plate and we can easily see what is on there so with this the next obvious step is to actually deliver some orders so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to build the delivery counter this is where we're going to drop some items that the customers have requested in order to complete the orders also just for fun we're going to learn how to use Shader graph to make a simple custom Shader okay so let's begin by making our counter so let's go into our base counter let's create a new prefab variant for the delivery counter let's go inside and now let's find the visual the visual for delivery counter let's duplicate it to make the selecting let's go inside modify the material then on the selected make it one percent bigger one zero one add the component the selected counter visual let's drag the kitchen counter like that okay that's our basic setup and also start with the kitchen count disable okay great now let's make a script to run this so let's go into our counters folder and let's create a brand new c-sharp script for the delivery counter let's attach it and open okay so now here as usual let's begin by extending our base counter class all right now let's override the interact function and for now let's actually do it it's not like the trash counter meaning let's just destroy the object so we just check if the player is holding something so if the player has a catch an object let's go into the player the kitchen object then let's destroy it however another room over here for an Oliver counter is this is only going to accept plates so let's see if the player is carrying a plate object so player get kitchen object and test try to get the plate so out played kitchen object for the Plate Kitchen object we try to get this and if it is a point then we destroy it okay that's it here in the editor let's just compound the script and drag the references so the countertop point and on the selected let's drag the counter reference and let's exit this save the prefab and let's drop it over here on the corner so let's find over here the delivery counter and let's put it over there hang on it on this side put it like this let's also just quickly reposition all of our counters since we already have all the types that we're going to use so on the lever counter let's put it over here on this corner so x 7.5 0 and Z of two then next to it let's put the plates counter so over there okay then next week let's put a clear counter after that let's put the trash counter and then let's also put another empty one there so let's duplicate this one move it up to about this and put it like that now we just need to move all of these down here so just select all of these counters and let's move them down by about this okay so on minus 5.5 like this okay so everything is nicely positioned just over there right now we cannot access that container so let's actually modify those as well which by the way over here there's the canvas in front so as I click I'm actually selecting the canvas in the hierarchy so here's a quick empty tab on the hierarchy on the left side you've got these two buttons so one of them hides the object and the other one simply makes it unselectable so if I click on this and I click through any of the click goes through the canvas so that makes it much easier to select over here on the items in our scene so let you select all of these okay all of these now just push them all to the side and make another empty one and put it over here okay that's a nice layout now let's just finish the rest so over here let's just duplicate our empty counters and place a bunch more let's put one more to the side and now these ones over here so let's put it over there and rotate it here and duplicate another one and another one and another one and just one more and get rid of this one okay great so here we have pretty much our complete map let's also just move the camera tiny tiny bit just make sure that it is nicely organized so put it over there just so everything is nice and centered okay so there's our map now let's get back to working on our delivery counter we already added this code so let's just quickly test so here we are and if I pick up something like for example some cheese go into the delivery counter and interact and nope nothing happens because that one only accepts plates now if I pick up a plate go there don't wait for any of there you go it does work okay great so this is the basic logic that we want for defining the actual recipe and logic we're actually only going to do that in the next lecture but for now let's add one more nice thing let's add a simple custom visual over here using Shader graph this is a great way for you to learn the pottery of Shader graph and just how easy it is to use this is a visual tool for making shaders it's really very easy personally I don't know how to write shaders with code but I can build some pretty nice things using Shadow graph as usual I have a dedicated video on it I also have an entire playlist showcasing how to make all kinds of interesting effects and even one special video covering some changes in recent shareware versions so over here let's learn the basics how to use it so first here in our project window let's create a brand new folder let's name it just shaders and now inside let's create one so let's create then go up here into sheet graph then we're using urp so let's go inside there and here we've got a bunch of options now don't worry about picking the quote unquote wrong option all this does is just create a template so for example if you accidentally create an unlit Shader you can then easily swap it out from it so right right now let's go with the English hitter and for the name let's name it moving visual okay there's our shade Rafael now now let's just double click to open it and up here we have the nice shade graph window by the way you can make this phone screen so you can either right click over there on the tab and maximize or alternatively you can just click on this window and then use the hotkey shift space and if there you go it does maximize okay great now by default we have this down the center this is called the master stack these are the actual properties that we're going to need to use then on the left side we have the properties Blackboard on the right side we've got the graph inspector and finally down here we've got the main preview all of these windows can be scaled and also if you don't see these windows or if you accidentally hide them they're all appear on these three buttons so the Blackboard that's on the left the graph inspector and the main preview okay so now here we've got a nice empty board so we can add whatever nodes we want so we can right click and go into create node and then we can write something or just click anywhere and press on space and there you go now we can cycle through and browse all of these menus to see all of the nodes that exist there's tons and tons of them or alternatively just go up here and use the search bar so for example let's find the sample texture 2D node so here it is this one okay we've got this node what this one does is it takes a texture and grabs the color from it so on the left side of the node are the inputs and on the right side are the outputs within the parentheses you can actually see the types so for the input texture this one is of type T2 so that means it's a textured 2D then on the output you can see there's a 4 meaning it contains four floats which in this case refers to the four colors so that's red green blue and Alpha so for an input we want a texture so let's set it over here as a property let's click on the plus icon and we've got a whole bunch of types for texture we want a textured 2D so let's go with that and then for the name now usually there are two standard names there's one called main text or base map main tags used to be the more common name but when working with urp for some reason they decided to name the main texture as base map so we're here let's stick within the urp standard and just call this basement okay there's our property and if we click the select it and on the right side we can see the graph inspector and we can see all the properties for this Actron property so we see a name reference and a bunch more things now the really important one is over here the reference this is the actual name that you're going to use if you want to interact with this Shader through code the name on the property this one is just a text ring so this can be whatever you want you can even have spaces and so on whereas the reference name this is the really important one and by default when you set up a name it should already accept the correct reference usually the standard is to name it just like the name both without any spaces and with an underscore in the beginning so just like this okay then we can give it a default texture so let's go ahead and select something for example over here the bread texture remember this is just the default this will not be hard-coded directly into the Shader we can then modify this okay so we we have our nice base map property definition now we can just drag it over here on the board and yep there it is and now we can just click on the server icon in order to drag a connection and let's connect it over here onto the sample textures to the input and yep right away we do see it does work so we are correctly sampling the texture however if you look on the main preview over here there's still nothing that's because we don't have this node connect to anything we need to connect it to the final Master sack in order to render something so again on the output over here we can see a four so these are all of our colors and actually one very useful node is the preview since so many things in Shader graph can be hard to visualize so we can move these nodes around and let's add the preview node and this does examine that so you can fit it an input and you can see down here what that input contains so for example let's drag just the red Channel and if they go over there we can see the red channel for this texture we can drag the green channel the blue Channel or look at the alpha Channel yep there you go it does work so this preview node is super useful for being able to see what your Shader is actually doing over here we have the colors so let's get rid of the preview right now in order to make it work we really just need to connect the rgba and go up here into the base color and right away it should work but you might not be able to see anything over here on the main preview I believe this is a rendering bug in the current Tech version so right now nothing is shown so if you still don't see anything it's actually pretty simple just go up here on the top left side and make sure to save the ascent okay save it great then let's exit from our maximize View and now let's close this tab let's click on play just to play the game now let's stop playing and now if we open the Shader again if there go now we do see the Shader compiling over there that color that is the Shader compilation and after a little bit it should work let's just maximize this see if there you go there we do see our texture okay great so again it's just a simple rendering plug on the current Tech version if you're watching this video in the future chances are you don't even have this box so there's no need to worry okay so right now we do see it working we can see our bread texture and it's currently being applied on a sphere for a use case we're working with 2D textures so this would be best to be seen on the Quan so we can right click over here on the preview in order to select the preview mesh so let's go with a simple quad and if there it is we have our Knight Squad okay great so over here we have our basic Shader all it does is just shows the texture that's it now it's actually use this and first let's always make sure to save the asset on the top left side on the moving visual if you see an asterisk here that means you have unsafe changes so always make sure to save them in my case I don't but still never hurts to save now over here in scene view let's go inside art only three counters and let's open it and now for the display for our Arrow let's make it a flat one so let's right click in the hierarchy and let's create a new 3D object and let's make it a quad let's call this the delivery Arrow let's place this on top of the counter so let's rotate it to face upwards by the way on the rotation make sure the collar is facing upwards most shaders by default they only render one face and not the other one so make sure you put the face with the collar upwards and not the other one okay so let's rotate this one upwards so there we go 90 over there and let's just put it just exactly on top of the counter so just enough so that it's visible okay great so now let's make a material for our Arrow so let's go inside the materials folder and over here let's create a brand new material let's call this the delivery Arrow let's make sure to use this material on the quad so let's just drag it over there on the mesh render okay so it's using our custom material and over here on this Shader graph drop down menu over here we can select what Shader we want to use so in our case let's go inside the founder Shader graphs and inside yep here we have our moving visual Shader so let's go ahead and use this and here right away we do see that it does work here we have our texture being drawn exactly on top of our material okay so far so good now again here remember one very very important thing that I said the texture that you define the Shader over here the default for the property this one is only the default the important one is the one that we have on the material I'm emphasizing this point because I've seen a bunch of people make this mistake if you modify default texture whilst inside the Shader like for example if I change here from bread let's say into the Cabbage slices if I modify that note how it does not modify any materials that were created we are only changing defaults so if you want to change the texture that is actually used make sure you change the one on the material that you created and not the defaults I changed the default but did not change this Shader however if I now were to make another material which by the way here's a quick tip you can recollect directly on the Shader file and going to create and create new material and it will automatically create the material using that Shader naturally here then update default just because I didn't save the Shader so I modified this one for the camera slices and now if I save the asset and now if I right click there and I create a brand new material and yep now that one does have the new default but again remember what you said over here is just the default what really matters is what is on the material after the material has been created modifying default here does nothing so always keep that in mind in most cases you want to be changing the property on the material itself not the default on the Shader okay let's just clean up both of these all right so let's continue now here we have our Sprite working okay except we don't want to show some bread so let's actually use the proper Arrow Sprite so let's select this one and yep it does work it is printing the Sprite however one obvious thing is that the arrow is not transparent like it should be so let's solve that back in our Shader graph in order to make this a transparent Shader we need to actually go into the graph settings so on the graph inspector go into graph settings and over here you see a bunch of settings that relate to the graph itself and not any selected property so let's go into graph settings for example like I mentioned a while ago you can modify between lit and lit and so on so this is where you would change that you can also appear at multiple targets so you can create a Shader in Shader graph and make it work with the Universe on random pipeline or the high definition render pipeline or the built-in render pipeline all of those are supported through Shader graph now for a goal in order to make this a transparent Shader let's just go over here onto service type instead of opaque and let's change to transparent and as soon as we do look what happens there and if there go it adds a brand new Alpha Channel if we just save the asset right now and open look at that it still doesn't work it's still not transparent basically we made this Shader transparent but now we need to fit in the transparent Channel over here onto the alpha this is the one thing that is different from a previous version of shadowgraph previously you could just feed the alpha Channel over here onto the base color and Shader graph would automatically apply it but in recent versions you need to add it over here separately so if you have any issues with transparency when following some older share graph tutorials always remember this change I covered that along with some other changes in a very useful video so if you're following along some other shade graph tutorials make sure you watch that video to learn what you need to do to update them to the latest version okay so here on the similar texture we already have the alpha channel so we just connect this onto the master Alpha and right there we already see it working let's just go ahead save our asset and here in scene view if there go now we do see our Arrow now one more small thing you might notice that from some angles it's not exactly transparent basically it actually is transparent but since we made this in literature sometimes the light might make the transparent Parts visible one option to solve that is over here on the graph settings instead of making it lit let's make it unlit that would work say up with the unload Shader the transparency is perfect but if you really want to keep it lit then the other thing you can do is just over here play around with these settings you've got smoothness AO and so on and over here you can even modify the workflow mode so for transparency instead of making it metallic let's go with a specular workflow and then over here set the smoothness to 1 and the ambient occlusion down to zero and now if we save this Shader look at that and yep now the transparent parts are indeed fully transparent finally over here on the right side on the mesh render if you want you might want to play around over here with the cast Shadows so maybe you don't want this one to cast Shadows maybe you don't want it to impact light probes and so on okay so with this we have our nice transparent Arrow let's make sure to save our delivery counter so let's go outside back into scenes and let's head on playing and if there you go we have our transparent counter with our nice Arrow now we want the arrow to actually move and doing that is actually super simple going back here in our shadow graph let's just modify default just so we can see the arrow that we want to see so let's select the arrow Sprite okay there's our Arrow now for moving over here on the simple texture we've got an input for the UV the UV is what defines what portion of the texture we're going to grab which by default just gets the whole texture so since this field represents where we're going to grab from texture by playing around with this we can grab different parts so to do that let's just add a standard UV node so here it is this is the standard UV channel so if we connect this then nothing changes everything still renders exactly the same but now we can modify this and to do that we're really just going to use some basic math remember that when working with shaders even though you do see colors everything is really just numbers so uv2 is just number the converges the number the alpha is just a number so visually everything might look like images might look like colors but really in the end it's all just numbers so for example how do we move this texture well it's actually pretty simple we just add a number onto it so we're here on the UVM let's just add an add node so this just adds two numbers together very basic so let's take the regular UV and let's add something on top of it for example we can make a vector two and let's put it on say 0.10 and let's add this one onto this one and now if we drag this one onto the input and look over there on the preview what happens and if they're going like that it moves slightly to the left so if I modify this one put it on zero there you go and that point one on that point two on that and so on so you can see that by modifying here I'm essentially offsetting the texture I'm offsetting on the X and over here I can also offset it on the y basically I'm offsetting the texture by ten percent the UV is a normalized value this is not pixels so that is why point one is ten percent regardless of how big the texture is and if we go way past one then texture essentially Loops back so this is really all we need for our moving Arrow we're going to have zero on the Y and on the X we're going to constantly either increase or decrease that's how we're going to have our moving Arrow so again the only issue here is that I'm modifying this manually we don't want a fixed amount on the Shader instead we want a nice animation so for that we have the very useful the time node this one has various time-based outputs the one that we want for this case is a time which is just the total time this one is constantly increasing since the start of the game by the number of seconds so if you use this over here directly on the end and they're gonna look that texture is constantly scrolling okay so that's great except obviously we have one issue we don't want it to scroll diagonally we only want to scroll in One Direction so for that we can essentially create a simple property to act as our spin so let's over here on the Blackboard let's create a new Vector two column Tower speed property and for the phone let's see if I want to say 0.1 on the x0 on the Y and now if I drag the speed over here onto our Blackboard okay great this is basically a multiplier so we just need to multiply the time by this so let's add a multiply node also by the way quick tip over here on each node you've got a nice little arrow so if you want to make it a bit more compact so if you don't actually need to see the preview so make that and in this case let's take our time multiply it by our speed and then for the output pass it into the end okay so like that now it is indeed moving in this direction and over here on the speed we can play around the values so if we put that 0.5 now it's moving faster and if I put it on the Y now it's moving diagonally put zero on the X and now it's only moving vertically okay so this is really what we want let's just go ahead save our Shader and now let's just select our delivery Arrow material and over here yep we've got the spin if you don't see it make sure they're on the speed property over here you have it exposed so we have the speed instead of moving on the Y let's move on the X and actually like this it's reverse going backwards so over here we can just put a negative value so let's put it on minus one and if there go now the arrow is moving perfectly also here let me make one important note just in case you're using this Shader with a custom texture instead of the one included in the course if you do that make sure that the texture that you use over here I'm using the arrow texture over here on the Arrow import settings down here under wrap mode make sure it is set to repeat if you set it as clamp you might get some weird visuals or nothing at all in order for the texture to constantly Loop and constantly repeat itself that one needs to be set to repeat okay so here it is in game and we have a really nice moving texture for that we created the simple but really nice useful custom Shader definitely go ahead and watch the various effects that I made in the shadow graph playlist this tool is super useful definitely make sure you know how to use it I've used it for making a building effect I've made some nice outlines a really nice wind Shader also a really interesting the sound of effect and even a cool transition Shader just like in the game Hades so this really is a super powerful tool make sure you watch that playlist to really learn how to use it alright so here we'll learn about share graph and created a really nice custom Shader however the delivery counter still only has a visual so let's create some proper Logic for generating and delivering the correct recipes in the next lecture hello and welcome I'm your code monkey in this lecture we're going to build a proper delivery manager that will generate recipes that customers are ordering and validate to see if the player made the right dishes alright so right now we have the player capable of making dishes so for example I can put some cheese cook some meat cut the cheese and then pick up both of them then let's say pick up some bread there you go got a nice cheeseburger and deliver it okay so that works but right now they just vanish on delivery counter so there's no recipe we need to follow no validation none of that so let's add both those things okay first of all let's make our script so let's create a brand new sharp script for the delivery manager let's make a new game object to run it so we need delivery manager attached to script let's make sure to keep things lean so reset the transform and also by the way since we're here let's go ahead and put the plates and delivery counter inside the counter so everything is nice and organized okay great so let's open up this script now here basically we need to Define some sort of list to store all the recipes that the customers are waiting for which of course begs the question what type is that going to be now technically one thing we could do since a recipe is around just a list of kitchen objects over here we could have a list of list of kitchen objects this would be our recipe list technically that would work but that really looks quite dirty instead of having a list of lists we should probably have a proper type for this so let's write some good clean code and Define a proper recipe Script Mod object back in unity let's go inside script knowledge's folder and create a brand new one let's call this the recipe so and over here let's make this a script Mall object so extend script on object make the create asset menu and over here for the films for that that we need well like I said a recipe is just a list of ingredients so just taking a list of kitchen object that sell for the kitchen object SM list okay that's it that's really all the data that we need to define a recipe just to be able to identify them for the player let's also add a public string for the recipe name so just a nice name String okay great now back in the editor let's define so let's go inside the certain objects and make a brand new one for our recipe so and now inside let's create a brand new recipe SL for this one let's call it just burger and over here first of all for the name just name it burger and then for the kitchen object list well to make a burger let's well first let's add some meat and we want some cooked meat we don't want to serve uncooked or burnt meat so only the cooked meat then for a simple Burger obviously we need some bread and that's about it so some bread some meat that's our very basic Burger now let's also make another one so let's duplicate this one and name this one the cheeseburger over here let's name it cheeseburger and lightning place has bread meat and obviously some nice cheese slices so there you go okay we have a cheeseburger now let's also make a mega Burger so something with everything so let's call this one the mega burger and over here for the string name for the Mega burger and for that we have meat bread cheese let's also have some nice cabbage slices and also some tomato slices alright that's our Mega burger with everything and finally let's also make just a nice simple salad so let's duplicate this for a salad let's name it salad and for the salad we don't have any meat we don't have any bread and also no cheese so just cabbage slice and tomato slice that's a simple salad okay so here we have all of our recipes so back here on the delivery manager script instead of making a list of lists of game objects let's just make a list of recipe recipe so and name it the recipe so list this is where we're going to probably see recipes that the customers are waiting for so it's actually rename this let's put it waiting recipe on list okay so the customers are waiting for whatever is inside this list and now we could make this a serialized field then set it in the editor but we don't want to have a fixed list we want to periodically spawn new recipes in order to spawn new recipes we also need to know which ones we can spawn so for that we could add a list of all of the recipes then we could pick a random one from the list and add it over here to the waiting list that would work that's one good approach but since we already did something similar to that various times in this course here don't let me teach you a different approach that sometimes might make more sense for that second approach we just need one thing we need a script more object to hold all of our recipes so let's do that let's do a brand new c-sharp script this is the recipe list scriptable object and then inside this one is going to be a scriptable object let's add the create asset menu and inside we're just going to have a list of recipe so for the recipe SLS so that's it super simple now let's just create one object of this type we can put it inside the recipe as soon as since we're only going to have one so let's make a recipe on Lister so namely the recipient list SL and then over here let's just drag our recipe so we've got a burger a cheeseburger we have a mega burger and finally a salad okay so basically we have a script ball object with all of our recipes and now just for safety since we only want to ever have a single one of these objects a recipe on SSO for this one we can go back here in the script and simply comment out the create asset menu so now back in the game over here we can no longer create another type of recipient list so so just say nice safety thing since we probably only need just one and let's also add an underscore just so it shows up at the top-down list okay great so we have this and over here on the recipe manager we can basically expose that in a serialization so let's make a serialized field make it private of type recipe so list recipe enlisted so for the recipient list so and now here in the editor we just drag that reference alright that's it so basically the difference that we did with this method is over here on delivery manager instead of having a list of all of our recipes we just have a reference to one object and then that object holds a list of all the recipes in this specific use case like I said this approach doesn't really have many benefits compared to just starting the last year but let's say we had another script that also needs a list of all of our recipes if we did that we would basically have duplicate references so this script would have a list of all the recipes then some other script would also have a list of all the recipes and then if you wanted to add a brand new recipe you'd need to add it to all the lists on all the scripts whereas like this any script that needs to know about all of the recipes just needs a reference to the recipe on SSO and whenever we want to add or remove a recipe we just need to update this one object and everything works perfectly that's one of the benefits of this approach where you have a script mode object to hold a list of all the objects of some type personally I find this pattern to be quite useful okay so on delivery manager we have a list of all of our recipes now let's just make a simple timer to spawn them like I mentioned previously in the spawn point logic you could just use Echo routine if you like that core routines can be useful for running timers but personally like I mentioned I do not like Co routines I don't like the pattern they force it to use so over here I'm just going to make a simple flow timer so a private fluid for the spawn recipe timer another one for the recipe timer Max and let's say 4 seconds then we just do a simple and private weight update on update let's count down the timer so time dot down for time and if the spawn timer is under 0f let's reset the timer and now let's basically spawn a recipe so for that let's grab a random one from the list so we go into the recipe list so and grab the recipe as a list then we're going to grab a random one so let's get a random index so random.range between 0 and the recipient list so dot recipes dot count so you get a random one this is going to be a recipe so for the waiting recipe so and then we simply go into the waiting rest PSL list and we add a brand new recipe okay that's it super simple let's just make sure to initialize the list so let's do here a simple awake for the waiting recipes and just initialize it okay so like this it should be working however we're also going to generate recipes non-stop we don't want that so let's define some kind of maximum so let's Define a simple end for the waiting recipes Max let's say we kind of have a maximum of four recipes waiting and then down here when camera lapses so if the waiting recipes only stock count if it is under the maximum then we generate and add it okay that's it pretty simple now for testing let's just set allow here to print the name so debug.log on the waiting recipe so that we generate so let's print out the recipe name okay so let's test so here we are in yep one will spawn right away so we have a solid and after four seconds Yep they're going out of salad and if we wait for four seconds we should have another one there you go a mega butter recipe and finally after four seconds we have yep we have another burger and now no matter how much time passes there should be no more since we're at the limit any uptime pass then no more okay all right awesome so we are correctly generating recipes that the customers are waiting for now it's a logic to try to fulfill these orders so over here on delivery manager let's make a function to deliver a recipe so let's make a public Point make it public since we're going to access this from the delivery counter currently deliver recipe and the recipes are going to be delivered whilst on a point so let's receive a parameter of type Plate Kitchen object and over here the logic is actually going to be pretty simple we just need to cycle through all of the recipes that the customers are waiting for and see if the ingredients on this plate matches the ones on any waiting recipe so over here let's cycle through all of our recipes so let's do before entire zero going through the entire recipe only star count I plus plus okay let's grab the recipe so for the waiting recipe so and we grab from The Waiting recipes on list on this index okay so we have that then first let's do a quick test just to check if the waiting recipe has the same number of ingredients as they are on the plate if not then we already know that it's not valid so over here let's do a quick test SO waiting recipe so let's check the kitchen object that's only it's not count if this one matches the play kitchen object let's get the kitchen object that's on the list and also check the count so over here we know that has the same number of ingredients so this is the first check then we need to cycle through all the ingredients on this recipe and all of the ingredients on the plate and basically see if both of them match so let's first cycle through the ingredients on the recipe so for each kitchen object as so let's call it the recipe kitchen object so in the waiting recipe so let's go into the waiting recipe and get the kitchen object list okay so here we are cycling through all ingredients in the recipe then we need to cycle through all the ingredients on the plate so let's do another cycle for the Plate Kitchen object SL and we're going to go inside the Plate Kitchen object get the kitchen object that's on the list like this so here we are cycling through all the ingredients on the plate okay so now here basically we need to see if this ingredient that we're cycling through if this one matches the ingredient on the recipe so here we check if the Plate Kitchen object does so if this one matches the recipe kitchen outlet if so then the ingredient does match so in order to keep track if it does match over here before we cycle through all the ones on the plane let's define a bone for found or ingredient found let's default it too false and over here if we have match then this one becomes true and by the way over here we can also break out of the cycle now if you're not familiar with break basically this is going to break out at the for each so let's say the plate has 10 ingredients and the second one matches when this cycle gets to the second one it triggers a break so it no longer goes through the remaining eight so basically it breaks out of the cycle so keeps writing some code right down here okay so we cycle through all of the ones on the aggressively then recycle through the plate and if we do find that ingredient on that plate then we have an ingredient found so over here if we have a not ingredient found then over here that means this recipe ingredient was not found on the plate so if that happens then essentially over here we have a phenocate so the ingredient that this recipe requires is not on the plate so let's go up here when we have the same number of ingredients let's define a Boolean called the plate contents matches recipe let's see found it to true and over here if we don't find at least one of them then the plate contents do not match the recipe and afterwards we can check this bowl again so if this one is true that means they all match if just one of them does not matches then this one won't be false so over here we know player delivered the correct recipe so over here on let's do a quick debug down log and print out a message and after we do let's also do a return so we stop the rest of the execution so basically if we find a waiting recipe that matches we don't want to keep going and also here if we do find it let's also remove it from the list so let's go into waiting queue remove at and remove at this index okay so we're going to remove this recipe but if this doesn't happen then it's going to be keep cycling and it's going to cycle through all the recipes so basically if it reaches the end this far then basically no match is found so the player did not deliver a correct recipe so let's do another debug in here okay so this is done for logic it looks a bit complex but I hope this was easy to follow when we see it in action It all becomes a bit more clear so all that's left is just calling this function from the delivery counter so let's do that over here on the delivery counter it accepts plates and destroys plates but before we destroy let's go into the delivery manager which means we need to access a reference so again we could add a serialized field or in this case it makes perfect sense to make this a Singleton so let's make it here public static of type delivering manager call it instance with a public get and a private set okay then over here on awake let's set instance equals this all right so now over here on the delivery counter we can go into the delivery manager access the instance and deliver our recipe and pass in the Plate Kitchen object okay that should do it let's test all right so let's look in the log to see what they are waiting for so there are two cheeseburgers waiting another Mega burger and a cheeseburger so let's make a cheeseburger to deliver so first of all let's cook some meat let's slice some cheese let's pick up the meat before it burns pick up the cheese and we just need the bread okay this is a valley cheeseburger so let's deliver it and if there go the players delivered the correct recipe okay great now let's deliver something that nobody asked for let's say just some meat actually let's burn it just for fun all right so there we have a bunch of charred meat so nobody really wants this but if we deliver if their yield player did not deliver a correct recipe alright awesome so over here everything worked we have a bunch of recipes being generated and then we have the logic so that when the player delivers something it checks if the players delivered something correct or incorrect so everything is great all that's missing is obviously some nice UI so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to create a nice UI visual to display our waiting recipes okay so our delivery manager is already working we are randomly spawning some random recipes every once in a while now instead of looking at the console let's add a proper UI so for that over here in the editor let's go inside the canvas and by the way let's click on the button to unlock the canvas and this is actually the first time we're using the Ragnar canvas quite a while ago we just created it we didn't really set it up so let's quickly do that for the render mode this one is meant to be a regular UI so let's leave it on the screen space overlay then over here on the canvas scaler instead of constant pixel size let's go with scale with screen size then for the reference resolution I like to use 1920x1080 and finally unlike to fully match with the height basically this means that objects in the canvas will be scaled if the height changes for example let's add inside just a quick UI image just a test let's look in the game View so there you go there's the image let's just put on a different color okay so there's the image and note how if I modify the aspect ratio here so let's say I put it on 5x4 there go the horizontal side of the window change but note how the element was not scaled so I can put it even on free aspects so really wide and does not change the size whereas if I modify this if I modify the vertical size the image does indeed get Scaled up or down personally I like the setup because means that I only have to worry about positioning things horizontally if the vericon part gets changed everything gets automatically scaled okay so great so over here let's go back into 4G all right and let's get rid of the image all right back in the scene view let's quickly look at the canvas so we can select the canvas press the F in order to zoom out and also we can press the 2D button up here to go into 3D mode okay so here's our nice UI now inside the canvas let's create them to game object call it the delivery manager UI then in the inspector let's make it stretch to occupy the whole thing so let's put zero on everything okay so this window now occupies the entire screen now inside let's do just like we did a while ago for the plate icons meaning let's make a template that we can then clone but let's also put those templates inside of a container so first of all let's make the containers so a new empty game object of currently just the container the reason why I'm going with this approach is because I also want to have other objects outside of here if you remember how we did with the templates we can actually go there and see so let's go inside the prefabs inside the counters actually it's on the kitchen objects let's go inside the plate over here for the template basically we use the play tokens UI this main canvas as the container but if you remember how we did that in order to make sure we didn't end up with duplicate icons we always destroyed the previous one when we spawned a brand new one so every time we were cycling through the children of this object in order to destroy all of them except the template so over here we're going to use a container so that we can apply the logic only to the children of the container and that way we can have other objects outside of the container for example outside of here let's say we want some nice text just saying recipes and waiting so on delivery mansion let's make it a challenge down let's go into UI and let's make a text text mesh Pro and this is the first time that we're using text mesh Pro so this window pops out it's actually import mesh Pro Essentials okay just let it import okay that's it we don't need the examples are extras so let's just close this window and over here on this window let's name this the title text let's set the text to something like recipes waiting let's put it up there on the corner so let's anchor it on the top left corner also for the text I like to put it on a width and height of zero but of course that makes the text really vertical so then down here on the wrapping let's just disable it so there you go looks like that and let's put it over there on that corner now in scene view we are seeing things different so if you want to see what this looks like just go into the game View and over there yep we do see the recipes and let's just make it in bond so there you go just some nice text okay so that's our text and then for the container let's make inside the delivery template so let's create an empty game object let's go with the recipe template and for this one we're going to want to Anchor it to the top left corner so with the template selected over here in the inspector let's click and we want to click up here however we also want to set the pivot so let's make sure to hold down shift in order to set the pivot over there okay great that's exactly what we want so we want the template right on the corner then let's give it a size of say 250 by 100 okay now inside template we just need two things we want to name the recipe as well as the list of all the ingredients although before that let's actually make a nice visual for the background so a new UI image for the background let's make this one stretch to occupy the whole thing let's put everything on zero okay that's the background let's put it on a black we're just a little bit lower Alpha okay that's good then for name let's make a text field so inside the template let's create another text call it the recipe name text then over here let's put it a bit small so on the font size of maybe just 20 let's put it in bold and let's also again put the width and height of 0 and over here make sure to disable wrapping okay so that's the text so we've got it up there let's just anchor it to the top left corner okay great over here we can change the name to recipe and then what we need is the icons on here and for that we're going to do pretty much the exact same thing that we done on plate but before we do that logic let's just get this basic setup working so let's just position everything so first of all the container for all the templates let's anchor it on the top left corner and let's push it all the way over there and for positioning them let's use this time the vertical layout group so inside let's duplicate the template just to be able to see them okay so that's pretty much we want we can actually set the width and height both to zero and let's set the spacing to something like 30. okay so that's our basic UI now let's make the script to run this so over here in our scripts let's create a brand new C sharp script for the delivery manager UI let's go into the parent game object and let's attach your script let's open okay so now here first we need a field for the container another one for the template so let's do a serialized film private transform for the container and another one for the transform and this is going to be the recipe template then let's do pretty much same thing we did previously so first of all let's actually go on a way in order to hide the template so game objects set active into false okay so first we hide the template then let's make an update visual function so private void update visual and for updating we're going to do the exact same thing that we did so first let's cycle through the container and destroy everything except for the template so do a 40 inch transform child in the container and if the child is the template if so then we're going to continue and if not we're going to destroy the child game object okay so we have the cleanup now we need is the second through all of the waiting recipes so that means that over here on delivery manager we need to expose our waiting recipes on list so let's go down here make a function to do that probably going to return a list of recipes so get waiting recipe so list and we just return the waiting recipes on list okay great so now here on the UI we can now go into the delivery manager xsc static instance in order to get the waiting recipes on list so let's cycle through this so do a 40 inch for each recipe so recipe so in the waiting rest vsl list for each of them let's instantiate and let's spawn our recipe template spawn it inside the container and then we just need to set this to enabled so let's read the transform for the recipe transform we grab this one grab the game object and set active into true okay so like this the only thing missing is the text but that's okay for now let you see where we're going to call this function to update the visuals and as usual we want to be smart and write some good clean code so let's not do the dirty approach of just updating this on every single update instead let's only call this function when something actually changes so over here on the delivery manager let's just make some simple events so if I'm like event event handler let's go on recipes fund and another one call it on recipe completed and actually as soon as I add the event handler which also add the using system now here we have an interesting thing we've got a nice namespace Collision it's telling us that random is an ambiguous reference between Unity engine now random and system.r random that is because both these namespaces Unity engine and system both of them have a class named exactly random so the code here does not know which class we're trying to use to solve this component we really just need to be more specific in this case here we want to use the UNT engine version so let's just write the full name Unity engine.renom and yep that works okay so now let's fire off the events so first of all the own recipe spawns over here when we spawn a recipe let's invoke this event so this is ventar is not empty and let's also get rid of the log we know we need that okay now we could also add the wedding recipe on the event artist but in this case we don't need it just firing the event is enough and then down here when the players delivers something if the player delivers the correct recipe we remove it from the list and then let's fire off the event so on recipe completing let's invoke with this and event rx.mt okay so we have the event and down here we also don't need analog okay so that works and finally over here on the delivery man GUI let's just make a private void start on start going to the delivery manager access the static instance and listen to both these events so they spawned and let's also listen to the other ones the library manager instance on recipe completed when either of these work let's just go and update the visual so just like this let's also rename this because again instance doesn't sound like a very good name let's actually rename this to only remanager and same thing up here by the way I'm using the visual studio shortcut control RR in order to rename this to delivering manager and finally we also need to update the visual OnStar just make sure the previous ones do not show up okay that's it so like this it should be working we should be able to see no Visual and then as more our spawned we should be able to see each one being spawned until the maximum so let's see just over here in the UI let's make sure to drag the references so the container and the template and let's hit on play and okay right away actually it spawned one recipe it spawned instantly then after four seconds there you go a second one and after four seconds we should be able to see yep another one now four more seconds and we should see the final one and now no matter how long we wait it should no longer spawn anymore and yep that works alright awesome so the basic logic is working now let's handle the proper Logic on the template for that like I mentioned previously one approach would be over here you could go and do a transform.find the actual recipe name text then get the text mesh component and set it that would work but like I mentioned previously that would be very dirty not good at all we should avoid using find at any time and we should also avoid the individual logic from the total logic so let's do it properly and make a proper script to handle each spawn template so let's create a brand new c-sharp script call this delivery manager single UI single just because it refers to a single recipe and also right now we already have quite a few UI scripts so let's organize our project again so let's organize new folder for the UI and inside let's put all of our UI scripts so if we manage is single this one deployed icons white icons and the progress bar so let's put all of these nicely organized in the UI folder okay so with the script let's go into the recipe template and attach the script now let's open and over here let's begin by adding a film for our text so a serialized field and over here it's also very important for the text we are not using the text inside DNT engine.ui this is the in Legacy text it is not text mesh Pro so this is not what we were using instead we want to use text mesh Pro U going which is inside TM Pro so we need to go up here and add using TM Pro and now we can use this type and also make sure you're using text mesh Pro ugui and not text mesh Pro this one also exists but don't mix these two these are two very different types if we go over here in the editor and if outside the canvas if I just create and create new 3D object a new text object if I do that then if we look over here in the inspector we see this one as a type text mesh Pro whereas for the ones that we're using inside the canvas if we unlock this is text mesh Pro it's a UI text so these are the two different classes within text mesh Pro you have text mesh Pro and text mesh Pro ugly we're working on the UI so we want this one okay so we named this the recipe name text okay that's it over here in the editor let's drag our reference all right so now this group let's make a function to set the recipe so a public void and let's call it set recipe SL they're going to receive a recipe so recipe so then we just go into the recipe name text and we set the text to recipe so dot recipe name okay so that's pretty much it now over here on the Y script when we instantiate our recipe transform let's get component of type of our delivery manager single UI and call set recipe so and pass in the recipe so okay so let's see if the name shows up any operator wait does show up so we can see that we generate a cheeseburger recipe and right now a mega burger recipe okay great so all that's left are the icons on here so like I said that is going to be yet another usage of our template pattern so inside the recipe template let's create an empty game object currently the icon container and then inside that let's make the template and template is just going to be an image so we can just create an image to our way called the ingredient image let's scale it with a size of 40 and 40. let's put a image by default just like that and on the icon container let's put the width of zero height of zero and let's put a horizontal layout group put it over there on the left side and we can create a bunch more just to see how it looks okay so that's pretty much it now over here on the single script let's add a serialized field private transform for the icon container another one for the icon template then we do the same thing as usual so when we set the recipe so let's first of all clean up the container so let's do a 40 inch transform child in the icon container and if the channel is the template then we want to continue and ignore it if not we want to destroy the child.game object okay so that's the cleanup and then let's do a four inch kitchen object as so in the recipe so dot kitchen object.zone list second through all of this let's instantiate our icon template instantiate it inside the icon container so this is going to be the transform for the icon transform then as usual we need to go into the game object set active in order to enable it and also let's go up here make a private way to wake and on awake the icon template game object let's disable it okay we don't want the template to be visible okay so we instantiate the template we set it as active then since this one just has an image we can just do a get component of Type image that's image not image conversion so image so it's this one the one inside Unity engine.ui so let's get this image and let's modify the Sprites and set it to this kitchen object so that's right okay so that's it that should do it let's test over here in the editor let's just go into the template let's drag the container reference and the template reference and let's also rename this instead of ingredient image put icon template just to be a bit more clear and we can get rid of the other ones or leave them doesn't really matter okay great so let's hit on play and see and yep right away does work so we can see a burger is composed of a burger and a bun a satellite yep there you go some sliced cabbage and sliced tomatoes then cheeseburger same thing as the burger with some cheese and then another Burger let's just deliver until we see the mega Burger so let's deliver a cheeseburger let's cut it get this get some bread place it in there pick it up before it burns that's a cheeseburger so that one should vanish and if they're good does vanish let's see something else not cheeseburgers so let's keep doing until we get a Mega burger just see that everything works so let's deliver a regular burger okay now let's deliver a regular salad okay just pick up like that like that and drop it okay let's see any up there it is the Mega butter all right great so the visual logic is fully working and the delivery logic all of it is working so I can deliver the right recipes and get rid of them from the recipe waiting list and more are spawned every time here we can see the name of the recipe as well as all of the nice icons okay so with all this our game is really taking shape everything is very close to being done one massive thing we're still missing is an obvious one which is sound so let's do that in the next lecture hey again quick intermission you're almost at the end so once again congrats for making it this far this is the second secret call out go ahead Post in the comments a timestamp and a nice monk Emoji it won't be fun to see how many people make it to this point by now you already know about the website I hope it's been very useful to you and you already know to ask any questions in the comments if you need help with anything so that's life for me to say right now is thanks for watching the course so far and I really hope you've already learned a ton there's only a bunch more lectures until we get to the final polish game so let's continue on the next lecture hello and welcome I'm your code monkey in this lecture we're going to add some audio to our game starting with a really nice music track okay so our game is already looking pretty good but everything is still way too silent so let's begin by adding some music adding this is actually extremely new in the included assets over here inside the sounds we've got a really nice music track I hired a musician to make this it sounds really good it's a seamless Loop so to add to our game it's going to be super simple we just want a constant never-ending Loop so let's begin by creating an empty game object call it the Music Manager let's reset transform keep things organized and let's add a component and we want the component an audio Source here it is this one like name implies this one acts like a source of audio you will note how by default on the main camera down here it already has an audio listener so the source plays some sound and The Listener listens to it now for here we just need to set these fields so for example on the autoclave let's make sure to drag the music audio okay great next over here and let's enable and play on a wink we wanted to start playing right wing and for this track we do want to enable looping okay great then for priority basically UNT has limited to how many sounds can be played at once if you play too many then some sounds won't play and which ones do you play is all based on priority we always want the music to play so let's put this one on Max priority then for the volume later on we're going to make a proper option screen to handle this but for now let's put it on something like 0.4 or 0.5 just make a nice background track then we have here the spatial blend for this music track we wanted to play the same regardless of where the camera is so let's make this all the way if only a 2d sound okay that's it we don't need to play around with any of the other settings and just like this if we are on play any up there's the music now if you're not hearing anything make sure that on the game view first of all that the game is actually selected make sure the scene is in Focus so over here I can move around so the game's in Focus then on game view we are on the top right corner make sure this sound icon is toggled if not then everything is muted and also again make sure like I mentioned on the main camera that it has the audio and listener component with all that yep you should be able to hear the music now this song is playing and it won't Loop forever just like we wanted personally I really like how it sounds I'm really happy with what the composer made it perfectly matches the E5 of the game so it really is this simple to add some music to the game let me just point out one thing also related to sound one of the things you can make is an audio mixer so for example on the project files let's create a brand new and let's find over here the audio mixer so there you go here is an audio mixer then you can double click to open up the audio mixer window and then over here you have the masternode and then you can create multiple groups so let's create a brand new groove for something else and then you can play around over here with the effects with the volume all kinds of things all kinds of effects everything then for each sound where you have the audio Source over here note how you have an output and for this output you can set it to play on the message so it plays on everything or set it on just one individual group so with this you could assign a group to one individual type of sound effect or the music or so on maybe you could even have your music split into multiple stems so there's a lot you can do but for me I'm not an audio engineer audio is probably the part of game development that I know least about I just stick with the absolute Basics but if you want to learn more definitely look into the audio mixer this is an extremely powerful tool but like I said for me I don't know how to work with it so I'm just going to stick with the basics so on the output let's revert back into none close the audio mixer and get rid of this and there it is music is playing and the wrong sounds really nice alright so here we very easily added some music to our game this lecture is actually super short because it is generally that simple now the next thing that we need is not going to be a little bit more complex and that is adding sound effects so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to add some sound effects for our game okay so previously we already added some really nice music now let's add a whole bunch of sound effects in the project files if we go inside the assets over here we've got all kinds of sound effects recently I heard the really nice sound designer to make all of these and I think they all sound really great so let's add them to our game now when it comes to sound effects there are two main ways to play a sound one is just like we did for the music so we can create a game object at the audio Source component and play it that's one approach but that basically requires pre-preparing the sound objects so there is another simpler way that just requires one line of code so let's begin by making a Sound Manager game object so a new empty game object for The Sound Manager let's reset the transform now let's make our script so let's go in the scripts folder create a brand new c-sharp script for The Sound Manager let's attach the script and open okay so now here let's make a function to play Simple sound so let's do a private void just call it play sound and over here the way we play sound through code is actually super simple we just go inside the audio Source class and in here there's a static function play clip at point this as you can see it takes an audio clip a vector 3 for the position and finally a volume so basically it won't play that sound on that position by default TNT already has 3D sound so if you play the sound on the left or the right side of the camera it won't play in the correct place also for the volume the further away it is from the camera the lower it will be and if we don't want the 3D sound we can just play it directly on top of the camera position okay so in this function let's receive our arguments so for the audio clip it's going to be our audio clip then let's receive the vector 340 position and let's also receive an optional one for the volume let's just default this to 1f okay so here we just pass this in into our function so the position and the volume okay great so now let's call this nice function and for example let's start with a simple one so let's start with the delivery sounds so over here on the delivery manager script down here we have the logic for delivering a recipe and over here we know when we completed a successful recipe or when we failed and the player delivered a wrong recipe so this is where we want to play some sounds and again here we have yet another very important clean code question we could definitely call the play sound function directly from here that would work but of course that would make this class tightly coupled with The Sound Manager for a simple game on this scale that approach can work just play sounds directly from the logic code however again to make things properly we should really separate the logic from the sound just like we separated in logic from the visuals so instead let's not call the sound directly from here instead let's make two more events so let's make one on recipe success another one on recipe failed okay so now let's fire off these events so over here we have the success so on recipe success and if we get down here then we have a fail so on recipe fail okay great we have two events now back here on The Sound Manager we can just listen to those so let's do a start go into the delivering manager access the instance and listen to the on success and on failed events let's listen to that one delivery manager instance on recipe film listen to both of these again let's write some good clean codes so let's rename this one instead of instance let's put it delivery manager and same thing on this one also name it correctly delivery menu okay great so now when you have this we want to call and play sound and now I want to pass in a reference to the recipe film sound so technically one approach would be appear to add a serialized film for an audio clip that would work but since we've already done that so many times in this course here let's use a different approach that I also like to use let's create a scriptable object to home the reference to all of our sounds so similar to how we Define the script object on all of our recipes let's just comment this out just make sure the code compounds okay great so back here in the editor let's make a new script more object type so let's create a brand new c-sharp script for the audio clip refs script long object now here let's make this a simple scriptable object with a create asset menu okay so now for the fields if we unlocking the S over here the audio design that I hired actually made several variations for each sound so we've got multiple chops multiple delivery fails and so on so back in the code here instead of storing a reference for a single audio clip let's store an array for all of them so we have the chop then we have on the other Solutions and all of the references so there's a job there's the delivery fail then we have delivery success then we have footsteps then the object drop then the object pickup then we have the stove Sizzle although this one is just one then we have the trash and finally we have the warning alright so these are all of the sound references we're going to use back in the editor let's just create the object so on the script mode objects let's create a brand new one let's make it of audio clip per episode just name it audio clip refs so and over here let's just write the references so let's use that quick ENT tip in order to unlock the inspector now I can select all the chops and drag them all the delivery fails drag them it's only re-success drag it then for all of the footsteps after that are all of the object drops then the pickups then we have the sizzle which is just one finally we have the trash and the warning okay those are all the references so our script on object now has all of the data we need let's unlock the inspector okay and back in the code here on The Sound Manager let's make another version of this function so let's make one play sound except instead of receiving an audio clip it receives an array of audio clips then basically we just call the other function so we call the other place on function and pass in an audio clip from this array so let's actually rename this so audio clip array and let's pass in an audio clip from here so do a simple random.range between 0 and the array down length pressing the position and the volume okay so just like this now we need is a reference to our suitable object so it's generalized film private of the audio clip refs SL okay we have this then here in the editor and let's just assign the reference so the audio clip refs okay great and over here when we have the recipe failed let's go into the audio clip refs and let's pick up this one instant delivery fail and then the other one is going to be delivery success for the position let's just default to the camera dot main transform that position so like this it sounds like exactly on top of the camera okay so let's test and see if it all works okay so here we are and let's do a wrong delivery now quick warning if you're following along or if you're just watching the video this sound will probably be way too loud but let's test so if I just pick up the plate and I just deliver an empty plate yep there you go there's the sound and now if I deliver a correct one so someone wants a salad so let's cut a nice salad chop that chop this pick up the plate pick up that one and that one don't be the correct salad any of that I go with those were all right great so the sound effects work they played perfectly but they're a bit too loud basically that's because these sounds were designed to be played in the world rather than on top of the camera so when we play the sound let's actually play it on the position of the delivery counter here is the delivery counter script and based on our design we're only going to have a single military counter so we can just make this a Singleton so as usual public static of type on Livery counter call it instance where they probably get and a private set then on privatoid awake let's just set the instance equals this okay so over here on The Sound Manager we can just grab delivery counter delivery counter and we just go into Library counter and grab the static instance and then for the sound position we can just go into delivery counter access the transform that position okay so just like this on that one and on this one okay so it says now it shouldn't be as loud okay so here we are and let's do a wrong delivery any hope it does work now let's be successful delivery so let's make a nice cheeseburger so grab some cheese slice it grab plate just need some bread and delivered any of there you go it worked all right awesome okay so this is really it this is how we're going to play our simple sounds now there are some that are going to require more logic like the footstep sounds and the stove Sizzle but first let's begin by adding the simple ones so let's begin with the chop sounds this is super simple we just need to go over here onto the cutting counter and actually we already have the uncut event that we made previously this was used to spawn the visual so we can also use it to spawn these sounds however there's actually one difference we're going to have multiple cutting counters and this one as you can see this one is not a static event meaning each different counter is going to have each list of listeners and we really don't want to have to subscribe to every single one of the counters individually so what we can do is instead of making it a regular event that belongs to each instance of a cut encounter we can make a static event which won't belong to the entire class but we still want to leave this one just for the visual so let's do another one a public static event event handler and let's call it on any cut basically for any static events that belong to any object type I like to add the keyword any we're going to fire this event when any cutting counter is going to trigger a cut action so where we fire this event is exactly the same thing so over here we've got the uncut and let's do the exact same thing so on any cut with this an event R is not empty okay so we have our nice static event and over here on The Sound Manager let's listen to it so let's go into the cutting counter again we're going to access through the class name and let's listen to the on any cut event and over here let's just play the sound so let's play the sound let's go inside the audio play prefsl and let's grab the chop sound then for the position we want to know who fired this event and by following the c-sharp standard over here we already have the object sender so we know this was the object that fired this event and we know this is going to be of type cutting counter so we can just get cutting counter cutting counter and we just grab the sender as a cutting counter okay so we have this and then over here very simple access transform that position okay that's it great that won't play The Cutting sound on that position on that cutting counter okay great now let's handle the player picking up something and for that let's go over here onto the player class and the way we set up the kitchen object parent system is actually already perfect for this down here we have a function so if we scroll down Yep this function set kitchen object this one is called whenever the player receives a kitchen object which means really when the player picks up something so if this kitchen object is not known then that means the player picked up something so let's do that so up here and let's make the event so a public event event handler call it on pick something and then down here just to be test so if the kitchen object is not known so if the player did pick up something then let's just fire off this event so just view our usual invoke with this an event RX rmt okay so that's great then on the sound management let's just listen to it so let's go into the player Quest let's access these static instance and let's listen to the on picked up something event and again let's rename this to a proper name so player on pick something and over here let's just play the sound and for the sound go into the refs and grab in this case the object pickup and for the position let's just go player dot instance and gravity transform that position okay that's it next for item dropping now we can only drop items on a counter so over here we have the base counter class and again we have the same thing so we have the set kitchen object and again the same thing as with the cutting counter we don't want to be required to listen to every single counter we just want to listen to one event so let's make it up here so if I'm like static event of type event handler and let's name it on any object placed here and then down here when we have the set kitchen object we do the usual if kitchen object is not known if so then let's fire off this event okay great and on the song Imagine let's listen so go into the base counter on any object placed here when that happens play the sound then let's go into the other top prefs and this one is the object drop so that one and for the position let's do the same thing we did so we cast the base counter equals the sender as a base counter and then we go into the base counter and let's grab the transformed up position okay so we just need one more special counter type here we have the trash counter and this one it never really changes the parent it just destroys the object it's over here on the trash counter itself let's fire off an event but again let's make it static even though we're only going to have one trash but make it Saturday just to be able to support multiple so public static event Handler on any object trashed and then over here just fire off this event so invoke with this and eventar is not empty okay so now if we go into The Sound Manager and over here once again the trash counter on any not the on any object place but on any object trashed and on this one let's do pretty much exactly the same thing so let's copy this the sound is going to be the trash sound instead of a bass counter we could just cast it to a base counter but let's make it proper so let's make a trash counter as a trash counter and this is a trash counter okay great that's it so these are all of our basic simple sounds as you can see all the logic is super simple so let's test and see if it all works okay so first of all let's pick up an object so if I go into a container and I pick it up and if there you go there's the sound now if I drop it somewhere and if there's a sound now for the trash pick it up drop it on the trash anyhow there's the trash down okay great then also let's check out the cutting so if I pick up some cheese drop it there and cut and if there go got a really nice cutting sound okay so far so good now let's handle the more complex ones starting off with the stove for this one the sound is meant to be on looping but only when the sub is on so we don't want to just play once but play and stop playing depending on the state of the stove so for this one instead of spawning the sound through code let's actually spawn it on the object itself so let's go inside the stove object let's go on the stove counter and open up the prefab and inside this prefab let's create a brand new empty game object name it sound let's reset transform make sure it's on zero zero zero okay great now let's add an audio Source component and for the auto clip let's use the pan sizzle let's make sure to not talk on play on awake but we do want it to Loop and let's also make it a 3D sound okay so that's the basic setup Now to control this let's make a script so let's go into our scripts folder and let's create a brand new c-sharp script come with the stove counter sound let's attach the script over here and let's open it so now here first let's grab the audio Source component so we've got a private audio source for the audio source and just go on awake and audio Source sequence get component of type audio Source okay then we're also going to need a reference to the stove counter so let's uh appear a centralized film private of type stove counter for the stove counter then back in the editor let's drag that reference all right now on the stove counter over here we already have the states and we have the on-site change event again the same one that we use to modify the visual so on the sound lets you pretty much examine the same thing over here let's do a private void start and on certain let's go into the stove counter and listen to the on stay changed event and basically when this changes we want to check if it's frying or fried if so then we want to play the sound if no then we don't want to play it so let's define a ball call it play sound and we're going to play if the state equals we are frying or the state equals that it is currently fried and about to burn Okay then if we have a play sound then let's go into the audio source and comp play and if not then let's go into audio source and call pause all right so that's it pretty simple let's just make sure to save our prefab go back outside and let's start on play and okay four stars there's no sound playing now if I pick up some meat and I drop it on there and if there go there's a sizzling sound and continues going and now it is still sizzling but if it burns it should stop so if I go and if there go the sizzling soundstomp all right awesome so let's take this one out let's actually trash it now let's pick up another one let it cook and once let's go pick it up and there you go the sound of the Stomp all right awesome so we just have one more final sound remaining that's the footsteps by the way the warning sound is going to be added during the Polish lecture for the footsteps we want very much the same thing that we did on the stove so we're going to want a script to handle that logic but this time we don't need an audio Source on the player we're going to use the same play Method as the other ones let's just make a script to run the sounds so let's make a new c-sharp script for the player sounds let's go into the player game object and attach the sound okay so here let's first grab the player reference so private player player and on private way the way let's get the component of type player and assign it to the player okay then for the footsteps basically we want to play them every certain amount of time so let's do appear a private Cloud for the footstep timer another one for the footstep tower Max and let's say you want to play say 10 times per second then we do a basic update and on update footstep timer countdown by time.com time and if the footstep timer is under zero then let's reset it so set it to the maximum and it's in here that we're going to play the sound so now here we have two options we can fire an event here and we can listen to it on The Sound Manager so exactly the same thing that we've been doing previously or we can just trigger the sound directly from here doing that will mean that this class is tightly coupled with The Sound Manager usually we want to avoid tight couplings however in this case the player sounds class this one is really only meant to exist alongside the sound manager so in this case it's perfectly fine to totally coupon them so let's play the sound directly from here which means we need a reference to The Sound Manager we can make a serialized field or just make this a Singleton so let's do that so a public static type Sound Manager name it instance where they probably get any private set then on private void awake we just set the instance equals this okay so then over here we can just access it so just go into the sound manager access the instance and we call play sound which we actually need to make public however this function also takes a reference to the audio clip array so that means we need a reference to the audio clips so again we have multiple options we could add over here on the player sounds at a serialized film for the footstep sounds or we can just make a specialized function over here on The Sound Manager both options can work just fine let's go with the second one just to be different so just make here a public void play footstep sound we're just going to receive a vector 3 for the position and then we just call play sound let's go into the audio clip refs ASL and let's pick up the footsteps and play it on this position and let's also receive the volume just appear a fault for the volume okay so that's right now we just need to call this function it's over here on the player instead of calling play sound let's go on the other one play the footstep sound then for the position that's the player transformed that position and for the volume I just exposed the volume just in case you want to make the footsteps a bit more sound or not but for now let's begin with one F and then see if that's waiting around as usual instead of using magic numbers let's define a fluid for the volume put it at 1f and over here use the volume okay great however you might be noticing an obvious issue here right now this is going to play non-stop obviously we don't want to do that we only want to play footstep sounds if the player is actually moving so this pre-semble we just need to ask the player if it is moving and we already did that so player is walking so if the player is walking then you play The Sounds if not we don't okay that's it so let's test so here we are and if I'm standing still there's no footsteps okay that's great and as soon as I move yep there you go we got some nice WhatsApp sounds all right great so with all that we added all of our sounds now here note how we mostly use this method of going into the audio source and using the play clip at Point function this one is great because it is so simple but it does have limitations specifically with regards to all of the options if we look on the audio Source component here we have all these options so you can use an output use an audio mixer like we saw in the previous lecture we can play around priority play around the pitch make it 2D or 3D play around over here with how the sound falls off so tons and tons of options that you can't really access if you use that simple function so one approach if you need these options you could make each sound a prefab so make a prefab for each different audio clip and then instead of calling that function you would simply instantiate that prefab to spawn that audio so if you have lots of options depending on how complex you want your sound to be but for a simple game and for simple sounds this one line of code is super simple alright so here we have added sound effects to our game that component with the music that we had previously already makes everything sound so much more alive it's really starting to look like a proper game the one thing we still don't have is some kind of game start and game and scenario so let's have that in the next lecture hello and welcome I'm your code Maki in this lecture let's add a simple and beginning state to our game so right now we can play the game of the mechanics everything works perfectly and it's all been implemented however in the beginning of the game it just starts right away as it loads there's no start no countdown no time for the player to get ready someone sort that out with a simple countdown let's begin by making a general game manager script to handle all of our general game States so let's create a brand new c-sharp script and now here you could use the name game manager so you could use this name however for some reason yantian likes uh this custom icon when a script is named exactly game manager personally I don't like this I don't want it to be a different icon I want this script to look and behave just like any other one of my scripts so personally I don't like this but if it doesn't bother you then go ahead use it doesn't really change anything just a visual but in my case I prefer to give it a different name so sometimes I call it game Handler or other times just something related to this game like for example the kitchen game manager and just like that it won't have that custom icon just need to go inside and rename this to Kitchen game manager okay save the script and all right now let's make a game object to run it so a new game object with the same name let's attach the kitchen game manager and reset transform okay let's go now here we're going to Define all of the various game states that our game can be in so for that let's define an enum so a simple enum call it state and for the various States let's say we are first of all waiting to start then we are on countdown to start then the game is playing and then we have a game over okay so these are our states let's do a private void awake and on the waiting list of the state so we need to store a state for our state and on a week we set the state equals and let's begin on waiting to start by the way the point with this waiting to start say it will also be very important in the next video covering multiplayer basically we're going to wait until everyone is connected before we start the actual countdown but over here for now we're just going to wait a little bit on the waiting to start then we're going to trigger the countdown and then after some time trigger the game playing state so pretty much all of these states are going to be time based so let's make a simple timer so a private float for the waiting to start timer let's begin on something like 1f so we just wait for one second then let's make a private void update and let's make a state machine just like we've done previously so do a switch on our state in case we are on state DOT waiting to start if so then let's go into the waiting to start timer count it down by time dot Delta time then if the waiting to start timer if it is under zero if so then let's move into the state equal state DOT let's go into the countdown to start okay so that's it and the other states are going to be pretty much exactly the same so let's just copy this so we have the winning start and the countdown to start then we have the game playing and finally we have the game over and that one doesn't have anything so just like this like I said we could reuse the same timer but let's write our code nice and proper so let's make different timers for each so let's make three timers so we're going to have the countdown to start timer so countdown for this one let's see Fallen two three so we're going to wait three seconds before we start and then the game playing timer and for this one let's put it something short just for testing so let's put it just test and then down here let's just use them so on the countdown let's count down this timer on the game playing count down this timer when the countdown ends we go into game playing and when the game playing ends we go into game over alright so that's our super basic state machine just a bunch of timers super simple let's do a quick look just to see so over here just say debug.log and let's just print out the current state okay so just like this let's test and yep right away we are waiting to start after one second going to countdown then after three seconds go into game playing and now if we wait for 10 seconds after 10 seconds we should be able to see just a little bit and yep there you go we've got our game over okay great all the logic is working although we actually didn't change anything technically the game right now is on a game over but everything still works the same experience only so I can still play I can still do everything so let's sort them when we are in any state other than the game playing State we don't want the player to be able to interact with anything we want to leave it movement because that's usually nice and fun but we don't want it to be able to interact pickup objects or do anything so let's do that basically over here on the game manager let's just expose the function so public pool let's call this is game playing then over here pretty simple just return if the state equals state DOT gameplay that's it so now we can go into the player script so over here on the player script let's go down into the interaction function so over here we've got the interact alternate and the interact and on both of these basically let's just ask if the game is in the game playing state if so we want to interact but if not then we don't want to do anything so to access the game manager we could add a pure serialized field or as usual let's just make a nice Singleton so pure public static of type kitchen game manager the instance make a public get and a private set then down here on awake let's set the instance equals this okay so now over here on the player let's just go into the kitchen game manager access the instance and test is game playing and we're going to do an if if the game is not playing so if we are not playing we want to stop this so let's just return so if the game is not playing the code is going to stop executing here and same thing on the interaction so just like that we won't be able to interact with anything once we are not in the game playing State okay so here we are waiting to start nope I cannot pick up anything count down to start nope I can't and as soon as we go into game playing yep now I can't interact so I can cut a bunch of things and as soon as it goes into game overstate there you go currently in game over state so now if I try and interact nope can't do it okay awesome everything works perfectly so in terms of logic this is really it there's nothing else we need to do but of course right now the player would have no clue as to why sometimes they can grab and sometimes they can't so let's add a proper visual first let's add a visual to the starting countdown so let's do that as a canvas element so let's go inside our canvas create an empty game object name this the game start countdown UI let's press F to focus on the object press 2 to turn this into 2D okay so let's see and over here we really just need a text object so let's leave this one anchored on the center let's put the width and height both on zero we don't need that and then let's go inside create a new text object call this the countdown text and then inside let's just put a number so just a three let's put the width and height both on zero then down here let's put it in bond on a really big font size so let's say something like 250 okay really nice big number then let's also put it centered and down the middle okay that's right we've got our nice big countdown number also by the way when using text mesh Pro we can easily add a whole bunch of effects if we'll look down here we have the default text mesh Pro material and over here we can add an outline another line and so on so that's really great however there's one very very crucial thing when you want to add some effects always remember that the effects are being applied to the material meaning any text objects that are sharing this material all of them won't modify so for the most part usually you don't want to modify the default material if you do then everything using this default material will change like for example I want to add a nice thick outline to this one but over here I've got some regular text that is also using the default material so if I now add an upline and I increase the thickness and if there you go those also got an upline as well as this and if I wanted download make it quite a lot bigger there you go all of them modify because all of them are sharing the same material so usually you don't want to modify the default material if you want to add some kind of special effects always make sure to create a brand new material beforehand so over here let's remove the outline put it back on the dilation and let's go up here to create the brand new material first we need to find our phones over here on the font asset we can just click on it and we can see it over here highlighted on the project window so it's inside the text mesh profiler the resources phones and so on so here is the default font and inside this one is the font that we're using now in this font there's a nice little error icon and inside we can see the default material so let's duplicate this material although it's important make sure you duplicate the material and not the font so with this material selected I'm going to press Ctrl D and there you go it duplicates the material and over here let's give it some name so let's say this is material that I want to use for the start countdown so there you go just like this also one very very important thing the name of the material needs to include the font name otherwise it won't show up for example if I get rid of this the only version Sans SDF if I name the material just like this and now I'll look over here on the countdown text look on text mesh Pro here is the drop down menu for selecting material and over here note how that one does not show up so it is extremely important in order for it to show up in here it needs to have the same starting name so over here if I rename this material put Liberation sends SDF and then the name and now back in here now look and yep now I do see my material okay so that's great and over here we can add what kind of effects we want and it will only affect this one and not any others okay so for this one let's add a nice outline and let's make some nice thick numbers so over here on donation let's handle it by quite a little bit then for the outline color let's put it maybe on a blue something a bit like this okay let's push it back just a little bit okay I think that looks pretty good now if you want you could add even more effect to this I made another video covering how to use custom Textures in your font doing that you can just import the font directly into Photoshop and edit it with all kinds of effects for example in that method is example what I used in my game hypernite make the head counter look really nice I also have a tutorial specifically on that so if you want even more custom text definitely go ahead and watch those videos but anyways here we have our countdown text looking pretty nice now the number itself will be written through code so let's do that let's go into our scripts into our UI folder create a brand new c-sharp script for the game start countdown UI okay and let's select the parent object and attach the script now here first thing we need is a reference to that text object so let's add a serialized film private and again remember what I mentioned a couple of night years ago with regards to the types so we want xmesh Pro U GUI we want this one so it's going to be our countdown text and now for updating this text basically we just need to know the game state so we need to know when the countdown should show up and as usual let's use some nice events so over here on the kitchen game manager let's fire an event whenever the state changes so a public event event handler let's call it on stay changed okay just like this no need for the arguments so let's go down here whenever the state changes and let's just invoke this event so invoke this eventar is that empty so we change in there change in there and change down there okay that's it so now over here on the game start countdown let's see we've probably start and on start let's go into the kitchen game manager access the instance listen to the on say changed event as usual write some nice clean codes so let's rename this the kitchen game manager so when they say changes we basically want to show this if we are on the countdown to start so let's go here to the kitchen game manager and let's make another function so public boom is countdown to start active and we just return if the state equals the state DOT countdown to start okay so that's a nice simple function and on the UI script if the kitchen game manager if this one dot is countdown to start active if so then let's show if not then let's hide so else let's do a hide so let's make these functions so proud void show and a private void hide and on this let's just do the usual thing so game objects and active into true or over here set it into false and on start right after we subscribe to the event let's also hide it by default okay so that's the basic logic for showing or hiding it and now for the timer text technically over here once inside the countdown to start we could fire an event on every single update that would work but it would have some unnecessary overhead so instead another option is just make a function to expose it so let's go here make a public returning float get the countdown to start timer and we just return the countdown to start timer very simple so then over here on the UI script we can just make a regular proud void update and on update go into the countdown text in order to set the text and let's go into the kitchen game manager and let's get the countdown to start timer and just do A2 string okay so that's it super simple so on update we're going to constantly update the timer so let's see if this works back here in the editor let's just make sure to drag the countdown text reference and let's hit on play and okay waiting to start and after a bit yep there you go there's the number it's currently on countdown and now the game is playing so the show and high did work on the number seem quite a bit odd that's because over here on the settings we have wrapping enamel so now I just quickly disable this and let's test again sir we are waiting to start and there you go there's our countdown three two one zero and there you go gameplay okay so it did work now of course as it comes to the visuals it depends on what you want for example if you want to limit the decimals you can use over here the two string this one can include all kinds of string formats for example for displaying just two decimal places you can add the string format F2 let's see what this looks like waiting for the countdown and there you go now it does Show with two decimals okay so this is one approach alternatively another format you can use is number sign Point number number and let's see this one and yep there you go now it looks like this so as you can see there's lots of things you can play around with when it comes to the two string formats but in our case I don't really want any decimals I really just want to see whole numbers so for that let's just seal out this number so in mathf.cl let's see on this one out and then just do a two string okay let's see so wait a bit and we got three two and one and there you go the game is winning alright awesome so here we have our waiting to start and the countdown to start all of that logic is working perfectly now the next thing we need is to handle the game end so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to handle the game over State now for the game over State this is obviously a game design question for example you can make it so that each recipe had a timer attached to it and the player had to create that recipe within time limit then if they failed enough recipes you could trigger some kind of game over or for something more simple let's just do exactly what we did for the game start let's just do a basic countdown timer after the game is over let's pop up a game over window and show how many recipes the players delivered so let's do that let's go into our canvas and inside make an empty game object call it the game over UI then over here let's stretch it to occupy the entire parent like this now inside let's begin by making a UI image this is going to be the background let's put it in black with just a little bit of transparency and let's also stretches to occupy the entire thing so just like this then let's make some text so let's make a new UI text click the game over text and let's say just game over let's set the width and height both at zero then down here disable wrapping put it centered let's put it pretty big so maybe 135 put it a little bit higher then for some more text let's duplicate this let's call this the enlay bone recipes delivered text and over here we just say recipes delivered let's put this one a bit lower and quite a bit smaller say on 50 okay and also on this one let's put it in bold then change the color a little bit okay next let's make yet another text this one is going to be for the final number so let's call this recipes don't deliver text and this one is just going to have whatever number of recipes we've delivered and let's put it over here and quite a bit bigger okay so this is the game over window that we want also a quick note like I mentioned previously the Sorting order over here on the UI is based on the ordering the hierarchy so for the game over we want this one to show up on top of everything else so make sure the game over it is the last one over here on the UI make sure it is the bottom most child on the canvas okay now let's make a game object to run this so let's create a brand new script game over UI let's go into the object wait for the compilation and let's drag the script okay now here the only reference that we need is just for the text so let's just make a serialized film of type text mesh Pro ugly for the recipes delivered text here in the editor let's just drag the reference okay now let's make some show and height functions and also show it just on the game over so really we're going to do the exact same thing that we did over here on the game start countdown so let's actually copy exactly this let's go into game over UI pass the exact same thing Okay so we've got the show and hide functions we test and then over here on the state change instead of showing this one on the countdown we want to show it on the game over so let's go over here and just make another function so public goal is game over and we just return if the state equals the state that game over okay that's a function so over here if we are is State game over if so then we show if not we hide okay the last thing we need is just for the text so this is going to be the recipes only vertex so we're going to set this to something which really means that we just need to keep track of all of the recipes that have been delivered so until here onto the delivery manager script and let's just keep track so just a simple end so a private end for the successful recipes amount and then whenever we have a recipe success so let's go here into our delivery recipe function whenever we have a success let's just increase this by one okay so that's it now we just need a function to expose this so we probably can't for the get the successful recipes amount and just return the successful recipes amount okay so finally back here on the game over UI let's just print it so go into the delivery manager xsc static instance and get the successful recipes amount and of course we need the string so to string except for this one this is never going to change after the game is already over so let's not do this on update that would be quite wasteful so let's just do it up here so as soon as we have the game over we show we print the recipes and that's it okay so let's test so here we are waiting for the timer and let's wait and just wait five seconds for it to finish and we should see a zero so let's just make sure that works so after a little bit of time yep there you go we've got recipes all over zero okay now back here again let's try and deliver some recipes now so let's try and make a cheeseburger try it only for that cut this one pick up this one pick it up put it in there and okay quickly all right good and there you go we've got a one all right Awesome everything worked perfectly let's just add one more final element right now we cannot see what is the time left in the game so let's add a nice lock element so over here on the canvas let's make another empty game object let's name this the game playing clock UI and let's also put it behind the game over UI so let's put it above on the hierarchy so that it shows up behind in order to be able to see what we're doing let's also just hide the game over UI but only here on scene view so let's click on the I icon okay so here we have our window let's just anchor it on the upper right corner so let's put it somewhere in there then inside let's create a new UI image come with the background for the Sprite let's go with these circles right so let's click on the eye icon to show all the default Sprites and let's use the one included with the circle so you have this one let's also add a nice little outline so let's put it on 2 2 with phone Alpha and let's also add a nice shadow just nice visual so on five minus five like that and for the color let's also put it some kind of dark gray okay so this is our background now let's duplicate this so Ctrl d and let's rename this one the timer image and for this one let's give it a different color so maybe something like a blue so something like this okay and now over here on the image type instead of simple let's go with filmed let's choose Radeon 360. okay great and now over here we can play around the film Mount and this will be our timer then you can set it up however you want for me I'm going to choose to start from the top so as it starts the time we're going to countdown Until the End okay so that's great now let's make the script to run this so let's create the brand new c-sharp script same thing the game playing clock UI and over here let's just attach a script so now all we need is reference to our image so let's make a serialized field private image let's make sure to use this one the image inside Unity engine.ui this is going to be our timer image okay like this back here in the editor let's drag the reference all right now that we have this we need to ask the game manager to get the timer normalized so let's go over here onto the kitchen game manager and let's make a function to return just that so a public float let's call it get plane timer normalized or game point timer actually just to match the state so get this one and up here we have the playing timer we just need to define a maximum in order to be able to calculate the normalized value so let's duplicate this call it the game timer Max and set this one to 10 and this one leave it like this and down here when we change the timer when we go into game pointing let's set this one equals this.mex that way we only Define the timer just up here okay so with that now down here we can do the compilation so we can return the game playing timer divided by the game playing timer Max except just like this going to be inverted because for the game playing timer we're counting down instead of counting up so all we need to do is our simple just reverses so just one minus just like this okay great so we have this function and then over here on the clock just go private void update and on update let's go into the kitchen game manager the instance let's get that and we're going to use that on the timer image.fillment okay that's it super simple let's see okay here we are on the waiting to start all right waiting and as soon as we start if there you go there's the timer going and we can see it constantly increasing so it's at the halfway point and just a little bit more and there you go yep we've got the time over and we have our game over all right awesome so over here we implemented a really nice game over Saint we have a playing timer with an icui element and when it ends we get a game over window showing you a bunch of stats now with this working the next task is to have some kind of main menu so we can play again after the game is done so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to make a super simple main menu and downloading system okay so every game needs a main menu so let's build one let's begin by making the scene so let's go into our scenes and create a brand new scene call this the main menu scene and okay here's our default scene now over here for the most part you really just want some basic buttons so nothing too special so let's create a brand new UI canvas and let's set up as usual so screen space overlay yep then let's go with scale with screen size 1920 by 1080 and let's match with the height okay so there's our canvas now inside let's make an empty game object name this the main menu UI let's stretch it to occupy the entire thing so zero zero on everything okay now inside let's create a brand new UI button let's name this the play button then inside for the text let's say play Let's size the button to be quite a bit bigger so let's say 450 by 150 and on the text itself let's put it in bold only font size quite a bit bigger let's say 70 then let's also change the color let's put the text in White and the play button over here the normal color for the image let's put it on a dark gray then also over here on the button background let's add a nice outline let's put it on foam black say something like three three then let's make a Shadow and for this one five minus five okay so that's our basic button let's just anchor the button so choose the play button let's anchor it on the lower left corner and let's push it just a bit like this okay pre-symbal now let's duplicate this one push it a bit lower let's also make it just a tiny bit smaller so just 120 this is going to be our quit button so let's rename this to the quit button and inside for the text just say quit and put a bit more on the font size okay like this okay so we have the two basic buttons that we need now let's make this crypto random so let's make script with the same name so main menu UI so let's go into our script UI folder create new script for the main menu UI let's attach the script and open okay so now here let's begin by making serialized films for our buttons so it's always film private of type button inside Unity engine.ei this is the play button and then we have another one for the quit button okay back in the editor let's drag the references so that's the only button and the quit button okay now here in the code let's add some listeners to these buttons and let's do a private way to wake and on the way let's go into the play button and going to the on click event so the event when the player clicks on the button and let's add in listener and now we pass in The Listener now for here to do this we can add a function so we can make a private void Play Click we can define a function kind of like this and over here add it as The Listener so that's one approach or another alternative that personally I like to use is to use what is called a Lambda expression so instead of defining an external function down here we just go up here and directly with the finding Lambda so we open parameters to display the parameters for the function which in this case we have none so just open and close then we do a nice little arrow and then we have whatever we want to be our clear code so both the code that I have here and one that I have here both of these are exactly the same thing this one is called the unlimited expression which is also a type of delegate definitely go ahead and watch my video on C sharp delicates in detail it's yet another extremely powerful c-sharp feature I find them especially useful especially over here to setting the click listeners there's no need to make another function just use a Lambda expression that's it so over here I'm going to use that instead of an external function Okay so we've got the play and then let's also listen to the equip so on the quit button the exact same thing okay now first on the equip button it's actually very simple we just go into application and we call the quit function this will quit the game that's it very similar although one note if we actually test it like this so here is the game playing and if I click on quit and nope nothing happens now the logic is actually working we can see visually that the button is changing state so we are indeed capturing clicks however when the game is running inside the editor calling that function the application.quit doesn't do anything but if this were a phone bill then clicking on that would indeed close their game okay so now for the play button for this one it's also very simple we just need to go inside the scene manager which is inside the unity engine.scene management we just need to go inside of this one and we call load scene this function will load with a certain scene and for loading we can either use the scene film index or we can use the scene name like I've mentioned several times string names are horrible although in this case the alternative using an INT is also not very good just a number is very hard to read the code and being able to know what scene this is loading so there's one better approach that I prefer to use but first over here let's just use the index just for testing so we're going to load the scene on index one so just like this and then here in the editor and let's go into file and build settings and over here we see the scenes in our build right now we just have the game scene so let's just add our scene so let's drag the main medicine and drag it on there and also let's make sure it's on the top of the list basically the first scene is the one that won't be unloaded as soon as the game starts so let's try it right up top just like that then over here on the right we see the index so by loading the scene on the next one we're going to be unloading the game scene okay so with the slits test so here we are and if I click on playing and if there you go it doesn't load the main scene okay great everything is working so this is the seamless way to do scene loading however this method does have one issue it's not super noticeable when a game of this scale because it loads pretty quickly but like this note how when we click on play there you go everything freezes for a little bit while the game is loading like I mentioned in this case the freeze is so small so not necessarily an issue but if the game was much more complex then the player would be staring at a frozen main menu for perhaps 30 seconds that would not be good one way to avoid that is actually very simple basically it's what I already covered in detail in the scene loading video that video was made quite a while ago but it's still very much up to date here we're going to do pretty much the same thing so we first create the scene just empty just saying loading and then from that scene we load the final scene that way the game stays Frozen on a scene that says loading which is much more clear to the player so let's do that first let's make our scene so inside our scenes folder let's create a brand new scene call this the unloading scene okay let's go inside and on this one we want this one to be fully black so let's go into the main camera and scroll down over here under environment and instead of rendering the Skybox for the background let's go with a solid color and let's go with phone black okay there's our black main camera now let's make a canvas so a new UI canvas let's set up as usual so scale with screen size 1920 by 1080 and match with the height okay then inside let's just make a simple text object so just say text then over here on let's say just loading let's put the text width and height on zero put it on Bold let's make sure to disable wrapping and push it over there on the side and maybe increase the font size down a little bit okay there you go we have our very basic loading screen now we're going to unload this scene and then once on this scene we're going to load the final scene although also one very important thing related to loading scenes is you need to remember the lifetime of the objects regular game objects only for example the ones that we see here in the hierarchy these get destroyed when you do a scene change so for the goal that we're trying to achieve we need to unload this loading scene but then also somehow transfer data so that the loading scene here knows which one is the final scene now you might think that over here on the main menu we could create a game object attach a script that would hone the reference to the final scene but like I said game objects get destroyed as soon as we unload the unloading scene so for transferring data between scenes we can't really use a regular script on a regular game object now one approach is to use the don't destroy on loan this is a Unity function that helps you stop a particular script or a game object from being destroyed that way the object won't process through scene changes so that's one option but another option that I prefer is very simple let's just make it another class so let's create a new c-sharp script call this loader and over here let's go ahead and make this class a static class and we are not going to extend Model Behavior so just like this basically by making it static it means that this one is not attached to any specific instance of an object this class cannot be attached to any object and cannot have any instances constructed then inside we can add static functions in fields like for example a static and for the Target scene index so now this field we could set this field from over here on the main menu UI and when we would load we would not be resetting this field also here I should point out one quick thing you can make field static without making the entire class itself static making the class static is just a good approach if the entire thing if everything in this class is also meant to be static if you don't make it static then you can have regular films here you can have both static and non-sanic whereas if you make this static then you're going to have an error because you cannot have non-static feelings so this is another clean code thing if it's only meant to contain static logic then make the class itself static okay so we have a static field for our Target scene but as usual we don't want this to be a public field we don't want the main menu to directly write to this field so let's make this class the only one responsible for anything related with scene loading since then let's make a function so a public static void call it load and for a printer let's receive a string for the Target scene name then over here we will load the actual scene so let's go into the scene manager and load the scene analyst best in the Target scene name okay that's it and then over here on the main menu UI instead of directly unloading a scene let's go into the loader and con load and pass in the scene name so that's the game scene okay so this is what we're going to do that's good except it's obviously not good over here we're using string names that's horrible we should never use this so let's avoid using strings as much as possible in one simple way is to just Define an enum for all of our scenes so let's go here on the other and let's define that so a public enum let's call it scene and for all of our scenes so we have the main menu scene then we have the game scene and the unloading scene okay so then down here on this function inside receiving a string we just receive a scene for the Target scene and we use the target scene although of course the NT API does not support unloading our custom enum it has to be an index or string so the simple approach is just to convert this one into a string that's it so the only thing you need to make sure is that the enum values over here match the actual name on the actual scenes perfectly so don't make any mistakes keep it case sensitive so don't do this make sure everything matches perfectly okay so just like this everything should already be working the same as previously so the main menu calls that let's actually just use that so let's use scene Dot Game scene so on the main menu we do this and unloader we load the scene okay let's test here is the main menu and if we click and wait a bit and after you go it didn't load the game scene okay great so everything still works the same as presently except now all of the unloading logic is inside of this class and over here let's open a loading scene in the middle basically when we have this function to load a final scene let's first off set this field so this one instead of being type in let's make it a type scene and this is going to be the target scene and let's make it private okay so when we have this function let's set that field although here remember how this is a static class so in order to access this field we need to exit through the class name because over here we also have a local variable with the exact same name so what sex is the unloader.target scene and set it to the Target scene so again don't be confused here you can even use visual studio and put the cursor on top to see what object represents what so you can see the unloader.target scene is referencing this field whereas this one over here is referencing the local field so we want to assign the member field to the one that we received as a parameter okay so we store that and then let's immediately unload the unloading scene so scene manager let's load the scene and we're going to load the scene dot loading scene dot to string okay so we're going to download that and now here comes the tricky part if we do this so if we load the unloading scene and then immediately unload the target scene if we didn't like this it won't actually show the loading scene we're calling these functions one right after the other so to unload the one and immediately the other basically we need to wait at least one frame to render so that the unloading scene is visible and then we can alert the final scene so let's make a script to do a very simple jump let's create a brand new c-sharp script for the unloader comeback and now let's go inside the unloading scene so this is important let's make this on the loading scene not the main menu or the game scene so over here let's create an empty game object for the unloader comeback let's reset transform just keep things nice and clean and let's attach a script so the only other comeback okay and on this script we want to basically just wait for the very first update so let's see private ball is first update and we started off as true actually so is the first update is true then we do a product void update so if it is the first update if so then let's set is first update to false we have the first update although technology I should point out that we don't really need this we're going to load right away so either way it will only run One update but still I like to add this just to make the logic perfectly clear basically if it is the first update then let's call a function on the unloader so on the loader over here let's make a function public static void call it below their comeback okay we have this function it's over here on the other convex let's just go into the unloader and call the unloader convex function all right so basically now here we have this function that is going to be triggered on the first update so we know for certain the unloading scene has been rendered so it's over here that we want to load the actual final scene okay that's it here we have a super simple loading system just make perfectly sure that the unloader come back with the script this one only exists on the loading scene it should not be on any of the other ones so let's test and for that let's go inside the main menu scene okay and now let's hit on play okay so here we are on main menu now if I click on play and actually here's the thing that I forgot so make sure you don't forget this we need to add the unloading scene to the builds in order to be able to load so let's go up here into the build settings let's go into the project drag the unloading scene like that okay so now let's test so here we are on the main menu let's hit on play and there's the loading scene after a bit yep here we have our game scene all right awesome so with that everything is working perfectly all of the logic is working great now the wrong words great let's just make a nice proper visual for our main menu so for that let's go inside the game scene and over here let's copy a few things so let's pick up the four object and let's also pick up the global volume with the post pressing so let's copy both of these let's go into the main menu scene and over here on let's paste both objects okay now let's also drag some player visuals so let's put this in 3D go back down into the floor and let's pick up some visuals so let's go inside our assets on the prefabs visuals let's find over here the player visual again make sure you drag the visual only we don't want any logic components and by the way this is yet another great benefit of separating the logic from the visuals right now it's super simple for us to play some players here because we have just the visuals commonly separated from the logic okay so on the visual let's just make it look at the camera let's position a bunch more players so let's duplicate this and put one to the side we're going to move the camera in a bit but now let's just place them and included assets there are a bunch of materials so over here we see the employer body then we've got a blue a green and a red like I said this first course is on making this game in single player but the goal is to then make a second course after this one on converting this game into multiplier so that's why I included multiple colors so let's just drag these let's go into this player Visual and on this one make it blue so on the head and on the body then on this one on the side here let's make this one green so green there and green on the head and for the one behind let's make this one the red one so put it in red and in red Okay so we've got our nice four players now let's also add a camera so we're going to have the camera kind of like this kind of from below and looking upwards I think that looks pretty good for that let's use cine machines and let's go into game object go into cinemachine and let's create a brand new version on camera okay unlike this let's just push it up a little bit okay so this is our nice composition now on the virtual camera let's just go ahead and add some noise so let's add basic multi-channel purlin so let's do it just like we did when we first had the thin machine so let's use the handheld normal mild and now let's just play around these films which by the way you can do that while the game is playing so let's hit on play and over here you can play around down the fields although actually defaults already look pretty good but let's put the frequency maybe a little bit less and the amplitude maybe a little bit bigger so just some nice little Sway and by the way if you make any changes to the send machine virtual camera and now you stop playing it will actually lose those changes but over here on the virtual camera there's this nice toggle save during play so if you tick this and now you exit play mode and there you go those changes were saved okay great now let's just make sure to untick this so we don't accidentally modify okay so here we have the basic Vision that we want finally there's also a game logo in the included assets so let's just go into our canvas into our main menu let's create a brand new UI image let's assign the logo Sprite then let's just position it on that corner so let's move it all the way up there we can anchor it to the top left corner and let's make it a bit bigger and by the way I want something like this if you play around this it might get a bit scratched so if so over here on the options on the image you can download this one to preserve the aspect ratio so that way even if you stretch it won't actually be stretch it will always be perfect okay just like this okay so here we have our basic main menu it's a basic setup but it looks pretty good and with that we have built a nice main menu alongside with the unloading system so I can click on play it goes into the loading scene and then into the game scene so that's great the next thing that we need is some kind of pause button so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to add a pause button with a pulse window that also has the ability to quit back to the main menu and in doing so we're also going to solve some sneaky issues with loading okay so here in the main menu we can click the play button in order to unload the game and yep everything works now I'm in the game but now let's say I want to pause the game for a bit or quit back to the main menu right now there's no way so let's do that let's go here onto the game scene and first let's send on the pause and for that we're actually going to need some input so let's first go inside our player input actions let's open this and then over here let's make a brand new action let's name it the pause for the action type let's go with button okay and for the bindings over here let's go with escape and actually if we use the same method that we've been using if we listen and press on Escape nope doesn't work because Escape just cancels it so instead we need to use a search bar here Search for escape keyboard just like this okay great now again as always let's make sure to save the asset and wait for the compilation to happen there it is so now here on the game input list let's listen to it and fire the event as usual so go into the player input actions the player action map let's go into the pause action and listen to the performed event and when this happens let's fire off an event so a public event event handler let's go on pause action and then down here we're simply going to invoke this event okay just like this now from listening to it here's the question where does that make more sense should we do it over here on the player script or perhaps over here on the kitchen game manager I think over here on the game manager makes more sense since a pause is more related to the game itself rather than a specific action by the player so let's add it over here let's first of all listen to the event so let's see what private void start and on start let's listen to it so let's go into the game input and we didn't actually make it a Singleton yet so let's do that over here let's make a public static game input for the instance with a public yet and a private set then down here on the Wake let's set instance equals this okay there's our Singleton so now back in the kitchen game manager what's going to be instance and listen to the on pause action event and again let's rename this to give it a proper name so the C game input on pause action okay so here we have it when we have this let's call some kind of pause game function so let's define this let's go to the end of the file here and over here let's make that function so a private void pause game and over here we're going to pause the game now for pausing doing this is actually surprisingly easy basically all of our logic is using time dot on time for example over here on the player script we have our movement speed yep then we get the inputs and over here on the handle movement function yep for the movement distance we have move speed multiplied by time.10 is done or another use case over here on the stove counter we've got a frying timer and how we count it down again is the same thing time dot double time well it turns out that behind the scenes time to time the time actually already has a multiplier when you access this it is after that multiplier calculation so over here on the pause game function we can just go into time and we can modify the time scale this one is the multiplier so if we just put this at 0f then that's it this is going to pause all of the other Delta times so let's test so here we are pay attention to that in the countdown timer and I press on escape and there you go everything pauses the countdown timer pauses over here the script pauses and I can no longer move nothing works everything is perfectly paused alright Awesome everything works except one problem obviously right now we cannot unpause if I press Escape it's not in pausing so let's do that over here on the kitchen game manager let's add a simple bone so a private bone let's come with is game paused and let's see found it to phones okay so is game paused and then down here on the pause game function let's simply flip this one so we set this one equals not this one so that is going to flip that Boolean and then we check if the game is paused if so set it to zero f and if not then we're going to set the time.time scale back into one F okay so now this should pause and unpause so essentially rename this function since this is no longer just going to pause let's rename this to toggle and pause game this is going to pause and unpause okay so let's test okay so here we are everything is running now I pause and there you go everything freeze I cannot move the arrow will stop the countdown to stop when I press again and there you go nice and redeemed all right great so all of the logic is working perfectly the only thing we need is we don't just see visual and as usual let's separate the logic from the visuals so let's go inside the canvas let's go into the scene View and inside the canvas let's create an empty game object call it the game pause UI then let's stretch to occupy the entire screen so zero on everything okay great now inside let's first of all add a background so a new image name this the background let's once again stretch to occupy everything and on the color let's put it in black with just a little bit of alpha okay just like that then let's add some text so let's create a brand new UI text let's name it pause text and in here let's just say paused let's just make it big so the width and height both on zero let's disable wrapping Put It Center down the middle and let's increase the font size by quite a bit and put it in bold and let's also change the color maybe a nice yellow something like this okay that looks pretty good let's just lift it up by a little bit now let's make a script to show this so on the UI folder let's create a brand new c-sharp script call this the game pause UI let's attach it then open now here let's do the usual thing so let's make two show and hide functions so private void show and then a private void hide so on the show game object set active into true and on the hides set it into false okay that's it pretty simple now we need to know when to show our hide these functions so we're here on the kitchen game manager let's make two events to do that so let's go up here make a public event event handler and let's name this on game pause another one for on game unpaused okay we have both events then down here on the toggle pause game if we have this one time scale 0 that means we have pause so let's invoke the on game pause this eventar is not empty okay and on this one let's trigger the other one so on game unpause okay we've got the two basic events now back here on the game pause UI let's listen to it and as usual let's do it on start so private start let's go into the kitchen game manager access the static instance and let's listen to the on game pause and I'm going to listen to the other one so the instance on game unpaused so listen to both of them and as usual let's write the clean codes and let's rename this so kitchen game manager and on this one the same thing so also the kitchen game manager okay we have both and when the game is unpaused then we want to hide the pause window and when the game is paused then we want to show the pause window and finally of course we want to hide it by defaults over here on sart after we add listeners let's just hide it okay so that's it that should work so let's test so here we are everything is running now press the pause and there you go got a nice pause window press again and there you go everything resumes okay great so the last thing that we want is just a button over here to go back to the main menu and let's also add a button to resume without having to press the hotkey so over here let's create a new UI let's make it a button this is going to be the main menu button now let's make it quite a bit bigger okay width and height of 30 and 80. let's put this one quite a bit down there and inside for the text this one is the main menu let's put the color in White and the background for the button let's put this one in a dark gray and let's also just for fun add a nice upline and let's also add a shadow for the outline let's put it on for Alpha and let's put it on about 3 3 and for the effect on the shadow 5 minus five okay so that's a nice outline and nice shadow and then for the text itself let's put it in bold and raise it by just a little bit okay just like that looks pretty good so this is the main menu button and then let's also make so duplicate this let's make this one rename it this is the resume button and inside on the text let's say resume okay we have our two basic buttons so let's handle them in the script so over here let's add as usual a serialized field private of type button so that's inside Unity engine.ui so it's for the resume button and then we're going to have the main menu button okay let's save the script and back in the editor let's drag those references so that's the main menu button and the resume button okay so now for these let's add the click action so let's do a private awake and on the way go into the resume button the on click and let's add a listener so this is going to be our listener and same thing for a main menu button so main menu now for the main menu this one is super simple let's just go into the loader and call the unload function and we're going to download the main menu scene okay that's the main menu very simple and for the resume this one is only going to be clickable when the game is paused so we can just trigger the same function on the kitchen game manager to toggle the pause so kitchen can manager the instance and toggle the pause game this one is actually private so let's go to it and let's make this public so we can count from there okay that's it super simple Let's test okay so here we are and let's pause the game and now if I click on resume if there go it does work everything resumes and now pause again and now let's go back to the main menu loading any up there you go back in the main menu alright awesome so everything works perfectly however there's one sneaky issue here you can already see the issue by seeing that all of these animations are still but let's click on play and notebook that issue everything is still frozen I cannot move the character and over there the Shader that one is completely Frozen so the times can only still set to zero basically we need to manually reset it and the simplest way to do this is really just in the main menu so we can go here on the main menu UI and we can just use this as our reset function so let's just go into time.time scale and let's set this one back into one F that's it that's the only change Let's test so here we are let's pause let's go back into the main menu and we can see the animations are indeed playing and if we go back into play and if there you go everything works perfectly we can pause and yep here we do see one of the other two sneaky issues left basically it has to do with scene loading and cleanup so the first one is on input over here on the game input class we are constructing our player input actions and we are listening to these events and technically this object the one where the game input is attached this object is going to be destroyed when the scene changes however this object that we're creating this instance of player input actions this one does not get destroyed automatically so that is why when I went into the pause menu again for the second time over here we've got a missing reference exception basically the player input actions of the previous game is trying to show the pause window also of the previous game which has since been destroyed so obviously we have a missing reference exception because that object no longer exists so in this case we have two options to solve this one option is we can just unsubscribe to these events Unity mono behaviors have a really nice combat called on destroying so over here private void on Destroy so this is the default one this one is called when the mono behavior is destroyed so we can go into this one and we can manually unsubscribe and the way that you unsubscribe is you just do minus equals so this would solve that problem because when this object is destroyed it's going to unsubscribe from those events so the next time it will no longer trigger so that would fix it however on the game input class we are still creating a new object of this type I'm not 100 sure how the input system works in the background so perhaps this object might say in memory which is not good so another approach we can do or perhaps in combination with this is we can unsubscribe and then we can properly dispose of this object how we do that is very simple let's just go into the player input actions and we just call the dispose function that's it this should clean up that object and free up any memory so let's test so here in the game view let's pause let's go back into the main menu now let's go back into the main game and now if I hit pause and if there you go we no longer have any errors okay so that's good however now we still have one more potential issue and this one has to do with Statics like I mentioned before Statics belong to the class and not any instance of that class so that means that static films will not be destroyed or reset when the scene changes in the case of our unloader here where we have a private static field this one the fact that this one doesn't reset automatically that was a good thing that's what allowed this to make the unloading system but in the case of maybe static events that might not be as good it might mean that we might be keeping some state from the previous game which might cause everything to break so basically we have a similar problem to what we had in the input where some logic from the previous game might be affecting the next game in all the code that we wrote the main place where we use Statics were in The Singletons and these are going to be cleared automatically when the underlying instance object when that one is destroying so these do not cause any problems however for example over here on the cutting counter we've got a static event when the scene changes this will not be cleared so this will still have the same number of listeners we can actually see how many listeners there are by printing it so let's go down here before we're invoking the event let's do a debug download let's go inside the on any cut event and over here we can get the invocation list this one is a list of all of the functions that are listening to this event and we can just print out the link to see how many listeners are listening to this event so let's see what this returns okay so over here let's pick up some cheese and slice it and if I'm working the log yep there you go one there's only one listener okay that's correct however now if I go back into the main menu and now I go back and I play again okay so let's play let's just wait for the countdown and once the countdown ends pick up some cheese go there slice it and there you go there's the problem now we have two listeners in this case doesn't really cause an error because the tune listeners they're just over here on The Sound Manager so we are subscribing to this event and we're doing the cut and playing the cut object however if here we do something with this transform like for example let's just do a debug download on this transform that position if we do this here let's go ahead on the first one let's slice and okay that works let's go back into the main menu now play again now wait for the timer pick up some cheese go there slice any of that I go there we have our air that is because we are now accessing The Sound Manager transform and that one has since been destroyed so if you do use static events like this one here if you do that always remember you need to manually reset that state it won't happen automatically on the scene load and one way that I normally do it is just make a class responsible for doing that so let's go ahead and let's create a brand new c-sharp class let's call this the reset static data manager and for this one we want this one to run only on the main menu That's only where we're going to reset things so let's go inside the main menu scene let's go there let's create a brand new empty game object for the reset static data manager let's reset transform just keep things clean and let's attach that script again it's very important that this object only exists on the main menu then over here we're basically just going to go into any script and reset any data so for that on all those scripts let's make a function so over here on the cutting counter let's make a public static function let's call this reset static data in order to reset any listeners let's just go into the on any cut and set it to null that will clear all the listeners so we just do this and then on this script Let's see we practically awake and on awake let's go into the cutting counter under the class so not any instance so we're going to access the static and we're going to reset the static data that will clear all the listeners on The Cutting counter all we need to do is make sure to do this on every single static event that we have so on The Sound Manager and by the way here we can get rid of the testing code here we can see all the static events that we're using so we've got the cutting counter then we've got the base counter and trash counter so let's go here on the base counter and paste the exact same thing and reset this event okay and now let's go into the trash counter so here on trash counter same thing reset this event set them all into null and by the way here we have a warning that's because trash counter extends base counter so basically this is telling us that we are hiding another function with the exact same name in this case we do want to hide it so what's actually make this new to make sure that this one is a different one just to avoid that warning and same thing over here on the cutting counter we also need to make a new okay so that's it and now we just need to go over here onto the reset static data manager let's go into the base counter and reset the static data go into the trash counter and reset the static data okay that should do it let's see so here we are in the game let's pick it up and slice it and yep we've got just one listener that's good let's go back outside back into the main menu let's play once more and over here let's pick it up again go there drop it and there you go still just one listener because we are now correctly eliminating all of the previous listeners so this is the one sneaky issue that you must be careful with when it comes to object Lifetime and Statics for static Fields you need to remember that they don't manually get cleaned up that's up to you so that's something you have to keep in mind but you can also see how easy it is to solve now that this is solved let's just go into the cutting counter and just get rid of our testing log alright so with all of that all of our scenes are working so we can start from here from the main menu and go straight into the game then here we are in the game playing normally we can pause the game at any point from the pause screen we cannot resume or we can go back into the main menu and from back into the main menu we can once again play the game from scratch and if there you go everything works alright awesome now the next thing that every game requires is some options so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to create a simple options menu where we can modify the audio levels okay so here let's make the options menu so on our game scene let's go into the canvas and create a new empty game object let's make this the options UI let's stretch out this one to occupy the entire screen then inside let's make a UI image once again let's stretch out everything let's put this one in black in just almost full Alpha okay now let's make some texts so let's create a brand new UI text call it the options text then for text let's say just options let's put the width and height at zero let's disable wrapping Put It Center down the middle and put it quite a lot bigger okay that's the options now just move it slightly upwards all right now let's make some simple buttons to handle our audio controls we're going to make it super simple literally just a button we can click so inside the options UI let's create a brand new button call this the sound effects button then let's make the button a bit bigger something like this okay and inside for the text let's say sound effects and then we're going to have a number for the sound effects let's just quickly change the color so put the text in White and the button over here the button image let's put it in a dark ring okay let's also make it just a tiny bit thinner it's just like that okay so this is the sound effects button now let's duplicate this one this one is going to be the music button so let's name this the music button then inside for the text music and then a number and that's pretty much it so by clicking on either of these buttons we're going to increase and then Loop the volume so let's make a simple script to handle our options window so in our scripts inside the UI let's create a brand new c-sharp script for the options UI let's go ahead and attach a script and open so here as usual let's get some films for our buttons so a serialized film private of type button for the sound effects button and then there's another one for the music button okay both buttons now let's add the click event so on private awake let's go into the sound effects button and on the on click let's add a listener and we're going to do the same thing on the music button okay so now when we click we want to change the volume so let's go here onto The Sound Manager and make a function to modify the volume let's make a private void change volume and here we're going to increase the volume by 0.1 percent so constantly increase in 10 increments so that means we need to keep track of the volume so up here in order to find a SIM phone private float for the volume well it's default it to one F okay so now down here we take the volume and we increase it by 0.1 F and now let's Loop it back to zero now for looping usually you do it using the modular operator so here you could do volume equals volume module of 1.1 f that way when it gets to 1.1 f it would reset back to zero but here since we're working with floats which can have a bit of odd Precision with this let's just do a simple lift to make sure that always works so if the volume is above one f if so then let's just reset it to zero okay so here we modified volume and let's just make sure to use it over here when we actually call the audio source.playclip Point here we've got a volume but this is the one that we received as a parameter so let's actually receive this one rename this to volume multiplier and we're going to basically multiply the one that we receive in the parameter by the one that we actually store so this way on these functions when we play a certain sound we can still give an optional volume if we want to make it louder or quieter then the regular sound effects okay so we have our change volume function now we just need to call this from the options UI so that means this one actually needs to be public okay so now here on the options UI we go into the sound manager access the instance and call change volume okay so that is going to change the volume then we just need to update the values on the options UI so let's make a proud void update visual and this one we need to update the text so up here on let's add once again some more serialized Fields so text mesh Pro ugly one for the sound effects text and another one for the music text okay we have both these then here the sound effects text not text equals and we go into The Sound Manager the instance and then we need to get the volume so over here on the sound management let's make a function together so a public float return get volume and we just return the volume okay so then here let's get volume except volume is going to be a normalized value so rather than showing 0.1.2.3 on the UI let's just multiply the volume by 10f that way we show between 1 and 10 okay then let's just round out this number and then add the text so here's sound effects and then we have the bone okay so that's pretty much it and up here when we change the volume let's just update the visual and let's also make a private void start and on start let's also update the video okay that's it pretty simple now let's do the exact same thing on the music except on the Music Manager we named it music manager but over here we just have an audio Source there's no actual manager so let's actually make one let's create new c-sharp script for the Music Manager let's go into the Music Manager object let's attach a script and let's open so here we really just need pretty much exactly the same thing that we had so let's just go here into The Sound Manager and just copy these so on the Music Manager let's paste them we need a volume so a private mode for the volume just like this okay so that changes the volume except again the Music Manager this one the music is constantly going to be unlooping so after we modify the volume we need to update the actual audio source so let's begin by grabbing the audio source audio source and we just do a pro void awake and on a week let's grab the audio source get the component of time Body Source okay so we have this and when we change the volume let's go here and update this phone okay that's it and let's also default it to some like 0.3f okay good then in order to be able to call this from the option Cy we just need to make it a single turn so as usual public static Music Manager for the instance and we have a public get and a private set and then an awake just set instance equals this okay so then here on the options UI we can go into the Music Manager the instance and change the volume and afterwards let's update the visual and down here on the update visual lets you pretty much the same thing so on the music text modify the text to say music then we go into the music manager and get the volume all right that's it all this should be working let's just drag our references so back in the afternoon let's drag firstly button so the sound effects button that's this one then the music button that's this one then we have the music text that's this one and the sound effects that's like that okay let's test okay so here we are the music is playing and as I click the music is currently getting louder and louder and their game I'm using is at max volume and if I click again no the music is completely muted alright awesome any sound effects also work so like this they should be less leather than usual okay great so everything works perfectly except obviously we have one big issue the options window is on top of everything the goal is for the options window to be kind of a sub menu of the pause window we want to have an options button on the pause window that won't bring up the options window so let's do that let's first hide the options window let's go into the game pause UI and over here we have these buttons let's just make one more let's put it down the middle this is going to be the options button and inside let's modify the text to options okay now let's edit this script so we're going to have another button so this is the options button and down here we're going to have another click so the options button okay and when this happens we want to just show the options window so in order to access it let's make this a Singleton so public static for the options UI a static instance with a getting a private set and on weak as usual instance equals this so over here on the game POS UI we go into the options UI access the instance and then call a show function so we need to make this so here on the options UI let's make those so a public void show and this one as usual just game objects that active into true and then we have a private hide and this set active in two phones okay we have both these on the other side we show it and over here on start let's also hide it okay then let's also hide it manually so let's add a button to close the options UI so over here let's show the options UI and let's make another button let's put it on the bottom this one is the close button and over here let's just say close so then here on the options UI just make another button the close button and down here for the click event we go into the close button and we just call height okay so that won't hide the window however remember that the pause window can also be closed by just pressing escape if we resume with the hotkey it won't hide the pause window so let's also make sure this one hides on the same thing so we can do pretty much going to the kitchen game manager the instance and let's listen when the game is unpaused so when that happens let's hide this window so once again let's do things nice and clean let's rename this so the kitchen game manager and when this happens let's just hide okay this should work let's just drag on the references so first here on the options UI let's drag the close button and then on the game pause UI let's drag the options button okay so let's test and if right away the options window is not showing the trade and if I press in this game there you go there's the pause window and if I can click on options if there's the options window now if I can go and close back here back into resume okay works now if I pause options and now press on the Escape key and you better go closes everything all right great so everything is working fine however we have one slight issue the option does work so I can modify this to change the sound effects and Music volume so for example let's mute the music and put the sound effects on five so I put it like this but now if I stop playing and I hit play again and working the options and oh there's the issue basically that is back to the default obviously that is resetting since we didn't actually save anything so let's save it now in unity the easiest way to save some data is using player prefs so let's go over here on The Sound Manager and when we modify the volume over here when we do that let's access the Unity Player prefs and over here we've got a bunch of set functions so we can save a float an INT or a string this one as you can see it takes a string and a value so this is pretty much essentially just a dictionary now for the key as you can see it's a type string but again we should not be using strings directly so let's go up here in order to make a proper constant so a private con string let's go with Pro layer prefs sound effects volume and let's go sound effects volume okay we have our nice Center in content and down here when we set the float let's use this string and say the volume okay so that is going to set the float and now technically Unity is going to automatically save the player perhaps basically there are only problems if Unity somehow crashes in between when you can't set float and when it actually saves but if you want to prevent that from happening you can just go and tell it to save manually just like that that won't definitely save it and now we just need to handle loading so here on awake when we have this let's go into the play prefs and let's use get float let's pass in the same key so this one takes the key and default value so let's default it to one F basically the default value is used if there's no save data on display prefs on this key so the first time we run it's actually going to use this default and this one's going to return these saved value so let's just set it on the volume okay so that's it that's only takes to save some basic data now let's do the exact same thing on music so over here on the Music Manager let's first Define our private con string for the player pref's music volume and this is going to be the music volume okay we have our string and then down here when you change the volume layer press and let's set the float on this key and let's pass in the Music Volume okay and then what's going to player prefs and actually save it and now appear on the wake let's grab the volume and it's going to be going to the player prefs in order to get the float on this key and default value is 0.3f however over here on the music again we are not spawning the sound afterwards the sound starts playing right away so let's make sure to set the audio Source volume to the one we grab from there okay that's it so like this it should be working so let's test so here we are and the music is playing let's pause go into the options let's bring the music completely down so let's mute the music okay the music is gone and sound effects let's put a note 5. now let's stop playing and now play again and going to the menu options and if there you go the data was indeed saved and the music is indeed muted alright awesome so here we have some basic data being saved and also just quick note related to saving for this simple game decisions are pretty quick so I didn't include any kind of save system for the actual game data but if you want to know how to do that I also have video covering that topic okay so with that we have our options window working the volume sliders work perfectly the next thing we need to add to our options is some key rebinding so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to add key rebinding to our options menu so here we already have this nice options menu we can modify the volume of the sound effects or the music next let's handle key rebinding okay so first let's build the elements over here on the UI so let's create a bunch more buttons but before that let's actually make some text on the side and buttons in the middle so let's create a brand new UI text call this move of text let's put it on the same size as the other one so these got a font of 24 so let's put it same thing font of 24 width and height let's put both of these on zero and down here anchor it to the left okay down the middle and with no wrapping okay so then over here this is going to be the move up action so we have move up then we have the move down move left move right then we have the interact the interact alternate and finally the pause so these are all of our actions so let's just make all of these so rename this so this one is the move down then this one over here is the move left this one is the move right this one is the interact text then the interact alternate text and finally the pause text now let's just modify the text on these so that's the pause that one is the indirect Alt then this one is the interact then we've got the move right then over here the move left and finally we have the move down okay so those are our labels for our controls now let's just make buttons over here on the right side so let's duplicate one of these buttons let's put it over here and put it on something like 50 by 50. so this is going to be the move up button and inside on the text this is going to be pretty much just a w okay so we have the move up then we're going to have the move down move left move right the interact the interact alternate and the pause so we just need a bit more space so let's move all of these up by quite a bit let's also move the music and the sound effects so move all of these like that okay let's just name all these buttons so this one is the second one so this may move down then over here the move left then the move right then the interact button the interact alternate button and finally the pause button okay those are on the buttons let's just position all of the labels exactly where they should be okay so here we have all of the options all of our bindings now in code let's grab references to all the buttons and all the text inside the buttons so here inside the options URL let's add all of those so first of all for the attacks we're going to have the move of text then the down left right and so on so let you see all of these so down then over here the left then the right then the interact text the interact alternate text and finally we have the pause text and for the buttons let's go up here make all the buttons so they move up button then they move down button then we have the move left button then the move right button then we have the interact button the interact alternate button and finally the pause button okay so we have all of these references over here in the editor let's just drag them so let's make sure we drag them on correctly so let's do it one by one so the move up this is the text and actually it's not that one so that's already a mistake right there we want the text from inside buttons so let's pick up all of these text objects so let's go into the options so text inside the move up let's grab that one then inside the move down let's grab that one and then left and so on so definitely make sure you grab the right ones okay that's on text now for the button so let's move up button then you move down then they move left the move right the interact interact alternate and finally the pause button okay great and just to verify that everything is working let's give proper names to these objects so the move up button text okay so I've renamed all the buttons so now over here it's much easier to verify that we have the correct references so the sound sound music music and so on so definitely make sure all of these are correct otherwise you might go crazy when things start to go a bit weird so make sure these are all correct all right now let's begin by updating the text inside over here so let's go into our update visual so we go into this set the text and now we need to get the binding text for this binding so for that let's make that function on the game input over here let's just comment this out then over here on the game input script let's make a function to get the bindings certainly we could make something just to grab this player input actions but again we don't want the options UI to know what input system we're using it should work regardless of what input system so we don't want the game input to return anything of this type instead we want to make a nice layer of abstraction so for that let's make an enum to Define all of our bindings so let's make a public since we're going to access it enum call it binding and over here let's add all the bindings so we've got the move up then we have the move down the move left the move right then we have the interact the interact alternate and finally the pause so these are all of the bindings now let's make a function to return the binding text so over here let's make a public we're going to return a string let's just name it get binding text and as a parameter let's receive a binding okay so now here let's just do a switch switch on this binding and basically just match up the enum to whatever action we have so for example let's begin with the interact since these are the simplest ones so for this one to get the bindings we first go inside the player input actions then let's go inside the player action map then for the action so in this case the interact and anything inside we've got the bindings this is an array of all of the bindings in our input map we defined all of the keyboard bindings on index 0. later on we're going to add Gamepad bindings but for now we're going to have the keyboard always on index 0. so over here going to bindings axis on zero and let's just do a two string okay so let's just return this and let's do a default to return always this one just like this okay so let's do a quick unlock to see what this returns so let's do it over here on the game input just a debug.log go into there get the binding tags for the interact okay so let's test and right away yep we do see it working so the interact and The Binding is on keyboard slash e but we don't want all of this text we really just want to see the E thankfully the input system has a really great function for just that so instead of calling the general to string let's call to display string let's see any of this one does return just easy okay great so this is the one that we want let's do the same thing for all of the other simple actions so we've got the interact then we have the interact alternate and we have the pause so these are all the super simple ones so just going to interact alternate grab the binding on zero and for the pause binding on zero okay so these are all super simple now the more complex one is the move it's more complex because you can see all the others just have one binding except for the move over here we have a composite binding so that's basically a binding which inside has four separate bindings basically the way that this works is that when you use a composed binding all of these are added to the array so this to the vector is going to be on binding 0 then the up is going to be on binding one two three four and so on then the arrow keys this one is going to be on five then we have six seven eight nine and ten let's do a log just to verify so here if we do one for the move up action for this one let's go into the move and let's print out just the binding zero let's do a regular two string let's see what this returns so up here let's just modify our log to say the move up okay so let's see any up index 0 does have the move to the vector and now if we print the one on binding of one yep now this one does have the move on the w so like I said we can see that all of these Composites these are technically inside that one but in terms of that array it's just a flat array so this one index 0 1 2 3 and 4. so that makes it super simple to add over here so they move up down left right and let's just do all these so we have all the bindings and over here just one two three and four and set a two string let's call the display string okay so the binding text this is all set up so let's go up here and get rid of our testing code we can now call this from the options UI so over here let's do exam with that so when we update the visual let's go into the game and put let's access the static instance let's get the binding text and this one is going to do the move up so that's it this one is going to return a string let's write all of them okay here are all of them so let's see and if there they are all perfect don't we SCD EF Escape okay great so the visual is working now let's end on the rebinding so let's add a click event let's go into the move up button let's go into the on click let's add in listener and for the enlistener over here let's make a function on the game input to rebind this binding so over here on the game input let's see public void rebind binding and we receive a binding now for rebinding I cover this in detail in the dedicated input system video first basically we need to disable the action map so let's go into the player input actions let's access the player and disable it so we need to do this first then we're going to need to find the action so player input actions and for now let's go into the player and let's just modify the move up action so we're going to call the function perform Interactive rebinding this one as you can see takes a binding index and if you remember up here we saw that in order to modify the move up it's on bindings index one so let's modify the one on index one okay so this is the function this returns an object of this type a rebinding operation this is a pretty complex object where you can modify all kinds of things add a bunch of limitations and so on like for example make a key not be able to be bound to the mouse or something so there's tons and tons of options you can play with over here for the simple thing let's just add an on complete listener so this one takes in a convex and this will be called whenever the interactive rebinding completes so over here on let's define and Lambda so we come back and inside we have this by the way over here this is the same line of the expression that we saw previously so exactly the same thing as this except when we have just one parenthesis we don't need to add them okay so like this so then on this convex we can see all kinds of things like for example we can see the action that we just rebound this is going to contain all the data on the rebind operation so for example let's print out the path so let's go into the action let's go into the bindings on index 1 and let's print out the path similar to a debug.log and there's actually another one so let's log the path and also the override path these are two different things let's see why in a bit we do this and after we log we also need to rename on the player action map so let's go into the player input actions deep layer and back enable this okay so we're only going to need these settings on the rewind action then we can just call start in order to start the rebinding process okay so this should work let's just call this from the options UI so over here we have the click let's go into game input instance and let's rebind The Binding and for this one is the move up okay with this let's test okay so here if I click on the button and I click on the T key and if there go it did work so you can see that it print out the regular path that is w and the override path which is C so now if I exit out of the options go back into the game if I press W nope it does not move but if I press T yep it does move upwards okay great so we have successfully rebound this one key now here just one thing in previous versions of the input system when doing a rebind operation you need to manually dispose of this comeback otherwise it would throw a memory error in the recent version that I'm using here there's no error so it seems perhaps it's no longer needed to dispose of the compact manually but still there's no harm doing it just in case over here combat dot dispose okay so with that the key rebinding is working except we have two issues the first one is that it's not very clear that it's listening for an input and the second one is that the text options also does not update so it's on both those first let's add a visual when waiting for a key press so inside the game options UI let's create an empty game object call this the press to rebind team let's stretch it out so put it on zero on everything okay then inside let's add a UI image let's put it in black and once again let's stretch it out okay now let's also add a simple text and for text let's say press a key to rebind as usual let's put the width and height on zero put it in bold Center down the middle with no wrapping and increase the size by quite a bit okay so that's our super basic window now in the code we just want to show and hide this so let's do that and let's actually begin with this hidden by default so let's disable this object so here on the options UI let's add another serialized film it's going to be a transform for the press to rebind key transform so you have this let's make two show and hide functions so we show press to rebind key we just go into that one game objects and active this one into true and another one where we set it to phones so just hide and set it to false okay pretty simple let's make sure to hide this over here on our start okay just like that and for showing let's show it when we actually rebind an action so right in here but since we're going to have tons of listeners to these events let's actually make a nice separate function to handle all of the rebinding logic so down here let's make a function rebind binding we receive a game input.binding then first we show the press rewind key and then let's go into game input access the instance and time to rebind binding and pass in the same binding okay so we have this and now up here on the button event let's just call in this function okay very simple so this will work for actually showing the window but now we need to know when to hide it and for that let's use something that we've used a few times in this course but never directly let's use a c-sharp donate as usual I have a dedicated video on them this is basically how you can define a field or a parameter of a type which can hold a function it's another Super useful CCR feature definitely watch that video to learn all about it let's go here on the game input and down here when we have our rewind binding over here let's receive a second parameter this one is going to be of type action this is one of the built-in dongates it takes no parameters and returns void so this one is perfect for a simple comeback just like this one let's go with on action rebound and we're going to trigger this right here after we achieve the convex so we get the comeback let's trigger this just like that and let's also get rid of these testing logs we no longer need them so just like this now back here on the options UI so we've got that and for the second parameter let's just pass in the function to hide that window so hi the press the rewind key that's it again remember we're passing in the function itself we're not calling it so there's no parentheses we're just passing in the function itself okay so with this let's test so here on the options let's rebind the move W and there you go it does show up to window and now if I press the key you better go down hides okay great so this is working but over here the text is still not updating so over here on the second comeback instead of just calling this function we need to call this and then also call the update visual function so as usual let's use a simple Lambda expression to do exactly both so let's open and close the parentheses and we do exactly this so we hide the price of rebind and then we update the visual okay that's it let's test so here we are let's rewind the move down we press on the T key and there you go we did rebind and it did update all right great now let's just apply this to all of the other bindings so first up here on the buttons let's set listeners to all the buttons so let's see move left actually be moved down then the move left move right the interact button the interact alternate button and finally the pause button and for the bindings this one is the fast binding the interact alternate then the interact then the move this one is the right again make sure you don't make mistakes here you call them the exact same one so they move down okay so all of it is correct here and over here on the player input let's do a switch on our binding so Keys move up we do something and now we could write this code directly up here and then make a move down and write a bunch more code that would work but that would be way too worthy so let's write our code in a nice clean way basically the only thing we need down here is we need to know the actual action we're going to rebind and we need to know the action index so let's just find up here exactly that so an input action for the input action and then an end for the binding index okay and then over here when we have the switch for all of our bindings we just set those so the input action in this case it's going to be the player input actions player and it's the move action and for The Binding index this one is on index one then we're going to have the other moves so they move down is going to be on index 2. then left and right these are on index 3 and 4. okay so we have all these and now for the other ones so for the interact this is the interact action on binding zero then we've got the interact alternate and the pause so interact alternate and the pause and this one is the pause action and the interact alternate action and all of them are on finding index of zero okay so that's good so over here we are assigning the input action and defining index and also one thing we need to make sure to always assign these values so let's make sure to add a default here just make sure it always works okay great so now down here instead of always accessing the move let's access whatever is stored in the input action and for The Binding whatever it is on The Binding index okay so now this will work with all of our bindings so here we are and let's try rebinding all of them so let's put them over here on the side so before it move up let's put on T down on G A on F then D on H for the interact on y interact jumped on J and for the Escape let's put it on E okay so all these Keys have been rebound let's just make sure they work so here I am moving with these keys and yep it does work go up here to interact and do the alt interact and now the pause and if there you go everything works perfectly alright awesome so everything worked perfectly although again we have the same issue as previously so all the keys have been rebound so it's not correct right however now if I stop playing and now if I play again and nope there's the issue the rebinding was lost so just like with the sound we also need to save the new state now thankfully the new input system has a function that makes that super easy let's go down to where we are rebinding things and when we finish rebinding let's just go into the player input actions and let's call this function the save bindings overrides as Json this one is going to return a Json string now if you don't know what is Json go watch my quick video on it basically it's a super easy to understand and widely used file format it's very easy to read and modify it's a format where it's stored as just text so let's look at what this says once we debug down log over here after rebinding something let's see so here if I rebind one of these and if there you go there we have our Json so the override Bindings that overload the move on this ID on this new path so basically we just need to sort this string somewhere and just like we did with the sound let's just store it in the player prefs so first let's define our constant so private constring for the player prefs bindings and let's call this the input bindings okay just like this so then down here after we rebind the king let's go into player prefs and let's set a string on the player prefs bindings and we're going to save the overrides as Json and after we do let's just make sure the player perhaps is correctly saved okay so that saves it then let's go on a way to unload it so over here on awake let's load that let's first do a quick test to see if there's a save so if the player prefs if it has a king and if it has this key if so then let's get it so the player prefs let's get the string on this key that returns this ring and we're going to use the string let's just go into the player input actions and let's call the function load binding overrides from Json just like this and also let's make sure we do this right after we construct the object and before we enable the action map okay so that's really it let's test so here we are let's rebind the move up to T okay hit rebound now stop playing now playing again and you appeared is still rebound to T alright awesome okay so here we created a really nice options menu where we can modify the volume and rebind keys the only issue that we still have is that we can only navigate the menus with the mouse so let's add support for many navigation with a controller in the next lecture hello and welcome I'm your code monkey in this lecture we're going to set up phone controller support for our game including regular actions and menu navigation okay so first let's just set up the controller input I have an Xbox impact controller connected so let's open up our player input actions and over here we have all of our actions and we already made the move one a long time ago so let's just add the bindings for the other ones for example over here on the interact let's add a brand new binding let's go into the path and listen and for interact I'm going to press the A Button and again here you can specify just the a button on Xbox controller or you can use the generic South button which will mean a on an Xbox or cross on a PlayStation or B on a switch or anything else so let's go with the generic one for the internal alternate let's add a binding and for this one I'm going to put it on the X on the Xbox so the button West and for the pause let's add let's listen and I'm going to press the menu which is the start button okay so these are the basic inputs let's make sure they work and thanks to this new input system we really don't need to modify any code let's just save this asset let's wait for the compilation and then we can do a test so here we are and yep I'm using my control to move now let's just wait for the countdown and go up there and pick up a cheese put it and slice some cheese yep I can do that pick up a plate and so on all right so everything works let's also pause and yep that also works okay great so everything works except there are two issues with the GamePad especially one with the movement that I only noticed just now the first issue that we have is the dead zone right now we don't have one so if I just lightly touch my Gamepad joystick there you go it starts moving automatically in Gamepad games you should always have some kind of dead zone to prevent any kind of joy-con drift thankfully that is super easy to Zone let's just go into the player input action so let's go into the move find the left stick binding and over here for the processors let's add one and let's add a stick dead zone so that's it pretty simple this basically considers that inputs under this minimum to be zero and above this maximum to be one so if you have joystick drift where when the joystick is Idle it's always moving by say 0.1 and direction this helps solve that problem except in our case for a game we're only using normalized inputs so actually for our use case let's increase the minimum by quite a bit I did some testing in 0.5 Works quite great and the max that default that is just fine okay so that's it one problem solved let's just go ahead save this Ascent now the other bigger issue that we have is if I approach a counter and I try and look at it it's really difficult it tries moving left and right instead of actually facing the counter that's because the logic that we added in a long time ago that logic to help the character controller feel better when moving on diagonals against the counter that works great for keyboard because it's digital so it's either moving phone and left probably right or on the diagonals but it messes up the control which is analog on the player movement if we are not moving perfectly up or perfectly down then it's considered a diagonal and on a Gamepad it's really difficult to get a perfect just up or just down input we're always going to have a tiny bit of either left or right so that's the issue that we have here and thankfully the solution is actually pretty simple let's go over here on to our player script and let's scroll down into the handle movement function okay so we're doing a can move using the regular move Direction and if it doesn't work then it's over here that we are attempting only the X movement or only the Z movement and for doing that we made it so we can move if there is nothing only on the X and if we have any movement at all on the X so if it is different from zero basically the issue here is if the move dear.x is let's say 0.001 that is still different from zero so it is still going to trigger this logic so basically let's just widen this Gap instead of testing literally just different from zero let's test if they moved here.x if it is under say minus 0.5 F or if moved here dot X if it is bigger than plus 0.5 f so instead of being exactly just on zero we're only going to consider diagonals if we are at least moving 0.5 either left or right so we just did this and same thing over here except we just test for this n so we moved here.z and they move the other dot set okay so like this it should feel much better on the GamePad and still work exactly the same on the keyboard so let's test so here I am moving around and yep now it is much easier to just stay around and look straight at the counter okay so that's great so I can pick up and this is all much much easier and the character is no longer just sliding left and right Non-Stop okay that's great so now that this is working let's set support for rebinding our controller bindings so over here on the game input let's do it just like we did for the keyboard so let's add a bunch more bindings over here on the enum let's add the GamePad interact then the GamePad interact alternate and then the GamePad pause okay so we have our bindings then let's go down and add them to both our functions so of course the text and then the bindings so we're here on the text let's copy pretty much this we're going to have the GamePad interact then we're going to have the other two so the GamePad tracked alternate and the GamePad pause okay now for these bindings we're going to use the same actions so this one is the interact alternate and over here we have the interact and over here on the input actions we saw that we added for all of them on index 0 we have the keyboard and on the next one we have all the gamepads so over here that's literally don't change for the GamePad let's go into bindings and access the array on index one okay and then over here on the rebind binding it's going to be pretty much the exact same thing so let's copy all these change this to the GamePad interact then the GamePad interact alternate and then the GamePad pause some of these all we need to change is just by an index put them all on one okay so with that all of the code over here on the game input is working perfectly now let's go over here into our options UI so we've got all of our buttons so let's duplicate our buttons let's just go into the interactive pause and so on let's duplicate push them to the right side okay and just change the name so let's get into all of them so this one's the game pad interact button then the game pad interact alternate and finally the GamePad Parts okay also inside let's also rename these buttons just to make sure the text works great and let's also make sure that these show up behind the press the rebound key so let's drag them put them above okay so that's our setup over here on the options UI now let's go over here on the options UI script and let's add references to our buttons and to our text objects so let's copy all these the GamePad and add all these this is the pause the interact and the interact confident and then down here the exact same thing let's add all of these okay like this now over here let's drag all of our references so on the options UI let's make sure to always write the correct things so the GamePad interact text the interact alternate text and the pause button text and then the buttons themselves so the pause button interact alt and the interact button again make sure you always drag the correct references so check and double check make sure everything is correct okay then over here for our code let's first handle the text over here so the text for all these so the GamePad interact text then the GamePad interact alternate text and finally the GamePad pause text and we just go the game file pause the GamePad interact alternate and the GamePad interact finally over here on the buttons let's do the exact same thing so Gamepad interact interact alternate and the pause okay so we added everything let's do a test and see if everything is working so over here let's pause the game go into the options and for the interact let's modify this one instead of a and let's put it on B and yeah there you go it did go so let's close let's resume and now let's see so if I approach and I press a nothing happens Press B and there you go it does interact okay awesome so the rebinding is all working perfectly except we have another obvious issue I can pause with the GamePad however now with this pause I cannot click on any of those buttons and if I go back to the main menu over here I also cannot do anything with a controller so at some of that the first step is on the event system object look at how it shows us this warning basically if we're using the new input system we should be using a different input Handler here thankfully this is super easy we just need to click on this button and yep that's it it automatically sets it up now the way that this works is by pre-selecting buttons in order to better see which button is selected we should probably add a more visible color let's go into our pause window so for now let's hide over here the options UI show the pause window and we have these three buttons let's select all of them and over here on the right side on the button we can see one option for the selected color so instead of being white which is going to be really difficult to see let's put something really visible so let's say like a bright green okay like this let's do the same thing for all of the buttons on the options UI so let's show this one and find all the buttons so we've got all of these ones down here and these three ones up here and let's do the same thing so on the selected let's put it all on my screen okay so all the buttons have a nice selected color and just like this if we test and if I pause the game and right now nothing is selected so right now I cannot do anything with the controller however if I press over here with the mouse on this button and then let go once outside the button yep look at that now that button is selected so now as long as that one is selected now if I move with the mouse pad yep now I can navigate through this menu and if I press on a yep I can essentially click that button so that's great basically all we need is to make sure that we select the button as soon as the pause menu shows up so let's go over here on the game pause UI script and then over here let's go into the show function so when we show this window when we do let's go into the resume button and just call the select function this will make it selected so that's it and with this if we test and now here with the game playing if I pause whilst pressing the button on the GamePad and if they go down and selected and now I can select any option okay that's great so now it works fully with just the GamePad except now if I go into options yep now you can see that the button that is selected is on the options one over there on the background so let's also make sure to select a button on the options as soon as the options window shows up so over here on the options UI let's go into our show function and let's just select the sound effects button and just console it okay let's test so here let's pause go into options select any of the Lego that did work okay great except we have another issue as I move up or down over here on these buttons you have a look at that some of them are a bit strange like for example over here on a I'm moving up and look at that it actually selected the resume button behind it so as we are moving up or down we are actually selecting buttons on both menus that's very strange basically what is going on is that since both windows are visible the game is trying to guess which button we want to select basically what is happening is Unity is trying to use automatic navigation if we select the button so let's go for example let's hide the options and show just the game pause okay let's select one of these buttons and over there on the button component we can see navigation is set to automatic and we have a button to visualize and if we click on that yep over here we can see all kinds of arrows for example we we can see one over here on the options that seems to be going to some button in there that is going to be the button that is showing over there so if we move down from the options we're going to end up over here on the interact alt button now usually the automatic navigation actually works very well the only reason why we're having problems is because we have both windows active at once one solution to this is to make the navigation explicit so let's hide the options here and over here on the resume on the navigation instead of automatic let's put none and then let's select explicit and if now we have our own four Fields so we can decide which object gets selected when we are here and we move up down left or right so for example here we would drag for the up going up we could go into the main menu so we will drag that button and going down we could drag the options button so that's one solution just add the explicit navigation to every single button or another simpler solution is let's leave this one on automatic and it said we're just going to hide the pause window once we are in the options window so over here on the game pause UI let's see over here we are showing the options you Ai and when we do let's just call hide on this so we are going to hide this window when we show the options and then on the options we want to know when the options closes so that we can show this one again so over here on the show function let's receive an action this is what we're going to do when we close the options let's call it on close button action and let's store it up here so let's store a simple and private action for this okay so we have this and then down here when we have our show function when we have let's set this equals this we store this and then we're just going to run this action whenever we click on the close button so let's go over here the close button we've got that one let's hide the options window and Trigger this action so now we need is over here on the game plus UI let's pass in and basically when we close the options UI we want to show the POS UI okay so let's test so here we are let's pause the game okay let's go into options and open it and if there go it only shows the options and over here moving up or down works perfectly and moving left and right also works perfectly and now if I want to go back let's go into close press it and there you go back into the pause menu all right awesome so everything is working perfectly now the last thing we need is over here on the main menu so let's do the same thing first let's open up the main menu scene let's save the changes okay and over here let's begin by doing the same thing on the event system so let's replace it okay great then let's go inside our canvas inside main menu y let's select our buttons and once again let's modify the select color put it on my screen all right and since over here we only have one menu we could set a test selected over here on the main menu UI script that's one option or we can just go into the event system and over here on the event system there's a film for the first selected so you can just drag the play button and that will automatically make it the selected one so it says and yep the play button starts off as selected and I can move up or down and if I press a button yep there you go here I am playing the game I can pause I can resume go back to the main menu and so on all right awesome so here we have the final thing we needed to make our game fully playable with the GamePad thanks to how the input system works and the menu automatic navigation this was a pretty simple task for this our game is pretty much completely done however the next lecture is also one of the most important lectures it's all about publish so let's do that in the next lecture hello and welcome I'm your code monkey in this lecture we're going to add all kinds of small things to polish our power game if you are regular on this channel then you've certainly heard me say that polish is what separates good games from great games so as you build your own games make sure you don't neglect polish here let's add a bunch of small tiny things that will make a big difference in the final game let's begin with a very simple very visual one let's just add some ones to our map and first let's just hide our canvas so that it's not blocking our view so again over here we can use the buttons on the hierarchy to hide it okay great so let's add some walls and for that let's create a brand new 3D cube let's name this a wall let's put it quite a bit thin so over here on the scale for the X so let's put it 0.25 then on the one let's put three so something like this then we modified Z so let's put it over here on the side right next to the counters okay so that's the wall let's just stretch it out One Direction and the other one okay so that's our basic one now when you included project files there's a nice one material so let's go over here into assets under materials and you appeared as you want material so let's just drag it and use this one and if there you go it's just a nice simple gradient this is also an example of how you can take something simple and make it a bit more interesting if you look at this material the base texture is really just this it is literally just a simple vertical gradient texture and then with the color point to it and looks pretty good okay so this dual let's put the wall on on three sides so let's supplicate this so just select and press Ctrl D 2.8 let's put one on the other side so right there right next to the counters okay and finally the one there so Ctrl D to duplicate it let's push it over there on the side and rotate it 90 degrees and let's put it just like that let's just scale it to get to that end and to get to that end okay so we have our nice walls but over here if we're playing the game we can still see the floor on the outside that looks a bit ugly so let's fix that let's create another object and let's create a 3D object another Cube and for this Cube let's put it over here on the side and this one let's use the black material so again in the included assets there's this nice black material there you go it's completely black nothing to it so let's just use this as kind of a Hider so let's just scale it quite a bit and lift it up okay so there it is a black material right next to the wall and let's put another one over here on the left side and just like that you can also put another one on the back there even though I don't think the camera can see that part but still let's put it so just put it like that and stretch it out okay that's good by the way over here on the outside it doesn't have to be perfect doesn't have to perfectly match the camera is never going to see that position so it doesn't matter it only matters what the camera can see and if we pull it like this and if they're yellow now that looks quite nice if we want over there we can get it together just a little bit and we can also move the camera forward a tiny bit so over here on this one let's push it just a little bit to the left okay and now in the virtual camera let's play the game and now here if we want we can push it up a little bit something like this so let's put it on this set so let's copy it stop playing the game and let's paste it just like that okay so here's our game and as you can see with just this one tiny chain just adding some walls and a nice black outside just with that it already looks so much better than having some counters in wide open space now for another simple one let's add some nice particles while the player is moving so in the included assets if we go inside the prefab visuals over here is a nice one for player moving particles this one as you can see is a particle system so let's drag it over here into the world see what it looks like and as you can see by default it's actually not spawning anything so I can make sure that this one is running and nope nothing is spawning so this is actually set up in a really interesting way is that instead of spawning particles all the time it only emits while moving so if I click to move this object there you go the particles start emitting and if I stop they stop so this one is definitely perfect for a player particle system the way this setup is over here on the emission on rate over time it is set to zero so it doesn't spawn anything automatically and it only has over here the rate over distance so as it moves it's going to spawn that number of particles then the other settings they're all pretty basic so there's some gravity so they fall down just like the stove counter particles simulation is over here on space so that as I move the particle stay behind this is important if I were to put that in local and I move it around look at that this is not what we want we want the particles to essentially stay behind instead of following this transform so that is why this change is super important if that one is set to whirl and as I move yep the particles stay behind okay great and the other property is around pretty basic for the shape it's a cone pointing upwards then for the size of our lifetime again just a basic curve constantly becoming smaller and smaller and down here on the renderer instead of rendering your quads actually rendering a mesh and it's rendering a sphere mesh so that's just so that it looks a little bit better I think than just having a Sprite particle okay so that's it so in order to make this work really all we need is just attach it to the player so let's find the player make this object a child of the player game object and again let's also make sure to set all of this to zero so the position on zero zero and zero and there you go just with this that's all we need if we test here we are stopping there are no particles and as I start moving if there you go some nice particles around the player okay great next let's add a pretty obvious one some kind of mini tutorial we want a window to show the controls and the goal of the game and wait for the player input before we start the countdown so for that let's go into our canvas so let's show our canvas and inside let's create an empty game object called the tutorial UI let's drag this one above the game pause window so that it shows up behind it let's double click to center it and let's press on the 2D button to go into 2D mode okay let's also hide those two windows so you can actually see what we're doing so outside all of these okay great now this one first of all let's stretch it to occupy everything so put zero on everything okay then inside let's make a UI image for our background once again let's stretch it put it like this and for this one instead of black like we've used for all of our Windows let's actually leave it on white put it on an alpha something like half so something like this just to be a bit different then on top of this let's make another image so let's make another UI image and for this one instead of stretching let's give it a size so let's put it on 1280 by 800 and for the image I created a nice image for the tutorial if we go inside the assets and then inside textures yup here is a really nice tutorial image so let's just go ahead and use it so on the image let's drag it all right there's our nice internal image so this has a pre-based tutorial so the recipe is coming from the customers then the player has to prepare the correct recipes and deliver them on a plate on the delivery counter so just a very base tutorial and also over here it's very important for the player to know how to actually play the game so there are some labels for the controls and now we're going to dynamically add some keys on top so let's do that let's create an empty game object call this the king let's put it on a size of 40 by 40 okay now let's go inside and inside let's make an image let's name this the background and for the Sprite let's go with the included Circle so default Circle and for the size let's stretch it occupy everything put it on zero zero zero okay there's our nice key so we have the background and for the background let's actually make it just a little bit darker and let's also add just a nice shadow so maybe three minus three and let's also make a nice upline let's put it on two by two full Alpha so something like this just to be a nice one maybe one by one okay so that's just the visual and then on top of it let's add a text and this one's essentially going to be the king so let's put a key for the width and height let's stretch it to match the parent size okay then for the phone here let's go with maybe just say 20 let's put it Center down the middle and also let's put it on bond okay so that's our nice key indicator so this is our key and we're going to have the movement so the movement on the keyboard is going to have four keys so let's just implicate so one two three and four Keys okay then on the GamePad that one is actually not rebindable so let's put this one as static so let's just go inside inside the text and just say left stick and let's lower the font size so that it fits in there okay great then for some more keys we're going to have the interact action then the interact alternate and finally the pause action then let's just duplicate these to be on the other side okay so these are all of our keys now instead of having key one two three this is very difficult to understand so let's give it some proper names so this is the key move up then we have the key move down then the key moves left then the key move right then this one is going to be the key Gamepad move then we have the key interact the key interact alternates the key pause this one is the key Gamepad interact alternate this one is the key Gamepad interact and finally the key Gamepad pause okay all of these and since we're going to drag references to the text objects let's also give those a name so just copy drop it with text just like this okay so those are all the names so everything is nice and organized okay great now let's make the script to run this so our tutorial UI let's go down into our UI scripts create the brand new c-sharp script for the tutorial UI and let's attach the script okay so first let's drag references to all of our keys we only need the text so let's do a serialize field of type text mesh Pro U going again never make the mistake always use the ugly one if we're working the UI so the key move of text so let's add all of these okay these are all the references then over here let's drag on and make sure to drag the correct ones okay let's double check to make sure all the references are correct okay they don't seem correct all right great and then over here only to pretty much exactly the same thing that we did over here on the options so we need exactly this so let's copy this and over here and let's do just that let's see a private void update visual and on this one let's do pretty much this so the key move up text I know this one you get binding text to move up yep let's just do all the others okay so those are all the bindings that's great now let's go over here on a proud void start and on start let's update our visual all right and also let's make sure this updates just in case the player rebinds something from the pause menu once the tutorial is still visible so we just need to know when that happens so let's go over here onto the game input and make a nice event so public event even Handler let's call it on binding rebind okay we have this event and down here when we have our rebind binding function we do this we rebind and over here let's invoke this event okay just like this so then on TTR only y let's go into the game input the instance on binding rebind let's listen to this event and as always let's rename this so let's put a game input okay when this happens let's simply update the visual okay that's it pretty simple so let's test and see if the inputs are correct and if there it is we do see it correct so we've got ones we've got e to interact F and over there we've got the GamePad okay great so all the buttons are correct all that's left is the show and hide so over here let's make the usual two functions so product void show and a proud boy in Hind and for these game objects set active and this one is going to be into false and this one's going to be true okay so for show up here on start let's actually show it by default even though it's actually already going to be shown but still okay then for the hind this one we want to hide when we press the interaction however when that happens we don't want just this window to hide we want the kitchen game manager to change the state so we're here on the kitchen game manager we currently have the waiting to start and that one actually has a timer so we count down the timer and then we start whereas right now we want it to be based on player input so let's modify this to not be based on timer so let's just get rid of this timer and now let's see all these errors so I'm waiting to start we are not going to count down any timers instead let's listen to the game input so game input let's listen to the on interact action event and rename this to the game input okay so when we have this event when the player presses the interact action let's check if the state if this one is on waiting to start if so then let's modify the state so let's go into State and we're going to go into the countdown to start and let's trigger the on state changed event okay so that's it so we're only going to change it on the player input and nothing over here on the updates then for hiding the tutorial over here one approach would be to listen to the interact action and hide it but I think it makes more sense for this to only listen to the kitchen game manager state that way if we wanted we could also modify how this one changes the waiting to start so let's listen to distinct over here on tutorial we want let's go into the kitchen game manager the incense and let's listen when the state changes so here we are going to check if the kitchen game manager instance if it is on the countdown to start active so if the countdown is active then we're going to hide this okay so that should do it now let's just do one more small thing the delivery manager is currently spanning a recipe whilst we're still reading the tutorial that's not quite right so let's go over here on the delivery manager and right now this one starts off at 0f and starts counting it down right away instead of only doing it like this let's just make sure that we only spawn a recipe if the game is playing so that's super simple over here kitchen game manager instance is game playing if so then we are going to spawn a recipe and let's do the same thing on the points counter so let's go in the plates counter so here we are on the plates counter so we count on time responsive lights but let's also make sure we only spawn plates if the game swing okay so with all of this let's test and right away here we are we can see our nice tutorial teaching the player how to play okay great here we've got the controls everything and we're currently waiting for an interaction we can see over there plates are not being spawned and recipes are also not being spawned but as soon as I press the E key and if there go the countdown starts playing and we've got everything else any up there you go the game starts and after a while yep we've got plates and we've got recipes alright awesome so next let's publish the countdown visual right now it's pretty basic it's just a static number so let's add a nice animation to it let's go inside the canvas let's find the countdown UI so the game start countdown okay so here it is we just have some basic text now let's go into the main game object and let's add an animator component then let's create a brand new animated controller so let's create a new down here an animated controller for the countdown UI over there let's assign this controller okay now let's open up the animation window so window animation open up the animation window okay let's create an animation clip and over here on let's name this the countdown UI number pop-up okay that's great now for making the animation we want to basically make it shake and also make it fade away so one very useful component is the canvas group so over here once on the parent let's attach a canvas group component this one is a really useful component in this case the main benefit is it let's just easily animate the alpha so let's go ahead and turn on recording let's go into the frame just before one second so let's go into 60 frames because we are on 60 frames per second over here let's record the normal keyframe so let's modify the scale on the tiny bit just to record it and let's reset it back to one okay just to record the keyframe then for rotation let's rotate on Z then put it on zero again just record the keyframe okay great so now we can go back into the first frame and over here let's first make it smaller so for the size let's put it on 0.6 then let's rotate it to the left so let's put 17 over here on the set rotation okay like that now let's move up by just three frames so on frame three over here let's make it quite a lot bigger so let's put it on 1.3 and let's rotate it to the opposite position so -17 okay that's great that's a nice start now let's put it on frame 10 and over here let's set the rotation to zero and for the scale put it on 1.1 okay so now finally over here on frame 50 let's set the alpha onto one and then on one second let's put the alpha zero okay so let's preview and if they go a nice simple animation okay so that was great now we just need to play this when the countdown happens so let's stop recording let's go inside the animator controller so here it is we've got our number pop-up and we basically just want to play this animation whenever we want so let's put it and make a transition from the any state onto the number pop-up on this transition let's make sure we have no exit time and for the settings over here for the duration let's put it on zero so that it's instant okay great now obviously we need a condition so on the parameters let's create a brand new trigger call this the number pop-up let's select that one and Trigger it on this trigger okay great so now for handling this logic here we have the usual question so do we put this visual Logic on the same UI script or do we separate the animations from the UI for me I find that UI is usually part of the visual so sometimes I like to mix the two and sometimes I keep them separate it really depends on a case-by-case basis this visual is so simple and so connected to the actual UI Logics over here let's put them together so let's open up the game start countdown script and over here let's first grab the animator so private animator for the animator and on private void awake let's just get the animator and just get the component of type animator okay so we have the animator now we basically just need to keep track down here where we're modifying the text we're doing this on every update but now we need to know when this number changes so let's basically just keep track of the current number and the previous number so first of all over here an end for the countdown number and we're going to get this so this is our countdown number and over here we set it to string okay and we just need to use a different function so instead of Cl lets you cl2n just to convert the output into an integer okay great so we have the countdown number now we just need to know if this one is different from the previous one so let's go up here let's define a private tint for the previous countdown number then when we go down here we've got the current countdown number okay then just check if it's different if it is different from the current countdown number if so then let's update it so the previous one becomes this one and now let's fire off the animation so let's go into the animator and set the trigger and again we don't want these strings so let's go up to the top of the file make a private cons string let's call this the number pop-up and number pop-up okay so we have this end down here we just set this trigger okay so that's it pretty simple and just for fun let's also add a nice sound effect so let's go over here onto The Sound Manager and let's make a function to play sound so just like we did over here for the play footstep sound let's make another one for this one let's go and play countdown sound and for this one let's not receive a volume or position and we just play let's say just the warning sound so just down on Vector 3.0 and with the current volume okay so we have this function and then down here just going to sound manager instance and play the countdown sound again we could refactor this code to separate the Yuan logic from the animation from the sound that is one approach and sectionally one thing that we're going to do in the next polish stage but this one is also a possible thing since the UI is only so directly connected to visuals okay so with this let's test so here in the options let's just make sure that we have our sound effects so let's make sure they are playing okay great now let's go ahead and play and there you go we have our nice countdown number and there you go it looks great so it looks great and sounds great alright awesome as you can see just by adding a simple animation and some simple sounds that already looks so much better now the next thing we want to publish is on the stove so let's go into our stove back into our counters back into 3D and zoom in over here okay let's also make sure that we hide the canvas just so we can play around this all right great so there's our stove and for this we want to add basically a warning icon on any nice sound when the meat is about to burn so let's go inside the stove counter prefab okay so now inside of this we already have a nice generic progress bar UI and like I mentioned if you want to get some more custom Behavior you can combine a generic bar like this one with some specific components so that's exactly what we're going to do right now so over here let's create a brand new canvas as usual let's make it a world space canvas for position let's put all of this on zero let's just lift it up by a bit so set it on a y of three okay great then let's add our super useful look at camera component and make it camera phone okay now inside let's go ahead create a new image let's put it on a size of 0.5 by 0.5 okay just a nice square and for the Sprite there's a nice warning image in the asset so it's this one here we have the warning okay great basically we want to show this when the meter is about to burn so let's make a screen to run this and on the canvas let's give it a proper name so let's call this the stove burn warning UI okay so let's make this crypto render so when you c-sharp script with the exact same name and over here let's attach a script okay great so now the first thing that we need is obviously a reference to the stove so let's make a serialized film private for the stove counter for the stove counter okay here in the editor let's drag the reference of the sub counter okay great so now we basically just need to know when the food is about to burn and for that we can actually listen to the on progress event so let's do a private void start and on start let's go into the stove counter and let's listen into the on progress change event okay so we have this one and recently we're going to want to show this element so let's find a bone show we're going to want to show this when the progress normalized is above a certain amount so let's define a float for the burn show progress amount and let's say 1.5 so on this one we show it except obviously we don't want it to be shown when the food is just cooking we only want it to show when it's about to burn so that means we also need to check the state on the stove counter so let's make a function to check if we are in the state that we want so we're here on the stove counter let's go down to the bottom and let's make a public bowl is fried and over here we just return if the state equals state DOT frame okay that's great so now here we're going to show if the progress is above 0.5 and the stove counter is on the Fright state all right so that's the logic that we want then we just want to show our height so let's make the original functions private show and a private void hide and just do game objects and active into either true or false and over here if show then let's call the show function and if not let's call the Hide function and of course on start let's start off as hidden okay that's it let's test just over here in the editor make sure the reference is right and let's save the prefab go outside and hit on point and yep right away there's no element okay great now I place it and it won't cooking there's no element and now once it's on the halfway point for burning and if there you go we've got a nice warning okay awesome so now that this is working let's just add a nice animation so once again let's go inside the stove counter and on the burn warning UI let's add an animator controller then let's actually create the animated controller so let's create a brand new animated controller for the stove burn warning UI then let's assign it okay and over here on the animation window let's create an animation let's put it on the same folder and call it for this one let's say flash we're going to make it Flash and then again for making it flash let's use the same component that we used a while ago so let's add a canvas group so here it is now we can play around the alpha so super useful although I should say that at this point since we just have a single image we could just record a change over here on the alpha for the image itself however one place where this component is super useful is if you have multiple images so if over here I duplicate this one and I put it off to the side if I change the alpha on one of them then obviously it only affects that one but if I go over here and I modify the canvas group that changes the amp for both of them so if you have a group of images then using the canvas group makes it super simple so anyway so here we have just our image let's go ahead and record and let's say we start off on Alpha zero then after 10 frames going to Alpha One and after 20 frames back into an alpha of zero okay so that's it a super simple very basic animation we don't even need analogic since we just want this animation to play Non-Stop so that's great that should be working now let's add some sound so for that we could make another script but already on the stove counter we already have a nice sound component so let's open up this grip the stove counter sound so this is basically where we're playing or stopping the sizzling sound so over here we can just add the warning sound we're going to play the sound just like we have over here for the burning UI so let's actually copy these same components and over here let's face it so for this one instead of show let's give it a proper name so play warning sound except it's not on say change so let's actually listen to the other one so still counter on progress change let's listen down and it's on that one that we use this Okay so we've got that one and then for playing the warning sound we're going to want to basically play it every certain amount of time so let's make over here a private void update and an update let's just Define a private float for the warning sound timer and so down here we just count down as usual time dot Delta time and if this one is under zero if so then let's reset it so Define a certain maximum let's say 10 times or maybe just five times per second that should be good so we have this but obviously we only want this to run if we should be playing the warning sound so let's actually save this one up here so probably won't for these play the warning sound and then we set it on this one and down here let's just go and we're only going to run this if play the warning sound then we're going to run our timer logic all right and then over here all we need is to play that warning sound so let's actually go into The Sound Manager and just like we added the countdown sound let's add another one so let's say the play warning sound and for this one let's receive a vector 3 for the position and we're going to play the warning sound on this position so now over here on the stove counter let's go into The Sound Manager the instance and let's play the warning sound and pass in the stove dot transform that position okay that should do it so we now should have a nice warning sound and over here we should have a nice animation on the burn warning UI so let's see both those okay so let's pick up some meat and drop it and right now it's cooking okay great and once it gets a halfway point if there go now we have a nice warning sound all right awesome let's just add one more tiny thing let's make the bar itself also flash red when we're about to burn so once again let's go inside the stove counter and on the progress bar UI let's add a nice animator and let's go ahead and make one so let's create a new animated controller for the stove burn flashing bar let's go ahead and assign it so it's the one on the progress bar let's add the stove burn flashing bar then on this one let's create new animation let's go inside the assets animations let's make one and just call it idle for this one we're going to want the exact same color as the normal color so let's go into the bar and set the color just save a keyframe over there okay so that's what we want now let's make another animation so let's stop recording and let's actually duplicate this one so duplicate it and for this one name it flash now of course we need to add it to the animated controller so let's go over here and drag it on top okay now for the animation let's select the Flash and for this one let's go ahead click on record let's start off on this one and after a few frames so let's say maybe after 10 frames let's Flash in red and after 20 frames let's copy paste the same frame okay so that's our nice flashing bar now let's just set it up so let's go into the animator and over here we're going to have a transition from that deformation form flashback now all we need of course is an animator to control this so let's make a new animator parameter let's make it a Boolean and call it is flashing and again make sure to be careful with cane sensitive okay so from idle into flash let's go ahead remove the exit time for the duration make it instant so zero and for the conditions when that one is true okay great and for going back once again same thing so instant and let's make the condition when it's false okay that's it super simple now let's make a script to run this so let's go ahead create a brainy sharp script for the stove burn flashing bar UI let's go ahead and add it to the bar so that's the flashing bar UI okay over here let's do pretty much the same thing that we did on the other one so let's go over here onto the stove burn warning UI I might actually copy exactly this so let's go on this one and paste this one then back here in the editor let's drag the reference to the self counter and over here the logic is going to be very very similar so the only difference is we have an animator so the animator and we're going to grab it on private wide awake and later get component of type animator so we have the animator then let's define the parameter so private con string for the is flashing and let's set it is flashing okay we have our parameter and now down here instead of showing and hiding we'll just go into the animator in order to set a ball and the bone will be the is flashing and let's set it based on show so either we show or hide and we actually don't need these functions and by default of course let's leave it on false okay so that's it super simple Let's test just make sure to save the prefab and hit on play okay let's go ahead and cook so let's pick it up and drop it alright so it's cooking let's wait for it to be burning and as soon as it gets there yeah there you go we've got a nice warning a nice flashing bar and a nice sound effect so all three warnings making ourselves much more polished alright awesome now just for balancing let's play around the timers so let's go into our script ball objects on the frying rest BSO let's make this one take five seconds then on the burning recipe for this one let's make it take six and finally let's also add another stove so let's take our self counter duplicate the prefab let's put it over here so rotate it to the side and let's get rid of this one and put this one right in there so on 7.5 0 and minus 1. all right so we now have two stoves I can put one cooking put another one and I can start cutting down some cheese start cutting and before they start to burn what's actually here there you go that one is about to burn so let's pick it up quickly and that one is actually gonna burn but I got it okay great all right awesome everything's working great now for one more polish element let's make a nice visual when we deliver either a correct or incorrect recipe I think it wouldn't look good as a warm canvas on top of the delivery counter so let's do that let's over here find the delivery counter let's go inside the prefab and now in here let's create a new UI canvas let's name this the delivery result UI and as usual let's make this a worm space canvas so put it on worst face and for the position let's actually lift it up and then we're going to make it look at the camera but just like this it might actually go inside the wall so let's put it over here to the side a little bit so let's put it on this position so on the X of minus 1.6 on a y of three and on a z of 1.2 okay that's the position so right there that is going to be unlocking at the camera now inside let's create a new UI image it's going to be our background and for the size the width and height let's put it on 2.2 by 0.9 okay that's our background for the Hunger let's tinted in a nice green so let's put it something like this then let's also add a nice outline let's put it on full Alpha and for the size let's put it on 0.1.1 then let's also add a nice shadow component for this one leave it on half Alpha and let's put it on 0.2 and minus 0.2 okay so that's a nice visual now on top of it let's create a new UI text let's call it the message text and for the message we're going to say something like delivery and then underneath success let's put it on a width and height of zero let's put it on a super tiny font so let's say just 0.25 let's put it in bold and put it down Center and get rid of wrapping okay that's it let's just push it a little bit on the left side so on minus 0.32 on the X okay and now next to it let's make another UI image for this one call it the icon image let's put it with a size of 0.5 by 0.5 and put it over to the right side so on an X of 0.7 okay and now for these Sprites including the assets are too nice sprites so there's a nice cross for when we get it wrong and there's a nice tick okay so that's the setup that we want now on the delivery result UI let's go ahead add our own look at the camera component and for this one let's go different so instead of the camera four let's go ahead with the unlock at inverting so there it is this is our setup now let's make the script run this so let's go ahead create the new UI new c-sharp script for the delivery result UI let's attach the script and open okay so now here on let's make serialized films for our elements so a serialized film first of all for the background image and this is actually going to be a Type image image inside in the engine.ui okay our background image then we're going to have another one for the icon image and we're going to have another one this one is a text mesh Pro e GUI for the message text okay let's save okay so let's drag the references to the background the message text and the icon image okay great and over here let's listen when a delivery is delivered so let's make a private start let's go into the delivery manager the instance and we have all of our next events so we've got a success and a field so let's listen into both them so both the success and on the recipe failed let's listen to all these and as always let's write good point code and rename this so the delivery manager on recipe success and for this one is the on recipe failed okay we have both of our events so over here it's actually going to be very simple we just want to play around the text the icon and the background color so for example when we fail let's go and we want to set the background image to about a red so for defining the column let's actually go here and Define a color for the success color and we're going to have another one for the failed color and then for the Sprites let's also have that so Sprite for the success Sprite and another one for the failed Sprite okay those are on the elements so we're here in the editor let's just set them so for the success column let's actually use the exact same color by the way here's a quick tip if you go up to film for example like this one on the color you can right click and copy and then go into delivery results and over here right click and paste there go the perfect color then for the final color let's go with the red maybe a bit darker and also importantly make sure you set the alpha to phone okay so we have a red nice and like that okay then the success Sprite this one is going to be the tech and for the fail this is going to be the cross okay those are all of our elements so over here when we fail let's go into the background image and set the color and let's put the fan color then for the icon image let's set the Sprite to the Fey on Sprite and for the message text let's set this one for delivery and then failed by the way this backward slash n this means a new line so we're going to let you set the text on this one so it essentially means that it won't write delivery then new line and then failed underneath just make sure you're using the Packer slash and not the forward slash so use the backwards one there you go there's a new line okay so that's the on recipe film and now on the recipe success let's use the success color the success Sprite and over here the delivery success okay so that's great that should be working now just one more visual thing let's add a nice animation so just like we did previously let's go over here over here and let's add an animator component let's create an animation for this one for delivery result UI so let's go up here create a brand new animated controller for this and let's go ahead and assign it so delivery result UI all right now let's make an animation so this delivery result UI let's call it just pop-up and for this one let's do just like we did for numbers so let's scale and rotate it however if we rotate that's actually not going to work that is because we have the unlocked camera and this one is already going to be setting the rotation so we would end up with this script finding the animator for the rotation so that would mess things up however one nice and simple solution to this basically we just put this inside another game object so let's create a new game object and let's put it inside what's an empty game object for the delivery result rewind then look at the camera so we have this one now the reason why I created it inside is that so over here we can set everything to zero and now with that one on zero we can go ahead and drag this outside of this object and there you go that one keeps the exact same settings and on this one we can add the unlocked camera component and set it up just like we had so then we'll look at inverting and on this one we're going to make a channel live down and there you go now everything is on zero exactly as it should be and on this one we can get rid of the unlocked camera and now we can indeed play around the rotation so for the animation let's just go ahead and set it so for this one let's go up to one second and let's record a keyframe on a scale of one and on a rotation of zero then let's go back into the beginning and for this one let's scale it backwards so maybe something like this maybe a 15 let's put it quite a bit smaller then let's go up by three frames let's put that one on -15 so rotation on the other side and put it quite a bit bigger and then on frame 10 put it on say 1.1 with a rotation of zero just like that so there you go there's a nice pop-up and for the alpha let's also go over here into the 50 and let's just add the canvas group let's set this one over here is on one and then we scroll it down to zero okay so that's our nice animation let's stop recording let's open up the animated controller and over here let's make our nice animations transition so transition from any state into that one let's make it based on a trigger let's call it just pop-up and for this one this says no exit time duration of zero and let's go when the condition when we have this trigger okay so that's it although one thing by default this animation is going to Loop so let's just go ahead we can select the animation and over here let's just untick Loop time so that way the animation will not Loop okay so that's great now let's go into the script and over here let's get our animator so private animator animator let's get the animator just get component of type animator and let's define over here the private constring for the pop-up so we have this and then when we have either fail or success let's just go into the animator and let's set the trigger for our pop-up both up here and over here now we just have obviously one issue which is that it starts off as visible we don't want that so over here we can just do game objects set active into false in order to hide it and when we get either of these let's set it both to true then afterwards the animation won't make it invisible so it will still be active but it won't be invisible so that's fine so just with this everything should be working as we want so let's test let's just make sure to save it and go back okay so here we are let's try delivering an incorrect plate and there you go Gotta delivery film okay great now let's try delivering a correct one so someone wants a cheeseburger so let's cook it slice some cheese let's get some bread so bread cheese and pick up the burger and deliver and there you go a nice delivery success all right awesome okay so with these handphone changes you can already see how we made quite a big difference in our game we didn't do anything to change any core mechanics we just made what was already there pop out we added a nice visual boundary to make the map look nice we added some nice particles when the character is moving then we added a nice tutorial and controls right as the game starts we also added a bunch of effects on the stove so it flashes has a warning and some sound and lastly we also added a nice pop-up when delivery is delivered whether correctly or incorrectly now of course we can always keep publishing the game until Infinity there's always more small things you can add to punish the game just a little bit more but at this point I'm very happy with what the game looks like so after all this work let's go into the next lecture where we're going to play our game from start to finish and see what we've done hello and welcome I'm your kudmaki in this lecture we're going to look at all the work that we've done and have some fun playing the final game okay so here we are in our nice starting main menu it's simple but it works I actually thinking looks pretty good so we have our main menu working and we also have the unloading system that we made so as soon as I click on Play There You Go loads in loading scene and here we are on the game scene so we start off with our really nice tutorial window and down here we have the controls of course some of these are dynamics so depending on if the player rebinds or something this one is going to update so we can look at this window for as long as we want the game is paused in the background so it's on a paused game state then whenever ready we can interact so again that's the game input class listening to the input and again all of the code in here is really nice and clean so when we press enter key the tutorial isn't directly listening to that but rather the general kitchen game manager that main State machine is the one listening to the input and this one is listening to that state so our logic is very well organized all of the elements only listen to the things that make sense to them so anyways here we have tutorial let's interact and there you go we've got our nice game start countdown some really nice animation really nice sound and yep here we are then we've got our clock showing the game time and on the left side we can see our recipes once again all of the elements they're all Dynamic they're all spawn randomly and the icons for all of the recipes they're also all Dynamic so over here we have the character control that we built we have the collisions that we implemented and of course we have the raycast testing for interaction so we can identify all the objects in front let's begin delivering some recipes so for example we need to cook some meat so let's go ahead put it on the stove so here is the really nice tape machine that we built so we've got all the various States we've got the visual completely separated from the logic so everything is really nice and of course here we have the nice burning elements that we added in the Polish lecture so that one is burned so let's go ahead and use the trash bin to get rid of that so let's go ahead cook another one and let's make a cheeseburger so let's put some cheese let's listen to the aunt interaction key and we can slice the cheese we can pick up the meat pick up the cheese then also pick up some bread and deliver the recipe and there you go our nice polish visual all right awesome so here you can already see everything that we've built the character the physics the logic the input all of the UI elements all of the worm UI elements of the various counters and how they are on prefab variants of the plates the separation between the visuals and logic separation between the sounds and logic of the Polish elements that we made over there the nice shadow graph that we made then of course some of the basic things that a lot of tutorials won't teach you like for example how to make a pause menu how to make the options how to modify the Sound and Music Volume how to rebind the Keys and so on so with all that here throughout this course we'll learn how to make a really nice game with lots of interesting interactions which you can now apply to any kind of game any kind of genre you want so like I mentioned in the very beginning you can take pretty much what we've made here which is really just a character controller and a bunch of interesting interactions you can take everything that you've learned here and make something on a Sci-Fi space like for example make something like Among Us you can make something like FTL or perhaps make some kind of survival crafting game some of the interactions you would have like resource nodes in the world then you can interact together those resources so with that you could build something like rust or Minecraft or Don't Starve so hopefully in this course you'll learn a ton that you can now apply to your own custom original projects and if you've made it this far then congratulations let's go into the next lecture where I'll give you my closing thoughts hello and welcome I'm your code monkey and congratulations you have completed this course awesome seriously congrats looking at the stats on my courses very few people stick with it until the very end so if you're hearing this then that's excellent you're on the top 10 percent it means you are serious about learning game development and I generally hope this course has helped you on your own Game Dev Journey throughout this course you'll learn about the basics of unity and c-sharp you'll learn how to make a character controller how to do a physics raycast and use that for both Collision detection and identifying objects to interact with you'll learn about c-sharp interface and events two extremely useful c-sharp features you'll learn about script mode objects how to use the new input system should graph and tons tons more and the most important thing of all you'll learn how to build a relatively complex game while writing good clean code I really hope that's the main takeaway you'll learn from this course learning how to write better high quality code learning how to refactor how to keep the visuals and logic separate keep the UI the couple from logic learning all those things has now made you a 10 times better developer than when you started so I really hope you enjoyed learning all that let me know in the comments what was the most important thing you'll learn throughout this course I really hope this was very fun and very educational if you enjoyed my teaching style check out my other courses I really think the turn-based strategy course would be excellent for you right now it Dives even deeper into some Advanced topics and since you've watched this entire course all the way you now have all the knowledge needed to follow that course it will help you really simply the final knowledge you gained especially everything related to writing good high quality clean code and since you use Unity check out my ultimate DND overview course it covers lots of tools and features of the engine so you can really use all the tones at your disposal to make any game you can think of alternatively if you like visual scripting I have course on that or learn how to make a really nice Builder Defender game and definitely make sure that you wishlist my upcoming steam game total one Liberation I won't be posting devlogs and in those you will see how the code that I use in my own steam game is on the same level of quality as what you learned in this course okay so that's it for me this course was a ton of work so I generally hope it helped you a ton on your gamedev journey thank you so much for watching and I'll see you next time
Info
Channel: Code Monkey
Views: 979,610
Rating: undefined out of 5
Keywords: code monkey, unity tutorial, unity game tutorial, unity tutorial for beginners, unity 3d, unity, game design, game development, game dev, game development unity, unity 3d tutorial, programming, coding, c#, code, software development, learn to code, learn programming, how to make a game, kitchen chaos, unity beginner tutorial, unity complete free course, unity free course 2023, unity free 2023, unity course, unity course 3d, unity for beginners 2023, unity complete course
Id: AmGSEH7QcDg
Channel Id: undefined
Length: 649min 41sec (38981 seconds)
Published: Mon Jan 30 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.