Learn Unity Beginner/Intermediate 2026 (FREE COMPLETE Course - Unity Tutorial) — Transcript
Full transcript
- 0:00hello and welcome I'm your code monkey
- 0:02and here is a free complete course on
- 0:04making a game from start to finish if
- 0:06you've always wanted to learn how to
- 0:08make a game or if you already know the
- 0:09basics but want to see how to organize a
- 0:11more complex project then this video is
- 0:13for you it's perfect for both beginners
- 0:16and more intermediate users this is a
- 0:18completely free course video but it has
- 0:20the same level of quality as my paid
- 0:22courses or my Steam games you can
- 0:24download the project files to follow
- 0:25along or inspect the final game you can
- 0:28even play the final game directly on
- 0:29Steam we're going to start complely from
- 0:31scratch and build a really awesome game
- 0:33with tons of systems and mechanics
- 0:35building this design requires working
- 0:37with lots of unity and C features so
- 0:39this is a really awesome project for you
- 0:40to learn after following this course and
- 0:43learning all of these techniques you
- 0:44will be able to build all kinds of games
- 0:46in all kinds of genres this is going to
- 0:48involve learning about the basics of
- 0:50unity and C learning how to make a
- 0:52character controller physics rcast learn
- 0:54all about C interface and events using
- 0:56script M objects handling UI the new
- 0:58input system and lots more very
- 1:01importantly everything that we're going
- 1:02to do here is going to be focused on
- 1:04writing good easy to understand clean
- 1:05code meaning that I will not be teaching
- 1:08you bad practices that some beginner
- 1:10tutorials teach the code that we're
- 1:12going to write here is production
- 1:13quality code this is not a throwaway
- 1:15demo the quality of the code and the
- 1:17structure of the game that we're going
- 1:18to build is on the same level of quality
- 1:20as my own Steam games as you can see
- 1:22from the video link this is indeed a
- 1:24complete very thorough course so don't
- 1:27try to watch this whole thing in one
- 1:28setting take your time take take it slow
- 1:30and just focus on learning there are
- 1:32chapters for every single lecture in the
- 1:34video here's a quick overview of the
- 1:36entire course all the steps that we're
- 1:38going to take to reach a final polished
- 1:39game so first of all we're going to
- 1:41start compling from scratch by selecting
- 1:44a Unity version and creating a brand new
- 1:46project with that new project we will
- 1:48then learn all about the basics of the
- 1:50unity interface and setup a layout then
- 1:53the other important part is Visual
- 1:54Studio which is where we're going to be
- 1:56writing all of our code after that comes
- 1:58an extremely important lecture all about
- 2:00coding style and naming rules like I
- 2:02said the code in this course is on the
- 2:04same level of quality as my Steam games
- 2:06so having proper naming rules and good
- 2:08coell is Paramount next we're going to
- 2:10download and import all the assets that
- 2:12we're going to use in the course
- 2:14everything is included so you can follow
- 2:15along with every step of the way with
- 2:17the as important we're going to set up
- 2:19some quick post processing just to make
- 2:21the game look good then for our first
- 2:23piece of logic we're going to make a
- 2:24simple character controller with that
- 2:27logic working we will then Implement a
- 2:29proper character visual with the
- 2:30included assets next we're going to
- 2:32learn the basics of animation and the
- 2:34animator component and with that we're
- 2:36going to make our player really come Al
- 2:38with some simple but really nice
- 2:40animations then we're going to install
- 2:42the cin machine package this isn't
- 2:44actually used too much in this course
- 2:46but I still wanted to include it because
- 2:47it is such a useful tool so I do want
- 2:49you to know about it after that comes
- 2:51another extremely extremely important
- 2:53lecture with regards to writing some
- 2:54good clean code we're going to do a nice
- 2:57refactor to replace the Legacy input
- 2:59manager with the brand new input system
- 3:01learning how to refactor is an extremely
- 3:03important and very valuable skill that
- 3:05will massively improve the quality of
- 3:07your code with that done we're going to
- 3:09implement some nice Collision detection
- 3:11to make sure our character doesn't walk
- 3:12through walls next we're going to create
- 3:15the very first kitchen counter and make
- 3:17a script to handle how to interact with
- 3:19it then we're going to learn all about C
- 3:22events and create a proper interact
- 3:24input next we're going to build a
- 3:26selected counter visual which will
- 3:28require us to learn about the extreme
- 3:29useful Singleton pattern with the
- 3:32counter working we're going to start
- 3:33working on the kitchen objects
- 3:35themselves so these are going to be the
- 3:36ingredients and the plates we're going
- 3:38to use script wall objects to Define all
- 3:40of the types then a very important part
- 3:43of our design is each kitchen object
- 3:45will have to be place somewhere so we're
- 3:47going to take some time to really think
- 3:49about the best way to achieve that all
- 3:50while writing some good clean code next
- 3:53we're going to enable the player to pick
- 3:54up an object in doing so we're going to
- 3:56learn about C interfaces then we're
- 3:59going to make a container counter this
- 4:01is from where we can spawn new objects
- 4:03with that we will enable the player to
- 4:05pick up objects and drop them anywhere
- 4:07where they're space then we're going to
- 4:09make the cutting counter this one
- 4:11enables the player to cut an ingredient
- 4:13into slices so to do that we're going to
- 4:16make an alternate interact action and
- 4:19for handling the cutting we're going to
- 4:20once again use script M objects to
- 4:22define a proper cutting recipe then
- 4:24we're going to learn about a really
- 4:26awesome Unity feature World canvases and
- 4:28use that to display a nice progress Bar
- 4:30for our cutting progress after that is a
- 4:33quick lecture just going to make a very
- 4:35useful generic script to make any object
- 4:37look at the camera next for another
- 4:39counter we're going to build a trash bin
- 4:41this is where the player can drop
- 4:43objects to destroy them then the stove
- 4:45counter this one is going to be quite a
- 4:47bit complex we're going to create
- 4:49recipes for cooking and for burning
- 4:52we're going to learn how to make a basic
- 4:53state machine and handle timers next
- 4:56we're going to make the plates counter
- 4:58this is a simple counter that just
- 4:59spawns a bunch of plates after that
- 5:02we're going to make some custom Logic on
- 5:03the plate to be able to hold other
- 5:05objects with that logic working we're
- 5:07going to build a complete visual for all
- 5:09the objects that can exist on the plate
- 5:12then make a nice UI element on the plate
- 5:14itself to showcase the icons of what
- 5:16exactly is on that plate afterwards
- 5:18we're going to make the very last
- 5:20counter the delivery counter this is
- 5:22where we drop the completed plates and
- 5:24in this lecture we're also going to
- 5:25learn about the unity Shader graph and
- 5:27make a quick simple custom Shader
- 5:30then we're going to build the delivery
- 5:31manager class that generates the recipes
- 5:33that the customers are requesting next
- 5:35we're going to build a UI to showcase
- 5:38the wedding recipes after that comes
- 5:40something pretty crucial we're going to
- 5:42add some music and then add some sound
- 5:44effects for all kinds of game actions
- 5:47with that the game will be almost done
- 5:49so next we're going to build a proper
- 5:50game start and a game end then make a
- 5:53simple main menu and handle scene
- 5:55loading after that handle creating a
- 5:58basic pause window then make an options
- 6:00menu enable the player to modify the
- 6:02audio levels and rebind keys after that
- 6:05we're going to enable menu navigation
- 6:07with a controller and in the end as
- 6:09usual comes a Polish stage so we're
- 6:11going to add all kinds of small tweaks
- 6:13and effects to make the game feel really
- 6:15great like I've said many times polish
- 6:17is what separates good games from great
- 6:18games after all of that we will have our
- 6:21final completed project so as you can
- 6:23see you will learn about tons of Topics
- 6:24by following this course also let me
- 6:27point out one of the reasons why I chose
- 6:29this specific design is because my next
- 6:31free course won't be on taking the game
- 6:32that we're going to build here and make
- 6:34it multiplayer so if you've ever wanted
- 6:36to make multiplayer games then that
- 6:37course will be excellent for you
- 6:39definitely take your time following this
- 6:41course the multiplayer free course
- 6:42should hopefully be out next month or if
- 6:44you're watching this in the future check
- 6:46the links in the description although
- 6:47that multiplayer video won't be starting
- 6:49from where this course ends so
- 6:50definitely make sure you watch this one
- 6:52now if you're new to the channel then
- 6:54welcome and here's a bit about me and my
- 6:56credentials or why you should listen to
- 6:58what I have to teach
- 7:00my name is Hugo and I've been running
- 7:01this Code Monkey YouTube channel for 5
- 7:03years now in total almost 700 videos on
- 7:06all kinds of topics including tons of
- 7:08tutorials sharing my knowledge to help
- 7:10you on your Game Dev Journey I'm also a
- 7:12professional indie game developer making
- 7:14games for over 10 years with eight
- 7:15successful Games published on Steam so
- 7:18what I'm teaching here is based on a lot
- 7:19of years of experience making a lot of
- 7:21games just like with my paid courses I'm
- 7:23always going to be in the comments
- 7:24answering questions so if you get stuck
- 7:26at a particular point or need extra
- 7:28clarification on something go ahead post
- 7:30a comment and I'll do my best to help do
- 7:32make sure you include a time stamp of
- 7:34what you're referring to I will also be
- 7:36updating the pin comment with any
- 7:38frequently asked questions that I see so
- 7:40actually right now go ahead pause the
- 7:42video and scroll down a bit just to look
- 7:43at that comment since on YouTube I
- 7:45cannot update the video after it's
- 7:47published I will be updating that
- 7:48comment over the next months and years
- 7:50with anything that comes up also I've
- 7:52been running this channel for 5 years
- 7:53and in that time I've made almost 700
- 7:55videos so there's lots of topics that
- 7:58I've covered separately in more detail
- 8:00all of those videos are linked in the
- 8:01description throughout this course I
- 8:03will be focused on building this
- 8:04specific game using whatever it takes to
- 8:06build it meaning for example when we get
- 8:08to using C events I will teach the
- 8:10basics about how they work in order to
- 8:12achieve what we want to build but if you
- 8:14then want to learn about C events in
- 8:16more detail definitely go watch a
- 8:17dedicated video and I also made a page
- 8:20on my website for this course it
- 8:22contains a link to download all of the
- 8:23project assets you can also download the
- 8:26complete project files for every single
- 8:27lecture so if you get stuck at any point
- 8:30you can download the code at that
- 8:31lecture and compare with your own
- 8:33there's also references to all of the
- 8:35videos and I will also be including
- 8:37frequently ask questions for each
- 8:38lecture so definitely keep that page
- 8:41open in a second tab as you follow along
- 8:43this course now this free course Took a
- 8:45ton of work to make so I really hope you
- 8:46find this video helpful go ahead and hit
- 8:48the like button if it helps you it's a
- 8:51small thing but it generally does help
- 8:52this video on the YouTube algorithm
- 8:54making this course with a ton of work
- 8:56and by making it complely free it means
- 8:57it will obviously never make as as much
- 8:59money as if I had just made the a paid
- 9:01course I'm perfectly okay with that
- 9:03decision with the hopes that by making
- 9:04it free it will reach and help many more
- 9:06people I'm also a big believer that
- 9:09education should be free so if you can't
- 9:11afford one of my paid courses like if
- 9:13you're just a kid or going through a
- 9:14rough time I still want you to have
- 9:16access to high quality education so you
- 9:18can achieve your Game Dev dreams one
- 9:20easy way you can help me for free is
- 9:22simply by liking this video subscribing
- 9:23to the channel and just watching this
- 9:25course that will hopefully help push
- 9:27this video on the YouTube algorithm and
- 9:29tempet reach many more people another
- 9:31free way to support what I do is I'm
- 9:33currently working on my next team game
- 9:35called total warm Liberation you can
- 9:37wish list the game on Steam wish list
- 9:39matter a lot for steam visibility so
- 9:41just by doing that you will be helping
- 9:42me and just in case you can't afford it
- 9:45and you find this free course useful you
- 9:47can also support what I do in a few
- 9:48other ways I spent a bunch of money
- 9:50making this course I heard an artist for
- 9:52the 3D assets so that I head right to
- 9:54the tribum so that you can download and
- 9:56follow along same thing for the music
- 9:58and sound effects the logo and the cost
- 10:00to upload the game to seam so I would
- 10:02like to at least not lose money on this
- 10:04project hopefully there's enough of you
- 10:06who can afford to help me so that I can
- 10:08at least break even and for one way you
- 10:10can support is I added this exact same
- 10:12course on my website as a regular paid
- 10:14course although I want to be very very
- 10:16clear there is absolutely no difference
- 10:19between this free video and the paid
- 10:20course there is absolutely nothing
- 10:22behind any kind of pay Woll all of the
- 10:25lectures are free all of the SS are free
- 10:27everything is free you don't have to pay
- 10:29for or anything if you can't afford it
- 10:30or you just don't want to the paid
- 10:32version is essentially a donation the
- 10:35only difference is this free YouTube
- 10:36video has regular YouTube ads whereas
- 10:38the paid version on the website doesn't
- 10:39have any ads that's it that's the only
- 10:42thing so the only reason why I made that
- 10:44paid version is just in case some of you
- 10:46can't afford it and you want to support
- 10:47what I do and want to help me break even
- 10:49on this project but again only do that
- 10:52if you can afford it if you can't that's
- 10:54perfectly fine I hope you'll learn a ton
- 10:56from watching and following this free
- 10:57course beyond that if if you follow this
- 10:59course and you enjoy my teaching style
- 11:01perhaps look into my other courses if
- 11:03you like this video then I think you
- 11:05will really like my turn-based strategy
- 11:06course that is the perfect course to
- 11:08follow upon this one it Dives even
- 11:11deeper into some of the concepts used
- 11:12here and it will help you make the jump
- 11:14from beginner to advance and since
- 11:16you're interested in unity I think my
- 11:18ultimate unity overview course would
- 11:19also be very useful to you each lecture
- 11:22on that course is focus on teaching one
- 11:24Unity tool or feature there's already
- 11:26over 50 lectures including plenty of
- 11:28small but very important things that you
- 11:30just wouldn't see in a regular YouTube
- 11:31video if you're interested in visual
- 11:33scripting I have course on making three
- 11:35unique games internally with visual
- 11:36scripting and no code at all or if you
- 11:39prefer code you can learn how to build a
- 11:40nice Builder Defender game so if you
- 11:42enjoy my teaching style in this free
- 11:44course then check out my other ones then
- 11:46of course YouTube has Channel
- 11:47memberships and super thanks so you can
- 11:49use those if you want I also have my
- 11:51patreon if you prefer that and in a lot
- 11:54of my videos I have some affiliate links
- 11:56if you ever pick up anything through
- 11:57those I get a nice Commission and I also
- 11:59have some of my own assets on the unity
- 12:01as store so if you enjoy this recourse
- 12:03and you want to support what I do
- 12:05there's plenty of ways but again don't
- 12:06feel obligated if you can't afford it or
- 12:09you just don't want to that's perfectly
- 12:10fine I hope you'll learn a ton from
- 12:12watching and following this recourse all
- 12:15right so that's enough talk of that for
- 12:16now before we begin building the game
- 12:18from scratch let's inspect the final
- 12:20polished game that we're going to build
- 12:22so let's see that in the next
- 12:24lecture hello and welcome I'm your Cod
- 12:26Maki here let's take a look at the fin
- 12:29game that we're going to build so we
- 12:30start off on a simple but really nice
- 12:32main menu so we've got a nice visual a
- 12:35nice logo and a bunch of useful buttons
- 12:37then of course the game has a nice
- 12:39loading system so when I click on play
- 12:40it's going to load into a loading scene
- 12:42and then finally into the finnal game
- 12:43scene so let's go ahead and play and if
- 12:46there we go here we do see the game
- 12:47scene and right away we see a nice
- 12:49tutorial window so it's telling us how
- 12:51to play the game so the basic
- 12:52interactions and then over here the
- 12:54controls importantly these are all
- 12:56rebindable so over here this element is
- 12:58all dynamic then we can look at this
- 13:00tutorial for as long as we want and we
- 13:01are waiting for the interact to continue
- 13:03there's also a really nice song playing
- 13:05in the background so the game has music
- 13:07now we can look at this tutorial for as
- 13:08long as we want and when we're ready we
- 13:10can interact to continue and as soon as
- 13:12we do y there you go we've got a nice
- 13:14countdown some nice animations a nice
- 13:16sound effect and there you go now we are
- 13:17playing okay so here I am controlling a
- 13:19nice character I can move in any
- 13:22direction there is Collision detection
- 13:24so obviously I cannot go inside solid
- 13:26objects so I can walk around and for the
- 13:28goal of the game over here on the left
- 13:29side we've got recipes that the
- 13:30customers are waiting for so for example
- 13:33One customer wants a simple Burger so
- 13:35for that we got to need to pick up a
- 13:37nice bun so let's pick it up then the
- 13:39burger obviously requires a meat Patty
- 13:41so let's go ahead we can pick one up
- 13:42from here but this one is an uncooked
- 13:44meat Patty so we need to drop it over
- 13:45here on the stove and there you go it
- 13:47starts cooking we've got a nice timer
- 13:49we've got a nice worm bar UI and there
- 13:52you go it keeps counting and we've got
- 13:54some nice Sparkles some nice visuals and
- 13:55over there even a nice indicator telling
- 13:57you the meat is about to burn and there
- 13:58you the meat has burned so now I can
- 14:01pick this up and I'm holding some burned
- 14:02meat so the customer probably doesn't
- 14:04want to eat this so we can go over here
- 14:06to the trash in order to trash it let's
- 14:08try doing another one and do it properly
- 14:10so let's wait for it to cook pick up a
- 14:12plate so we can pick it up directly onto
- 14:13the plate there you go the meat is
- 14:15cooked so let's pick it up then go pick
- 14:17up some bread and there you go here we
- 14:18have our complete recipe so let's go
- 14:20into the delivery counter delivered and
- 14:22there you go a nice delivery success all
- 14:24right awesome we've just delivered our
- 14:26first recipe so then someone else wants
- 14:29a salad so let's go ahead pick up a
- 14:30tomato here we have a big uncut tomato
- 14:33so let's drop it onto a cutting board
- 14:35and now we can interact with it so we
- 14:37can interact with a secondary
- 14:39interaction key and by interacting we
- 14:41cut the tomato so it takes a few cuts
- 14:43and there you go it slices and it sliced
- 14:45into tomato slices so let's do the same
- 14:47thing for the Cabbage here we are
- 14:49holding a regular cabbage then slice it
- 14:51and this one actually takes a bunch more
- 14:53and there you go got both slices okay
- 14:55great so now let's pick up the plate
- 14:57pick up both slices and leave to the
- 14:59customer and there you go got a nice
- 15:00success all right awesome and of course
- 15:03we have a correct identification of if
- 15:05we have a correct recipe or not so if I
- 15:08just pick up an empty plate and deliver
- 15:10it there you go got a final delivery
- 15:11because nobody wants just an empty plate
- 15:14all right so here you can already see
- 15:15quite a lot of interactions quite a lot
- 15:16of systems at work so the character has
- 15:19a nice character controller it has
- 15:20physics interaction you can see how it
- 15:22identifies the counter that is in front
- 15:24of the character I can press a button to
- 15:26interact with the counter and
- 15:27interacting with different counters does
- 15:28different things so if I interact with a
- 15:30clear counter I can pick up or drop
- 15:32things over here I can pick up drop it
- 15:34with an alternate interaction I can do
- 15:36the second action then there's the stove
- 15:38machine so that one has a nice State
- 15:40machine so it counts up over here we've
- 15:42got some nice particles we've got a nice
- 15:44Ploom so all the visuals look really
- 15:45great so we've got some postprocessing
- 15:47we have a bunch of UI elements directly
- 15:49on the world and outside of here we've
- 15:51got some regular UI elements so we've
- 15:53got the recipes with Dynamic icons for
- 15:55all of them we've got a timer over there
- 15:58on the top right corner showing how long
- 15:59we have to deliver all our recipes and
- 16:01on the kitchen counter we're also using
- 16:03a custom Shader so this was built using
- 16:05Shad graph so as you can see lots of
- 16:07interlocked systems then the game also
- 16:09has of course the basics that any game
- 16:11should have so I can pause the game and
- 16:13there you go we've got a nice pause menu
- 16:15so we can resume to go back or pause it
- 16:17again and of course while pause
- 16:18everything is paused so that's great we
- 16:20can go back into the main menu or we can
- 16:22go into options and over here we can
- 16:24play around the sound effects volume the
- 16:26Music Volume we've got all of our
- 16:28controls importantly these are the
- 16:30controls for the keyboard and also the
- 16:32game pad so the game can be played with
- 16:34any game pad so it can be an Xbox
- 16:36controller PlayStation switch controller
- 16:38it doesn't matter all of them work and
- 16:40we can also rebind all these Keys both
- 16:42the keys as well as the gam pad inputs
- 16:45so let's go ahead and deliver a
- 16:46cheeseburg so here's some burned meat so
- 16:48let's toss this then pick up some more
- 16:50meat pick up a plate here we've got some
- 16:52cheese we've got some bread pick up the
- 16:55meat and the liver all right awesome and
- 16:58of course finally a at the end when our
- 16:59timer is elaps here we have a nice game
- 17:01over window showing how many recipes we
- 17:03deliver all right so this is the final
- 17:06game that we're going to build as you
- 17:07can see it involves lots of interesting
- 17:09interactions which require learning lots
- 17:10of different skills we're going to be
- 17:12using C interfaces C events the new
- 17:15input system Shad graphs SC all objects
- 17:18we're going to learn about C events make
- 17:19a character controller handle collisions
- 17:21and so on like I said one thing that
- 17:23we're going to focus heavily throughout
- 17:25the making of this game is on writing
- 17:26good clean code meaning that the final
- 17:28game that we're going to build will be
- 17:30very easy to expand upon thanks to how
- 17:33the code is very clean it will be very
- 17:34easy to add more recipes maybe more
- 17:36counters with more actions maybe things
- 17:38like perhaps washing dishes adding an
- 17:40oven and so on or really you could make
- 17:42something completely different this game
- 17:44is all about character and interactions
- 17:47so that could be whatever you want you
- 17:49could take this as a base and build some
- 17:51kind of sci-fi game something like among
- 17:52amongus or FTL you can make a survival
- 17:55crafting game like rust or Minecraft or
- 17:57don't starve really by learning how to
- 17:59build this game by the end you will have
- 18:01gained the knowledge required to build
- 18:03all kinds of unique and interesting
- 18:04games all right so now that we've seen
- 18:06the final game Let's actually build it
- 18:08just before we do let's get a quick
- 18:09refresher of the absolute Basics you
- 18:11should know in the next lecture hello
- 18:14and welcome I'm your code monkey in this
- 18:16lecture we're going to just get a quick
- 18:18refresher of the absolute Basics you
- 18:20should know in order to be able to
- 18:21follow everything in this course okay so
- 18:24like I said this free course is targeted
- 18:26at both beginners and more intermediate
- 18:27users in order to start following the
- 18:29course you really only need to know the
- 18:31absolute Basics I've made three useful
- 18:33videos with all of the basic knowledge
- 18:35required to follow this course watch the
- 18:37video on how to download install and
- 18:39setup Unity then the quick Unity Basics
- 18:42and the C Basics those three Quick
- 18:45videos contain all of the absolute basic
- 18:47knowledge you need so if you're a
- 18:48complete beginner go ahead pause this
- 18:50video and go quickly watch those and
- 18:52even if you're already somewhat familiar
- 18:54with unity still go ahead and give those
- 18:56videos a watch perhaps in a faster speed
- 18:58just so you know everything that this
- 18:59course assumes that you know here I will
- 19:02assume that you know the basics covered
- 19:03in those videos like what is a game
- 19:05object what is a transform what is a
- 19:07Mony Behavior how scripts have a start
- 19:09and update and some C Basics as long as
- 19:12you know those absolute Basics you
- 19:13should be able to follow everything in
- 19:15this course I will teach everything
- 19:17above the absolute Basics and if you are
- 19:19a more advanced users definitely keep
- 19:21watching the beginning of this course
- 19:23might not have much that is new to you
- 19:25but as we build the game and start using
- 19:26more advanced tools like script V
- 19:28objects C events and interfaces
- 19:30refactoring code and focusing on Project
- 19:32architecture and writing some good clean
- 19:34code if you're not a complete beginner
- 19:37you will still learn quite a lot from
- 19:38seeing how this project is built and
- 19:40again like I said I answer comments
- 19:42every single day so any questions you
- 19:44have just post them there and I'll do my
- 19:46best to help this course is played into
- 19:48lectures they are all as chapters on
- 19:50video so you can navigate around let me
- 19:52also take this time to point out that
- 19:54you are not expected to follow this
- 19:55course in one sitting go ahead and take
- 19:57your time for focus on actually learning
- 20:00remember that's the only goal you're not
- 20:02competing with anyone you're gaining
- 20:04knowledge just for yourself so take as
- 20:06much time as you need rewatch some
- 20:08lectures if you feel you didn't fully
- 20:09get it or just ask some questions
- 20:12whatever you do take your time and just
- 20:13focus on actually learning so again if
- 20:16you haven't done so go ahead pause this
- 20:18video and go watch those three Basics
- 20:19videos with that we're going to have
- 20:21everything we need to get started we're
- 20:23going to start comely from scratch so
- 20:25let's begin creating a brand new project
- 20:27in the next lecture
- 20:29hello and welcome I'm your Cod monkey in
- 20:31this lecture we're going to begin
- 20:32actually building our game so let's
- 20:34create a cum2 project and start building
- 20:36it all from scratch okay so the first
- 20:38thing that we need is to install Unity
- 20:40now I covered this in detail in that
- 20:41other Basics video so here I will assume
- 20:43that you already have Unity Hub
- 20:45installed the first decision we really
- 20:47need to make is choosing a Unity version
- 20:49so on Unity Hub you go into installs and
- 20:50install an editor and now Unity
- 20:52recommends that you use the LTS version
- 20:54or long-term support you should be using
- 20:56that one in most cases it's what it in
- 20:58installs by default which as of the time
- 21:00of this recording the latest one the
- 21:02latest LTS one is 20 21.3 however I want
- 21:05this video to stay up to date for as
- 21:06long as possible so for making this game
- 21:08I'll actually be using version 2022
- 21:10point2 if you're watching this video
- 21:12where as came out then download this
- 21:13version and if you're watching this
- 21:15months in the future after version 22
- 21:17LTS is out then you can use that one it
- 21:19will probably be the exact same thing as
- 21:21version 22.2 so you should be able to
- 21:23follow everything exactly for any
- 21:24changes I will Point them out in the
- 21:26updated pin comment and if you're
- 21:28watching this here in the future and
- 21:29there's an even newer LTS version I
- 21:31would still recommend you follow using
- 21:32the 22 LTS don't worry about using a
- 21:34quote unquote older version everything
- 21:36you'll learn here in this version will
- 21:38still be applicable even 10 years from
- 21:39now so like I said I'm going to be
- 21:40installing this one and in terms of
- 21:42modules doesn't really need anything
- 21:44already have Visual Studio Community
- 21:45installed and all the other ones are
- 21:47unticked so
- 21:51install Okay so the version is installed
- 21:54now let's create a new project let's go
- 21:55into the project tab then create a new
- 21:57project and now first up up here make
- 22:00sure to select the right version so
- 22:01again I'm going to be using
- 22:0322.2 then for the templates this has
- 22:05mainly to do with the unity render
- 22:07pipelines now if you're a beginner don't
- 22:09worry about that too much just go ahead
- 22:11and select the 3D urp template so scroll
- 22:13down this one right here 3D urp make
- 22:16sure you select this one and not the one
- 22:17that says just 3D the urp here stands
- 22:20for the universal render pipeline which
- 22:21means our game won be playable on
- 22:23literally any platform so we can make
- 22:25the funnel game and put it on steam or
- 22:27consoles or mobile it run on everything
- 22:29then over here on the right side let's
- 22:31quickly just download the template there
- 22:32it is it's done now select the name for
- 22:35your project so I'm going to call this
- 22:37kitchen chaos and then select the folder
- 22:40for it all right so that's it again make
- 22:42sure you're using the exact right
- 22:43version make sure using the 3D urp
- 22:45template give it a name a fer and let's
- 22:47head on
- 22:52create all right so it's open and right
- 22:55away you might or might not see a window
- 22:57talking about urp material upgrades I
- 22:59think this has to do with the template
- 23:00not having the default materials updated
- 23:02to the latest urp version so if you're
- 23:04watching this in the future chances are
- 23:05you might not see this one that all but
- 23:07if you do then just go ahead click on
- 23:08okay and it will automatically upgrade
- 23:10all the default materials all right so
- 23:12here we have our basic unity window now
- 23:15since we started a project starting from
- 23:16the urp template we have down here A
- 23:18bunch of urp helper files so you can
- 23:20click to select the read me file and you
- 23:22can see it over here on the right side
- 23:23on the inspector if you want you can
- 23:25browse around these links in order to
- 23:26learn more about urp but in our case for
- 23:28building our game we really don't need
- 23:30this so over here on the inspector let's
- 23:32just click this button to clean up these
- 23:33breed me files just go ahead click on
- 23:35yes and okay that's it so basically you
- 23:38should only have these files in your
- 23:39project window so there's the scene
- 23:41folder and inside we've got the sample
- 23:43scene then we've got the settings and
- 23:44inside a bunch of urp assets all this
- 23:47should have been set up automatically
- 23:48since we use the 3D template and then
- 23:50finally we just have the urp global
- 23:52settings asset now let's just verify
- 23:53everything work correctly so let's go to
- 23:55the top left go into edit then go down
- 23:57into project settings then over here
- 23:59let's go into the graphics Tab and you
- 24:01should see the urp High Fidelity asset
- 24:03assigned by default if not you can click
- 24:05on the circle icon and assign it then
- 24:07the other menu is over here the urp
- 24:09global settings again this one should be
- 24:10set by default then down here on the
- 24:12equality tab on this one make sure High
- 24:14Fidelity is selected basically whatever
- 24:16you select here is the quality that
- 24:17we'll be using in the editor and in turn
- 24:19the selected quality over here also has
- 24:21a render pipeline asset now in order to
- 24:23avoid any confusion let's actually get
- 24:24rid of the other ones so let's just
- 24:26click on the trash icon to get rid of
- 24:27the performance and the balanc quality
- 24:29so just click and click okay so we only
- 24:31have this one then let's close the
- 24:33project settings and let's go into the
- 24:34settings folder and over here let's
- 24:36select the urp balance there are two
- 24:38assets for each quality so select those
- 24:39leave the High Fidelity and the
- 24:41performance and let's delete these all
- 24:43right that's it by the way if you made a
- 24:44mistake and accidentally deleted
- 24:45something don't worry you can always
- 24:47just click over here on the plus icon on
- 24:48the project window and then go over here
- 24:50under rendering and you can create a new
- 24:52urp asset with universal render okay so
- 24:54just like this so we only have one
- 24:56quality setting we have high fidelity
- 24:58the quality setting is using this render
- 25:00pipeline asset which is also using this
- 25:01renderer so that's really it with this
- 25:03we have the absolute bare minimum we
- 25:05need if in the end after building the
- 25:07whole game you want to provide multiple
- 25:08quality settings then you can come back
- 25:10to this menu and recreate them but in
- 25:11order to avoid confusion while building
- 25:13the game let's keep things like this as
- 25:14simple as possible okay so that's the
- 25:16basic setup done next we want to prepare
- 25:18our layout so let's continue on to the
- 25:20next
- 25:21lecture hello and welcome I'm your Cod
- 25:23monkey in this lecture we're going to
- 25:25learn about the UN layout and set it up
- 25:27so first first things first let's
- 25:29familiarize ourselves with the various
- 25:30Unity Windows to create our own layout
- 25:32it's very important that you feel
- 25:34comfortable with your layout that you
- 25:35have easy access to all the things that
- 25:37you need and you know where everything
- 25:38is you can see that there's lots of tabs
- 25:40everywhere over here on the N window all
- 25:41of them can be dragged and dropped in
- 25:43any different position so you can
- 25:45customize your layout to get it looking
- 25:46exactly as you want you can set it up in
- 25:48any way but it will be easier to follow
- 25:50this course if you're following the same
- 25:51layout as me I'm assuming you've seen my
- 25:53quick Basics video so I'm assuming you
- 25:55know what is the inspector what is a
- 25:57game object what is a trans form what is
- 25:58the console where is the hierarchy and
- 26:00so on if this is the very first time
- 26:02you're seeing the unity interface go
- 26:03watch that other quick video first just
- 26:04to learn the absolute Basics now for me
- 26:06I've been using Unity for over 10 years
- 26:08now so let's see the layout that I've
- 26:10developed over the years first the
- 26:11inspector on the right side just like
- 26:13default that way we always have a nice
- 26:15view of the selected object and whatever
- 26:16scripts and components it has then for
- 26:18the hierarchy I like to put it down here
- 26:20on the left side we're going to make
- 26:22sure that our scene is always organized
- 26:23so we don't need the hierarchy to take
- 26:25up tons of space then with the project
- 26:27files next to it this corner is enough
- 26:28to really browse all the files we want
- 26:30the console to be on the tab right next
- 26:32to it usually I find that when making
- 26:34the game I want to look at the project
- 26:36window but when playing the game I just
- 26:37want to look at the console so keeping
- 26:39them in the same place but on different
- 26:40tabs works great then over here on the
- 26:42center the scene View and again with the
- 26:44game view right next to it okay so this
- 26:46is the basic layout that I normally use
- 26:48now for a couple more options let's go
- 26:50into the project window and on the top
- 26:52right corner you can see over here these
- 26:54little three dots by default it shows
- 26:56you a two column layout so there's a
- 26:57column here and a column here but
- 26:58personally I prefer the one column
- 27:00layout this showcases all of the project
- 27:02files in a nice compact list view the
- 27:04one thing where I prefer the other one
- 27:05is if you're browsing for some visual
- 27:07assets over here you can increase the
- 27:08thumbnail size but for most times I
- 27:10really like to use the onecom layout
- 27:12much more compact also since we're
- 27:14talking about the project window just in
- 27:15case you don't know there's over here
- 27:17this little button with the ey this one
- 27:19has to do with package visibility if you
- 27:20toggle it then some of the install
- 27:22package are hidden whereas if you
- 27:23untoggle it then you can see all the
- 27:25various packages with all the source
- 27:27code and so on you can expand over here
- 27:29the packages and right now it is showing
- 27:30all of them all of them with source code
- 27:32the things everything there and if you
- 27:34click on this then it hides it only
- 27:35shows a bunch of core ones but for most
- 27:37part you really want to leave this
- 27:38teched and leave this one collapse nice
- 27:40and clean okay so then on the console
- 27:43over here once again let's go into the
- 27:44three dots and for the log entry for
- 27:47this one I like to select one line this
- 27:49makes the console nice and compact which
- 27:50I personally prefer you can see more
- 27:52logs without taking up more space and if
- 27:54you want to read the whole log you can
- 27:56always just click on it to see the whole
- 27:57stack now there are also some more
- 27:59options over here if you want for
- 28:00example show the time stamp this will
- 28:02show the time stamp when each message
- 28:04was sent you can use a mono space font
- 28:06meaning a font where every character has
- 28:08the exact same width so a bunch of
- 28:09options but for me leaving it just like
- 28:11this works perfectly fine then also
- 28:13importantly over here these three
- 28:14buttons these toggle the visibility for
- 28:16the TP messages that appear in the
- 28:18console the left one this one is for
- 28:20regular messages we're going to use this
- 28:21a lot then we've got warnings and
- 28:23finally errors if you untoggle them then
- 28:25the messages of that type will not show
- 28:27up on the console so if you ever come
- 28:28across an issue where nothing is showing
- 28:30up on the console make sure all three of
- 28:32these buttons are ticked then on left
- 28:33side on clear you can click on the Arrow
- 28:35to see more options I like to set it to
- 28:37clear on play then collapse this one
- 28:39basically collapses messages that are
- 28:40the same of them into one entry
- 28:43personally I do not like this I want to
- 28:45see every single message as it comes out
- 28:46even if it's repeated I've also seen
- 28:48this lead to a lot of confusion for some
- 28:50people they think their code is firing
- 28:51just one message when it's actually
- 28:53firing hundreds So to avoid any
- 28:54confusion make sure you leave this un
- 28:56toggled then for air pause this will
- 28:58automatically pause the game when an
- 28:59error occurs you should definitely have
- 29:01this one toggled if there's an error you
- 29:02definitely want to know about it you
- 29:04want to know when it happens so you can
- 29:05fix it whereas if you untoggle this you
- 29:07might get some errors and the game might
- 29:09keep playing which will then lead to
- 29:10lots of confusion when something start
- 29:12behaving weirdly so always leave this
- 29:14one toggled and then the editor button
- 29:15this one is for more advanced use case
- 29:17so don't worry about it okay so that's
- 29:19the console then over here for the game
- 29:21view we've got a button here to select
- 29:23the aspect ratio let's go ahead and
- 29:25select full HD this one is a 16x9 aspect
- 29:28ratio so everything is pretty normal
- 29:29this will really only matter when we
- 29:31start working on the UI but still I like
- 29:33to keep it as 16x9 always then on this
- 29:35button that says play Focus we can
- 29:37modify some options basically Focus will
- 29:39play exactly like this on this small
- 29:40window if you choose maximize then it
- 29:42will maximize this window when playing
- 29:43the game and play in Focus won't play
- 29:45the game even when the window is not in
- 29:47Focus then another important one is
- 29:49actually on the same one as the aspect
- 29:50ratio here we've got a button to togg on
- 29:52vsun usually When developing the game
- 29:54you really want to toggle this that's
- 29:55because right in the beginning when the
- 29:56game doesn't really have anything if you
- 29:58leave it un toggled then this might run
- 29:59at like 1,000 frames per second and that
- 30:01will pretty much drive your GPU crazy
- 30:03finally if your game view is looking a
- 30:05bit too pixelated make sure over here on
- 30:07the scal slather make sure this one is
- 30:09not zoomed in this one should always be
- 30:10pushed straight to the left as much as
- 30:12possible okay so that's the game view
- 30:14then over here on the scene view for
- 30:15this one default should be good these
- 30:17two buttons are extremely important
- 30:19pretty much all the time you want to
- 30:20keep the tool handles on the pivot and
- 30:22not on the center if you ever see your
- 30:23handles on weird places always come back
- 30:25to this you want this on pivot pretty
- 30:27much all the time then for rotation
- 30:29sometimes local is useful but for the
- 30:30most part you should probably be keeping
- 30:32it in global then for the grid showing
- 30:34the GD and why yep that looks pretty
- 30:35good a nice little visual grid then
- 30:37you've got a bunch more options if you
- 30:38want then next to it we've got snapping
- 30:41this one we also don't need this for now
- 30:43and finally same thing for increment
- 30:44also don't need this okay then on the
- 30:46right for the draw mode let's leave it
- 30:47on shaded for 2D let's leave this
- 30:49disabled since we're working on a 3D
- 30:51game for lights let's make sure this one
- 30:53is enabled for sound we're only going to
- 30:55add this in the end so it doesn't really
- 30:56matter for now then for special effect
- 30:58usually you want this one to be enabled
- 31:00so it shows everything you can click on
- 31:01the arrow and make sure all of them are
- 31:03toggled the only exception is always
- 31:04refresh you probably don't need this
- 31:06little scene window to be refreshing at
- 31:0860 frames per second so you can leave
- 31:10that one unticked and take all the
- 31:11others then these are for the Hidden
- 31:13Object so let's leave them toggled for
- 31:14the camera here are the defaults and
- 31:16finally gizmos leave them all enabled as
- 31:19the defaults all right so all that said
- 31:21here is the layout that I'm going to be
- 31:22using throughout the course it will be
- 31:24easier to follow the course if you're
- 31:25using the exact same layout as me so
- 31:27ideally you should be using this but
- 31:28again like I mentioned all the windows
- 31:30are customizable so if there's something
- 31:31that you absolutely prefer differently
- 31:33then go ahead you can drag and drop and
- 31:35place any Windows anywhere you want so
- 31:36once you have layout your happy win you
- 31:38can go up here to the top right corner
- 31:40where it says default you can click on
- 31:41it and here you've got a bunch of
- 31:43layouts so you can save your new layout
- 31:44so I'm going to save this one as kitchen
- 31:46chaos and then over here you can select
- 31:48anyone you want for example if you ever
- 31:50have some issues with any kind of weird
- 31:51editor Windows you can load back the
- 31:53default layout and then go back and load
- 31:55your own layout okay so with that our
- 31:57layout is set up the next important
- 31:59thing is setting up visual studio so
- 32:00let's do that in the next
- 32:02lecture hello and welcome I'm your code
- 32:04monkey in this lecture we're going to
- 32:06set up our visual studio all right so
- 32:09with the UN layout set up let's make
- 32:10sure Visual Studio is also set up
- 32:12correctly I'm going to be using version
- 32:1422 Community this one is the free
- 32:16version you don't absolutely have to use
- 32:18the same code ID that I'm using you can
- 32:20use ryer or vs code or whatever you want
- 32:22so let's see my setup for visual studio
- 32:24but first let's actually set up
- 32:25something over here in unity so let's
- 32:27let's go up top into window and then
- 32:30let's open up the package manager then
- 32:32over here on the drop- down menu let's
- 32:34select the packages and select the ones
- 32:35from the unity registry then let's
- 32:37scroll down to find the visual studio
- 32:39editor package so here it is this one
- 32:41this package basically handles the
- 32:43integration with visual studi so you can
- 32:44use the debugger and a bunch of things
- 32:46alternatively there's also a package
- 32:48over here for visual studio code and
- 32:50there's also one over here for jet
- 32:51brains Rider so if you're using a
- 32:53different ID go ahead and install the
- 32:54package for me I'm going to install the
- 32:56visual studio one so this one just go
- 32:58ahead and install okay it's done so next
- 33:00let's go up into edit and let's open up
- 33:02the preferences then over here let's go
- 33:04down into external tools and on the
- 33:06external script editor make sure you
- 33:08select the one you're using so again for
- 33:09me I'm using visual studio 22 and also
- 33:11over here you've got a bunch of extra
- 33:13options now if you want to play around
- 33:15with reading the source code for the
- 33:16various un packages then you can take
- 33:18all these boxes but in our case for this
- 33:19simple game we don't need that so go
- 33:21ahead and leave everything just like
- 33:23this with defaults okay so with this set
- 33:24up now we can go over here into assets
- 33:26and open up the C project and this
- 33:28should open up visual studio and all
- 33:30right so here it is now for some more
- 33:32settings inside of here in my visual
- 33:34studio I have a really nice extension
- 33:35that adds a bit more colors to my code
- 33:37which makes it easier to read and write
- 33:39so up top let's go into the extensions
- 33:41menu and manage extensions and the
- 33:43important one that I've installed is
- 33:44this one vs4 if you want you can go into
- 33:46the online Tab and over here search for
- 33:48it and yep it does show up in here then
- 33:50for the settings on that extension let's
- 33:52go up here into tools and let's open up
- 33:54the options then over here let's scroll
- 33:56down and find vs4 Yep this one and here
- 33:58are all the settings and expand this and
- 34:00a bunch more settings now for me I think
- 34:01these are all the defaults I don't
- 34:03remember if I changed anything the
- 34:04important one is over here the rainbow
- 34:07braces so these have a bunch of colors
- 34:09which make it a bit easier to read the
- 34:10code so let's create a simple script
- 34:13just to see this so back in unity let's
- 34:15go into the project window let's click
- 34:16the plus icon and let's create the brand
- 34:18new C script let's call it just testing
- 34:20wait for it to compile and now let's
- 34:22open now over here I'm just going to
- 34:24write a bunch of simple code just to
- 34:25test it out you don't have to follow
- 34:27this all right so here's a bunch of
- 34:29sample code these are the colors you can
- 34:31see it makes everything a bit easier to
- 34:32read although again this is not a
- 34:34requirement you don't absolutely need
- 34:35this extension but personally I do find
- 34:37it quite useful I find that it helps
- 34:39make the code more readable than having
- 34:40everything be gray okay so that's the
- 34:42setup for this extension next for the
- 34:44text formatting options so once again
- 34:46let's go into tools go into options and
- 34:48then over here let's go into the text
- 34:50editor then over here I think I've got
- 34:52pretty much all the same defaults then
- 34:54we can go into the C rules so here are
- 34:56all the settings if you notice something
- 34:58different on your end go ahead and pause
- 35:00the video and compare the settings but
- 35:01again I think everything here is pretty
- 35:03much default I believe the only
- 35:04difference that I did was over here on
- 35:06the code style over here for new lines
- 35:08personally I like to have the currently
- 35:10brackets on the same line but if you
- 35:12want you can also change it and put it
- 35:13on the second line I think that's pretty
- 35:15much the only difference that I did
- 35:16everything else should be exactly the
- 35:17same as defaults so that's the code
- 35:19style settings and speaking of that the
- 35:21next lecture is very important we're
- 35:22going to talk a bit about naming rules
- 35:24although just before we go let's just
- 35:26clean up our testing SCP so let's close
- 35:28this one click on the X then back into
- 35:30Unity we don't need the script so let's
- 35:32just delete it okay so with that we have
- 35:34Visual Studio set up and ready to go now
- 35:36let's continue in the next lecture to
- 35:37learn about some naming
- 35:39rules hello and welcome I'm your Cod
- 35:41monkey in this lecture we're going to
- 35:43learn something extremely important
- 35:45let's learn about naming rules this one
- 35:46is a very important lecture that you
- 35:48should definitely refer back to whenever
- 35:50you have some questions so first what
- 35:52exactly are naming rules these are
- 35:54really just rules you follow when
- 35:55writing your code it is extremely
- 35:57important that you you are consistent in
- 35:58applying your own rules you don't want
- 36:00one class in your game to be written a
- 36:02certain way and then a different class
- 36:04using a completely different style that
- 36:06would create tons of confusion so naming
- 36:08rules and writing the code correctly is
- 36:10very very important one mistake that I
- 36:12see a lot of beginners do is they send
- 36:14me some code and ask why it's not
- 36:15working then I take a quick look and I
- 36:17see that all of the code is written in a
- 36:19very messy way some functions are in
- 36:20lowercase others using snake case some
- 36:22fields are in Pascal case some in camel
- 36:24case and so on remember that code is
- 36:27case sensitive so it is extremely
- 36:29important that you write the code
- 36:30correctly if you change a character from
- 36:32lower case to uppercase then you are
- 36:33suddenly referring to something
- 36:35completely different if you're a
- 36:36beginner keep that always in your mind
- 36:38code is case sensitive so don't just
- 36:40write code semi-randomly write it
- 36:42properly as if you were doing an English
- 36:44literature test now with that said when
- 36:46it comes to naming rules you can use
- 36:48whatever naming rules you want different
- 36:49people like different rules for example
- 36:51you can use a prefix in your variables
- 36:53you can use a postfix you can use
- 36:55capitals for constants camel case for
- 36:57property snake case for Fields by the
- 36:59way here are the definitions of what
- 37:00those terms actually mean Pascal case
- 37:02starts with a capital and every word is
- 37:04capitalized camel case starts lower case
- 37:06and then uppercase for the first Lector
- 37:08of every other word kind of like a camel
- 37:10hump in the middle and snake case is
- 37:12where you add an underscore in between
- 37:13the words like I said every rule can be
- 37:15valid the important thing is that you
- 37:17are consistent in always following
- 37:19through with your rules as you might
- 37:20know Unity mono behaviors have some
- 37:22default functions you can Implement
- 37:23things like start and update which are
- 37:25written using Pascal case since you can
- 37:27can't really change un's rules at least
- 37:29on function names I would say you should
- 37:31base your rules off of theirs so for
- 37:32functions you should probably be using
- 37:34Pascal case for the other rules like I
- 37:36said choose whatever makes sense to you
- 37:37here are some of my own personal rules
- 37:39that I've developed over the last 10
- 37:41years and the code style that I will be
- 37:42following in this course for functions I
- 37:44use Pascal case just like unity and just
- 37:46like the C standard for function
- 37:49parameters I use chamel case for Fields
- 37:51also camel case properties are in pel
- 37:54case constants are in uppercase snake
- 37:56case then other rule is that I like to
- 37:58add the Tope of the variable as a
- 38:00postfix so if it's a list I open the
- 38:02list if it's an array I open array and
- 38:04now you might be thinking with this
- 38:05wouldn't it be an issue if you change
- 38:06the type then the name is suddenly wrong
- 38:08and the simple solution for that is that
- 38:10if I change the type then I just use
- 38:12Visual Studio to quickly change the name
- 38:13that's it then for the currently
- 38:15brackets like I mentioned in previous
- 38:16lecture I like them on the same line
- 38:18some people have some very strong
- 38:19opinions about this really it's just a
- 38:21visual style and this is the one that I
- 38:23personally prefer if you like new line
- 38:25then go ahead and use that it doesn't
- 38:26change how the code works in any way and
- 38:28a final rule spend some time deciding on
- 38:30a proper name and don't be afraid to
- 38:32rename things you will note how all the
- 38:34code that we're going to write in this
- 38:35course has proper names for everything
- 38:37you should never use a variable with a
- 38:38single letter like X or k the exception
- 38:41of course would be iterated in a for
- 38:43Loop also don't use acronyms or
- 38:45abbreviations those might seem clear
- 38:47right now but in a few weeks you might
- 38:48not remember what they mean remember you
- 38:50don't get bonus points for writing
- 38:51extremely compact code so prioritize
- 38:54making your code readable and
- 38:55understandable even if it requires
- 38:57variables and functions with long names
- 38:59so these are my general rules and the
- 39:01code style that I personally follow
- 39:02figure out what works for you and follow
- 39:04your own naming rules but naturally in
- 39:06this course I will be using my own code
- 39:07style so if when following the course
- 39:09you're not sure how to write some type
- 39:10of code you can refer back to this
- 39:12lecture and watch it again like I've
- 39:13mentioned many times the code that I
- 39:15willon teach you how to write in this
- 39:16course is on the exact same level of
- 39:18quality as my paid courses and my Steam
- 39:20games so as such because that this
- 39:21lecture these naming rules are all
- 39:23extremely important okay so with this
- 39:25very important lecture out of the way
- 39:26now let's start playing with some
- 39:28visuals by importing some Assets in the
- 39:29next lecture hello and welcome I'm your
- 39:32Cod monkey in this lecture we're going
- 39:34to import the project files with all the
- 39:36assets that we're going to use by the
- 39:37way remember that if you have any
- 39:39questions go ahead and post them in the
- 39:40comments I go through those every day
- 39:42and I'll do my best to help okay so with
- 39:44the project created the next thing we
- 39:45want is to import the assets that we're
- 39:47going to use to make this game you can
- 39:48download all of the assets with the link
- 39:50in the description which by the way like
- 39:51I mentioned a while ago that link
- 39:53contains a Unity package that contains
- 39:54both the assets and the finnal game so
- 39:57any download that you get a Unity
- 39:58package just go ahead and double click
- 40:00or click and drag and drop it on the
- 40:02project window here is the asset import
- 40:04window just make sure you select all and
- 40:06let's import okay so here it is this
- 40:08import the assets folder and inside
- 40:10comes all of the assets meshes textures
- 40:12and so on so everything we're going to
- 40:13need and then it also imported inside of
- 40:16it another un package so if you want to
- 40:18import the final project with all of the
- 40:20code already written it's also here if
- 40:22you extract this one you're going to get
- 40:23the complete project files now of course
- 40:26don't do that if you want to follow
- 40:27follow along with the course and be
- 40:28aware that if you're following along and
- 40:30you accidentally unpack this one it will
- 40:32override all of your own files so if you
- 40:34want to inspect the final project files
- 40:36go ahead and do that but do that in a
- 40:37separate project in order to make sure
- 40:39that we have no accidents I'm going to
- 40:41delete this one from the current project
- 40:43so just go ahead and delete okay so
- 40:45that's it and over here we've got all of
- 40:46our really nice visuals we can look in
- 40:48the prefab visuals and over here we've
- 40:50got a vision for a container so there
- 40:53you go that's a container counter then
- 40:55we have a cutting counter we've got a
- 40:56trash B then on the kitchen object
- 40:59visuals we've got all the visuals so a
- 41:01block of cheese we've got some burned
- 41:02meat we've got a plate and so on these
- 41:04are all the nice 3D models that we're
- 41:06going to use in our game and then over
- 41:08here on the textures folder we also got
- 41:10a bunch of General icons as well as
- 41:12actual icons for all of the various
- 41:14parts okay so all of the assets have
- 41:16been important now let's continue onto
- 41:17the next lecture hello and welcome I'm
- 41:20your Codi in this lecture we're going to
- 41:23set up post processing now here let me
- 41:25make a quick note usually when Mak your
- 41:27games you probably don't want to handle
- 41:28on post processing right away you should
- 41:30first get an ugly prototype up and
- 41:32working before worrying about any
- 41:34visuals so normally I would only add
- 41:36post processing much later on in the def
- 41:38process but since this is a course and
- 41:40video format in order for the video to
- 41:41look a bit more appealing let's set a
- 41:43post processing right away now we
- 41:44already have the project set up to use
- 41:46urp so adding post processing is
- 41:48actually super simple it's actually
- 41:50already added by default first before we
- 41:52do that let's rename our scene with a
- 41:53proper name so inside the scenes folder
- 41:55it starts off with sample scene this
- 41:57this will be our main game scene so
- 41:58let's just rename this to game scene
- 42:00okay and now here on the hierarchy we
- 42:02can see by default this scene already
- 42:04contains a global volume game object
- 42:06this is how you actually add post
- 42:08processing and by default you can see
- 42:09that it also already has a sample
- 42:11profile attached this is how you add all
- 42:13the various effects you can click on
- 42:15this link and it will show it over here
- 42:17on the project window now let's build
- 42:18this from scratch instead of starting
- 42:19from this one so let's go into that file
- 42:21into that asset and just delete it okay
- 42:24so now we have no volume profile now
- 42:25let's go ahead and click on new to
- 42:27create a brand new one okay so now here
- 42:28we can add overrides add all of the
- 42:30effects that we want let's drag some
- 42:32visual meshes that we imported in the
- 42:34last lecture to get a better look at all
- 42:35these effects and what they do so first
- 42:37let's make some kind of floor so let's
- 42:39make a 3D object let's make it a plane
- 42:41let's name this the floor also one
- 42:43extremely important thing whenever you
- 42:44create a brand new object always check
- 42:46the object's transform position by
- 42:48default when you create an object it
- 42:49appears in front of the scene camera
- 42:51which will probably not be on 0000 you
- 42:54always want to be very careful with the
- 42:55position of your actual objects so for a
- 42:57plane we do want this to be on the
- 42:59origin so on 0 0 0 so make sure you
- 43:01always do that then let's scale it up a
- 43:03bit so on the scale let's put it on 555
- 43:06which by the way you've got this nice
- 43:07little icon this was added in a recent
- 43:09Unity version basically if you enable
- 43:11this then it matches all of these values
- 43:12so if you just change one of them it
- 43:14changes all of them so let's put this on
- 43:15Five okay great now for the visual let's
- 43:17go ahead into the mesh render on the
- 43:19materials and let's select the brand new
- 43:20materials so let's click on the circle
- 43:22icon and over here let's find the floor
- 43:24material so here it is it's the one
- 43:25included in the assets there you go
- 43:27we've got a nice basic for material now
- 43:29let's also drag the player visual so
- 43:31let's go inside the assets folder and
- 43:32over here let's go inside the prefabs
- 43:34visuals and down here we find the player
- 43:36visual so let's just go ahead and drag
- 43:38this one so there it is a nice player
- 43:39visual let's also drag a counter so
- 43:42let's find let's say the Clear counter
- 43:44let's drag this one let's rotate it to
- 43:46face the camera something like this and
- 43:48let's also put a cutting counter again
- 43:49we're just placing some visuals just so
- 43:51we can see what the post processing will
- 43:52do and let's also place a bunch more
- 43:54things so let's say a tomato let's place
- 43:56a tomato over there and maybe cabbage
- 43:58all the way over here okay so we've got
- 44:00a handful of nice visual elements so we
- 44:02can test out our post procing by the way
- 44:04here's a quick inty tip on scene
- 44:05controls whenever you are on the scene
- 44:07view which make sure you're on scene
- 44:08View and not game view those are
- 44:09different so on the scene view you can
- 44:11move the camera with a mouse you can pan
- 44:13with mouse 3 so the middle Mouse button
- 44:15so hold that and pan it around you can
- 44:16rotate with the right Mouse button you
- 44:18can rotate around the point by holding
- 44:20down left alt and left click and just
- 44:22drag it around to rotate around an
- 44:24object you can select an object like for
- 44:25example player visual then then you can
- 44:27press on F to select that object and now
- 44:29if you hold alt and click it will rotate
- 44:31around that object also another method
- 44:33is you can hold the right Mouse button
- 44:34to move it around and then you can use
- 44:36was to move so d a and so on then you
- 44:39can even press shift to move in faster
- 44:41and you can use the scroll wheel while
- 44:43holding down the right Mouse button or
- 44:44to modify the speed at which you move so
- 44:46there are plenty of camera controls to
- 44:48really get you seeing exactly what you
- 44:50want to see now for another quick un tip
- 44:52you can move the scene camera to where
- 44:53you want the game camera to be so let's
- 44:55say I want the game camera to see things
- 44:56from about this angle so you just
- 44:58position the scene camera then on the
- 45:00higher key select the camera game object
- 45:02so the main camera right here and with
- 45:03that object selected you press control
- 45:05shift and F and if there you go you can
- 45:07see over here on the camera preview let
- 45:09it position the main camera looking on
- 45:10the exact same position at the exact
- 45:12same direction as the scene camera so
- 45:13that's the shortcut control shift F or
- 45:15alternatively go up into game object and
- 45:17over here Aline withd view now if you
- 45:19look here is the scene View and over
- 45:20here we've got the nice camera view so
- 45:22just position the camera somewhere where
- 45:24we can view all the Assets Now with this
- 45:26let's add some post Crossing effects so
- 45:28first let's select the global volume
- 45:29game object and over here we can add all
- 45:31of our effect overrides first up let's
- 45:33begin by adding tone mapping so there
- 45:35you go we've got the effect and over
- 45:37here we've got a nice little checkbox so
- 45:38you can enable it in order to enable
- 45:40this effect and set one of the options
- 45:42now for this one I'm not too familiar
- 45:44with color correction but I find that
- 45:45usually adding a neutral tone map
- 45:47usually that helps also make sure you're
- 45:49looking at the game View and not the
- 45:50scene view if you're looking at the game
- 45:52View and you enable and disable this
- 45:53effect you should see a difference
- 45:54whereas on the scene view if you enable
- 45:56and disable doesn't actually show that
- 45:58even if on the scene view over here you
- 45:59have all the effects enabled even with
- 46:01that some effects for some reason don't
- 46:03show up on the scene view so when
- 46:04playing around these effects always make
- 46:06sure you're looking through the game
- 46:07view so like I said you should be able
- 46:08to talk on this and see a visual
- 46:10difference on the game view if you don't
- 46:12then make sure the camera has
- 46:13post-processing enabled so let's select
- 46:15the main camera game object and down
- 46:16here there's the tole for post
- 46:17processing make sure this one is enabled
- 46:19and then also on the render pipeline
- 46:21asset so let's find that one on the
- 46:22project window over here we've got the
- 46:24settings and you've got the urp High
- 46:25Fidelity this one should be using a
- 46:27renderer so if you click on the renderer
- 46:29over here you should have post rossing
- 46:31enabled again all of this should already
- 46:33be correctly set up by default so if you
- 46:35go into Global volume enable or disable
- 46:37you should see a visual difference okay
- 46:38so next Effect one that I always like to
- 46:41add is a bit of saturation so let's add
- 46:43an override post procing and let's add a
- 46:45brand new here it is color adjustments
- 46:47then over here you've got plenty of
- 46:48things to play around in for me I like
- 46:50to add a bit of saturation so just lift
- 46:52it up a little bit let's say just about
- 46:5420 and I also like to add a little bit
- 46:56of contrast over here let's also add 20
- 46:59and there you go it makes the colors pop
- 47:00a little bit more so personally I like
- 47:02this effect then later on we're going to
- 47:04have some glowing objects for example
- 47:05the stove let's actually try dragging
- 47:07that into the scene so let's go into
- 47:09scene View and in the assets let's find
- 47:11the stove counter so here this and
- 47:13inside the stove counter there are some
- 47:16things so here is the stove on visual
- 47:18this one is disabled by default so on
- 47:19the inspector let's just enable this
- 47:21game object to make it visible again
- 47:22don't worry about the positioning of the
- 47:24objects on the scene view right now
- 47:25we're only positioning them just set up
- 47:27the post processing we're going to
- 47:28delete them all at the end of this
- 47:29lecture okay so that one enable let's go
- 47:31into the game View and over here we see
- 47:32the stove enabled so now let's go into
- 47:35the level volume let's set an override
- 47:36go into post pressing let's add a bloom
- 47:38effect so right now notice how that one
- 47:40is not glowing red hot for that to work
- 47:42we need to have Bloom and we need to
- 47:43enable the threshold and the intensity
- 47:46if we raise the intensity we do see yep
- 47:47there we go a really nice glow there by
- 47:49the way here's a quick visual tip if you
- 47:51want to make your game feel a bit more
- 47:52ethereal and magical one good way is to
- 47:54put the Threshold at a low value below
- 47:56one so something like 0.5 and then put
- 47:58the intensity as a little bit and with
- 48:00this notice how everything has a slight
- 48:02low even colors that don't have any
- 48:04extra intensity so the floor is glowing
- 48:05the character is glowing so everything
- 48:07looks quite a bit ethereal this is a bit
- 48:08extreme but it is an interesting effect
- 48:10also another quick note here in case
- 48:12you're not seeing anything change make
- 48:13sure you go into the render pipeline
- 48:15asset so the urp High Fidelity and over
- 48:17here make sure AGR is enabled you can
- 48:19look at the so low if I disable it yep
- 48:21that one stops glowing and with that
- 48:22enabled it does start glowing HR stands
- 48:24for a high dynamic range so that is how
- 48:26you can have a color go with an
- 48:28intensity above one which actually makes
- 48:29it low when you have the balloon post
- 48:31pressing if even with that you're still
- 48:32seeing issues then make sure you go into
- 48:34the renderer and over here for the
- 48:35postprocessing sometimes Unity has a
- 48:37weird bug and doesn't generate this
- 48:38postprocess data file so if that does
- 48:40happen just go ahead un toogle and
- 48:42toggle this and it should work and
- 48:44finally like I said on the camera make
- 48:45sure you have post procing enable so
- 48:47with all of that you should be able to
- 48:48see the game view glow okay back into
- 48:50our effects with our Bloom working like
- 48:52I said you can lower this below one to
- 48:53get a nice ethereal look but this is a
- 48:55bit too intense on what we want so let's
- 48:57make it a bit more subtle so on the
- 48:58threshold let's put it at 0.95 so
- 49:00there's a slight low on the white Parts
- 49:02but nothing too intense and for the
- 49:04intensity let's put it at a r one okay
- 49:06so I think that's a nice amount of Bloom
- 49:07all the colors glow a little bit and we
- 49:09can see over there the stove it is
- 49:11indeed glowing okay great now if you
- 49:13ever forget all these steps and you
- 49:14can't get your project to Glow I made a
- 49:16nice video with a nice checklist of
- 49:18everything needed for you to Glow
- 49:19definitely go ahead and watch that video
- 49:21whenever you have issues then for
- 49:22another fun effect we have vignette so
- 49:25let's go into add override post pressing
- 49:27and let's find the vignette what this
- 49:28one does is adds a bit of Darkness to
- 49:30the colors so if we enable on the
- 49:31intensity and we increase it you can see
- 49:33what it does so it adds Darkness right
- 49:35on the corners there personally I find
- 49:36this one looks good when it's quite a
- 49:37bit subtle so let's put the intensity at
- 49:39some like 0 25 and then for the
- 49:42smoothness let's also put it on point4
- 49:44so just like that just a slight Darkness
- 49:46on the edges so personally I think it
- 49:47looks pretty good and that's pretty much
- 49:49it for the Post pressing on the volume
- 49:51component I like how this looks you can
- 49:52see difference with the volume enabled
- 49:54or disabled quite a big difference looks
- 49:56pretty nice
- 49:57but again these are just visuals so feel
- 49:58free to play around maybe add some more
- 50:00effects use in different settings these
- 50:02are just visuals they don't impact the
- 50:04game logic at all so feel free to make
- 50:05it work exactly as you want it then yet
- 50:08another thing related to post procing
- 50:10but not in this component is some
- 50:11anti-aliasing for that one place where
- 50:13you can change it is on the main camera
- 50:15over here you see a field for post
- 50:16rossing and you have a bunch of types so
- 50:18FXAA or SMA or if you want some more
- 50:21higher end post pressing you can go into
- 50:23the rendom pipeline asset so urp high
- 50:25fodell and over here we anti analing
- 50:27msaa this one is a bit more expensive
- 50:29but looks a bit better if you want to
- 50:31see the difference you can go over here
- 50:32into the game View and on the slider up
- 50:34top on the scale you can increase this
- 50:36quite a bit so with this we can now see
- 50:38the pixelation and you can see over here
- 50:39if I switch anti eling from 4X back into
- 50:42disable you can see lots of jagged edges
- 50:44and if I put it on 2x Yep looks a bit
- 50:46more smooth 4X a bit more smooth and 8x
- 50:48even more smooth so with that you can
- 50:50see difference on all the edges all the
- 50:52things by default this renderer has on
- 50:544X and nothing on the camera this
- 50:56already looks pretty good but to make
- 50:57the video look even better I'm going to
- 50:58put it on 8X and on the main camera I'm
- 51:01also going to leave it with no antiy you
- 51:03can combine them but if you do then
- 51:04everything looks a bit too blurry so I
- 51:06don't quite like that effect so put this
- 51:08one on none and the other one on 8X
- 51:10although again this is just a visual so
- 51:12if you have a low NPC feel free to go
- 51:14into the urp and over here disable
- 51:16anling so the game looks a bit worse but
- 51:18it will run much better okay let's drag
- 51:20the scale back down okay now one final
- 51:23thing we can add is some really nice
- 51:25screen space ambient inclusion for that
- 51:27let's go into the renderer so not the
- 51:28render pipeline asset the renderer and
- 51:30over here by default it already added
- 51:32screen space amb inclusion if it didn't
- 51:33add you can click on ADD render feature
- 51:35and over here you won't be able to see
- 51:37it I don't see it because I already have
- 51:38it okay so here it is basically what
- 51:40this effect does is it adds some tiny
- 51:42Shadows where geometry intersect if we
- 51:44enable and disable it quickly we can see
- 51:46the effect over there on the counters so
- 51:48you can see with the default effects it
- 51:49already Works quite nicely for example
- 51:51look that on the player we can barely
- 51:53see the difference between the head and
- 51:54body but if we enable this it adds that
- 51:56nicely Shadow I think it looks really
- 51:58nice but then we've got a bunch of
- 51:59settings we can play around increase
- 52:00intensity the radius and so on Now One
- 52:02important thing when setting all these
- 52:04effects is to remember the point of view
- 52:06of the camera in this case we're making
- 52:07a top down game so before we play around
- 52:10these settings let's actually position
- 52:11the camera in a correct position so
- 52:13let's go ahead select the main camera
- 52:15and let's position it above pointing
- 52:17down so let's put it on an X of zero on
- 52:20a y of 21.5 on a zed ofus 21.3 then for
- 52:24the rotation on the X for six then 0 and
- 52:27zero and finally on the camera over here
- 52:29on the field The View instead of 60
- 52:30that's really wide for this game let's
- 52:32go with 20 okay so this is the view that
- 52:34we're going to use for our game let me
- 52:35just rotate the objects so they actually
- 52:37face the camera so on the hierarchy
- 52:39let's just select all the objects let's
- 52:41rotate them all around and just position
- 52:44them again we're only using these just
- 52:46to see what they'll look like we're
- 52:47going to delete all of these objects in
- 52:49a bit okay so yep that's the game view
- 52:51now that we have the camera set up let's
- 52:53work on the settings for the EM
- 52:54inclusion so let's go down select the
- 52:56render and over here for the settings
- 52:58for the intensity let's put it on four
- 53:00for the radius let's put it AT3 and the
- 53:02rec lighting strength let's put it all
- 53:03the way up to one okay so you can toggle
- 53:05this enable and disable to see the
- 53:07difference and yep I do think these
- 53:08settings look pretty good finally the
- 53:10last thing we need to check is the
- 53:11lightning window so let's go into window
- 53:13then down into rendering and let's go
- 53:15into lighting out pops up the lighting
- 53:16window personally I like to Anchor it
- 53:18over there next to the inspector and
- 53:20over here we're really going to leave
- 53:21everything on defaults so you can leave
- 53:23it as the lighting settings assets and
- 53:24nothing assigned and then on the
- 53:26environment tab over here again all the
- 53:28defaults I didn't touch any of these so
- 53:30you've got environment lighting from the
- 53:31Skybox intensive multiplier of one so
- 53:34everything pretty much on defaults
- 53:35although again like I said most of these
- 53:37visual effects are very much personal
- 53:38preference so if you want to make your
- 53:40game look a bit different than mine then
- 53:41go ahead you can play around with
- 53:43lighting over here you can change Skybox
- 53:45to gradi and color and so on if you want
- 53:47you can use some bake lighting then if
- 53:48you want you can add all kinds of extra
- 53:50effects and also by the way remember
- 53:52that the effects are sored on this
- 53:53profile over here so for example you can
- 53:55click over here here on the Clone button
- 53:57and it won't clone the effect so let's
- 53:58click on it to find it yep there you go
- 54:00so that's the one that I built and
- 54:01here's a clone one so if you want you
- 54:03can make a clone one and then make it
- 54:04look very different for example let's go
- 54:06into chromatic aberration make it really
- 54:07intense and for example let's go into
- 54:10the color curves and over here for some
- 54:12reason let's drag the green up and so on
- 54:14so there you go completely different
- 54:15visual so if you want to play around
- 54:17make some weird effects and if you want
- 54:18to go back just revert back into the
- 54:20original profile personally I'm quite
- 54:21happy with how this looks so I'm going
- 54:22to be using this one okay again you can
- 54:24enable and disable the volume game
- 54:26object to see quite the big difference
- 54:28that post pring makes if you ever want
- 54:30to make your game look quite a lot
- 54:31better always make sure to add some post
- 54:33pring all right so like I said this
- 54:34looks really good I like it now before
- 54:36we go to the next lecture let's just
- 54:38clean this up so let's get rid of all of
- 54:39these objects so the counter cabbage
- 54:41tomato and so on let's get rid of all of
- 54:43them except the floor so let's leave the
- 54:44floor and get rid of all these all right
- 54:46so here we have our nice empty scene
- 54:48let's just save our scene and let's get
- 54:50ready for the next
- 54:52lecture hi there this is a quick
- 54:54intermission so how are you doing are
- 54:56you enjoying the course so far are you
- 54:57having any trouble with anything is
- 54:59there something you didn't understand if
- 55:01so remember I'm always active in the
- 55:03comments answering all the questions so
- 55:05if there's anything you need some extra
- 55:06clarification go ahead and ask and I'll
- 55:08do my best to help also remember to
- 55:10check out the pin comment YouTube videos
- 55:13cannot be updated so for any notes or
- 55:15comments I'll put them in the pin
- 55:16comment and definitely check out the
- 55:18website page for this course as people
- 55:21ask more and more questions I will keep
- 55:22that page updated with any frequently
- 55:24asked questions for every single lecture
- 55:25so that way you can see what others have
- 55:27asked and learned from them and you can
- 55:29also download the project files for each
- 55:31lecture so keep that page open on a
- 55:33second Tab and check it every time you
- 55:35start watching a new lecture I really
- 55:37hope you're enjoying the course and I
- 55:38hope you've already learned quite a few
- 55:40things go ahead and hit the like button
- 55:42and subscribe to the channel if you
- 55:43haven't already Okay so let's go to the
- 55:46next
- 55:47lecture hello and welcome I'm your codm
- 55:50in this lecture we're going to begin
- 55:51creating our character let's make a nice
- 55:53character controller so we can move our
- 55:55character in the world
- 55:57okay so first let's begin by creating
- 55:58the character game object and now
- 56:01usually most beginner tutorials would
- 56:03tell you to just right click go into 3D
- 56:05object and create something like a
- 56:06capsule that way you would have the game
- 56:09object with the visual
- 56:10included however for a good project
- 56:13structure and good organization you
- 56:14should always separate the visuals from
- 56:16the logic for example here let's say
- 56:18that I don't want my capsule Exel like
- 56:20this let's say that I want my player to
- 56:22be a little bit more skinny to do that I
- 56:24would have to modify on the scale on
- 56:26this game object so put it maybe on 7.7
- 56:29so something like this basically by
- 56:31doing that by modifying the visual I
- 56:33also modify the scale on the actual
- 56:35player game object having a non-uniform
- 56:37scale on a logic game object that can
- 56:39cause all kind of problems with any kind
- 56:41of logic component also I would prefer
- 56:44to have my character on the floor but if
- 56:45I put it on y of zero notice how the
- 56:47character is half underneath the floor
- 56:49so if I were to use this method I would
- 56:51have to apply some kind of offset in
- 56:53order to make the visual above the floor
- 56:55so that would require rear arranging all
- 56:56the logic to work with an offset on the
- 56:58Y position so because of those reasons
- 57:00and many more you should not Place both
- 57:03the logic and the visual on the same
- 57:04game object instead you should separate
- 57:06them so let's get rid of this and
- 57:08instead let's create an empty game
- 57:10object let's name this the player let's
- 57:13put it on 0000 0 okay and now inside of
- 57:17it now inside let's create let's say a
- 57:19capsule now this one we can easily scale
- 57:22this get any size and shape you want so
- 57:24for example 7.7
- 57:26then since the visual is a child of the
- 57:28game object we can also easily offset
- 57:29this so let's say put it up by about one
- 57:31unit so with this we can position the
- 57:34visual so that basically the player game
- 57:36object it's over here on 0 and the
- 57:37character is above the floor so we don't
- 57:39have any weird offsets this will make
- 57:41all of our logic much more simplified
- 57:44and now on this empty Parent Game object
- 57:46we can attach all of the logic
- 57:47components we want and then in the child
- 57:50visual we can add or replace whatever
- 57:52visuals we want so as a general rule you
- 57:54should always try to do this always
- 57:56separate the logic from the visuals in
- 57:57your game objects okay so with that we
- 58:00have the player game object now let's
- 58:02make our character controller script and
- 58:05before we do let's keep things once
- 58:06again organized so before we do let's
- 58:09create a brand new folder so let's right
- 58:10click on the assets create a brand new
- 58:12folder call it scripts and now inside
- 58:15let's right click and create new C
- 58:16script call it the player wait for the
- 58:19code to compile then select the player
- 58:21game object and attach the script again
- 58:23remember logic components go on the
- 58:24parent game object not the child visual
- 58:27so child visual this one only has visual
- 58:29components and the player this is the
- 58:30one that actually has the logic
- 58:32components so let's open up this script
- 58:35okay so here's our first C script like I
- 58:37said I'm going to assume you know the
- 58:39absolute Basics go watch the C Basics
- 58:41video If you haven't seen it yet so I
- 58:43will assume that you know what is a
- 58:45function what is a variable what is
- 58:46start and update so pretty much the
- 58:48absolute basics for a character
- 58:50controller we first need some input from
- 58:52the player and for that Unity actually
- 58:54has two methods you have the Legacy
- 58:56input manager and the new input system
- 58:59basically the Legacy input manager is
- 59:00super simple and very easy to use so
- 59:02this one is perfect for quickly
- 59:04prototyping and the new input system is
- 59:06extremely capable with tons of features
- 59:08but it's also a bit more complex so what
- 59:10I do is while I'm doing a simple demo or
- 59:12testing out a new prototype I just use
- 59:14the Legacy input manager but when making
- 59:16a more complex project like for example
- 59:18my seam game then at a certain point I
- 59:19refactor my code to use the new input
- 59:21system so here I'm going to teach you
- 59:23both as well as teaching you how to
- 59:25refactor code which is an extremely
- 59:26useful skill so let's first begin by
- 59:28using the simple Legacy input manager we
- 59:31want some basic was movement to move our
- 59:33character and we're going to need to run
- 59:35that logic on every single frame so
- 59:37let's do it on update and let's actually
- 59:39get rid of the code that Unity writes by
- 59:41default let's start compling from
- 59:43scratch let's get rid of this just close
- 59:45okay so here let's start by writing
- 59:47private void update and now here very
- 59:49important if you're a beginner make sure
- 59:51that update is written exactly like this
- 59:53if you write update with lower case if
- 59:55you do this then it won't work the
- 59:57function will not be called
- 59:58automatically I'm pointing this out
- 1:00:00because I have seen a bunch of comments
- 1:00:01from beginners wondering why their code
- 1:00:03doesn't work and it's as simple as this
- 1:00:04with the lower case Unity will not call
- 1:00:06this automatically it needs to be
- 1:00:08exactly perfect so again if you're a
- 1:00:09beginner make sure you write the code
- 1:00:11exactly the code is case sensitive so
- 1:00:13this is very important also another note
- 1:00:16you saw that the code that Unity wrote
- 1:00:17by default when we made a new script it
- 1:00:19just had void update it did not have the
- 1:00:22private keyword private is what is
- 1:00:24called an accessor you have private then
- 1:00:26you have public and then there are some
- 1:00:27more advanced ones technically you can
- 1:00:30omit the accessor and in most cases it
- 1:00:32willon defa to private however in
- 1:00:35writing good clean code you should be as
- 1:00:36explicit as possible there should be no
- 1:00:38room for misunderstandings so while
- 1:00:41technically you could Adit the private
- 1:00:43you should always include it to make
- 1:00:44your code easy to read and easy to
- 1:00:46understand this one is the first of many
- 1:00:49clean code rules that I will teach you
- 1:00:50during this course like I said all of
- 1:00:52the code that I'm writing here is on the
- 1:00:53same level of quality that I use in my
- 1:00:55own profession games I'm not going to
- 1:00:57teach you bad practices like so many
- 1:00:59beginner tutorials do so always be
- 1:01:01explicit always include the accessor
- 1:01:03okay so we have our update Running code
- 1:01:05on every single frame then to test if a
- 1:01:07key is being pressed we just go inside
- 1:01:10input then over here we've got two
- 1:01:12functions so we have get key and get key
- 1:01:14down both these functions were turning
- 1:01:16bulling so that's either true or false
- 1:01:19the difference between them is that get
- 1:01:20key down this one only returns true for
- 1:01:22a single frame when the key is pressed
- 1:01:25whereas get key this one stays true for
- 1:01:26as long as the key is held down for
- 1:01:28example for an action like jumping you
- 1:01:30just want to know when the player
- 1:01:31presses the button so for that one you
- 1:01:33would use get key down however in our
- 1:01:36case for a character controller we want
- 1:01:37to know if the key is being held down we
- 1:01:39don't want just one frame but always so
- 1:01:42for movement let's make sure we go with
- 1:01:44get key then requires a key so let's
- 1:01:46write our key code and then choose the
- 1:01:48key let's say we want W and then let's
- 1:01:51just put this inside an if just like
- 1:01:53this okay so here we have code we want
- 1:01:56to run while holding down the W key
- 1:01:58let's do a quick test just to verify
- 1:01:59everything is working perfectly and for
- 1:02:01testing we can use a super useful
- 1:02:03debug.log this one lets us print a
- 1:02:06message in the console so let's add one
- 1:02:07log here just say something like
- 1:02:09pressing and then let's also do an else
- 1:02:11and if else let's do a debug.log and
- 1:02:14just do a dash okay so here is our very
- 1:02:16basic script let's make sure to save it
- 1:02:18so contrl s then back in unity over here
- 1:02:22make sure you have the script attached
- 1:02:23to the player game object and now we can
- 1:02:26test and now down here on the console we
- 1:02:28can already see dashes so I'm not
- 1:02:30pressing any key also like I mentioned
- 1:02:32in the setup lecture if you're seeing
- 1:02:33just one message then maybe that means
- 1:02:35you have over here the collapse toggled
- 1:02:37if you toggle it look how it only shows
- 1:02:39one message but then over here on the
- 1:02:40right side says the number of messages
- 1:02:42personally I prefer to always keep it un
- 1:02:44toled so I can see every single message
- 1:02:46also over here on the right make sure
- 1:02:48you have info messages visible if you
- 1:02:50untoggle this and you don't see it so
- 1:02:52make sure this one and actually both of
- 1:02:53them make sure all of them are enabled
- 1:02:55okay so we're seeing a whole bunch of
- 1:02:57dashes and one more note if over here
- 1:02:59the scroll bar stop scrolling so right
- 1:03:01now you can see it's stuck up instead of
- 1:03:02being down there so if that happens one
- 1:03:04easy way to reset that is just click
- 1:03:06over here on clear and it goes back into
- 1:03:08Auto scrolling okay so we have the
- 1:03:10dashes I am not pressing any key now as
- 1:03:12I press yep there you go there's the
- 1:03:14message if you don't see it make sure
- 1:03:15the game window is in Focus so select
- 1:03:18the game View and click right here on
- 1:03:19the middle to make this one the focused
- 1:03:21window then if you press the doubling
- 1:03:23key you should see the message and if I
- 1:03:25Let Go yep it is a nice Dash okay great
- 1:03:27so all the basic logic is working back
- 1:03:29in the code here now that logic is
- 1:03:31working let's get rid of the else here
- 1:03:34and let's set test for all of the other
- 1:03:35keys so let's copy paste this so we're
- 1:03:38going to need w a s and D so let's make
- 1:03:41all of
- 1:03:43these okay so we have our inputs let's
- 1:03:46also get rid of the logs we don't need
- 1:03:48this all right so we have all of our key
- 1:03:50presses now let's construct a vector
- 1:03:52with our inputs and since we're just
- 1:03:54going to have to X
- 1:03:56the Ws that is forward and backwards and
- 1:03:58this one is left and right so just two
- 1:04:00axes so because we have just two let's
- 1:04:02use a vector two and let's call it the
- 1:04:04input
- 1:04:06Vector let's construct it so we do new
- 1:04:09one and start off at 0 0 okay then over
- 1:04:12here the logic is pretty simple so when
- 1:04:13we press W then let's go into the input
- 1:04:16vector and set the Y to plus
- 1:04:18one then when we have an S we want to go
- 1:04:21backwards so put the Y on minus one for
- 1:04:23the a we want to go left so that's an X
- 1:04:25on the minus one and finally for the D
- 1:04:28that is an x on plus one okay so with
- 1:04:31this we have our correct input Vector
- 1:04:33let's do a quick log just a test so
- 1:04:34debug. log on the input Vector okay so
- 1:04:38let's test all right so we can see in
- 1:04:40log 0 0 okay makes sense now if I press
- 1:04:42W yep we've got an one on the Y if I
- 1:04:45press a we got minus one on the X press
- 1:04:47D+ one press s and minus one okay great
- 1:04:50so everything works except we also need
- 1:04:52to be careful about one other thing if I
- 1:04:55press press both W and D with this look
- 1:04:58at that the vector is 1 one which is
- 1:05:00correct that's exactly what we did
- 1:05:01except the vector 1 one actually has a
- 1:05:03bigger magnitude than just one vector if
- 1:05:06we leave it like this then the character
- 1:05:07will move faster when moving diagonally
- 1:05:09versus when moving in just one direction
- 1:05:11for our input Vector we really want it
- 1:05:13to be normalized meaning we want it to
- 1:05:15have the same size regardless of the
- 1:05:16combination of keys that we're pressing
- 1:05:18so back in the code here after
- 1:05:19calculating the input Vector let's
- 1:05:21simply normalize it so we go into the
- 1:05:24input vector and we set it equals to
- 1:05:26input vector. normalized so this will
- 1:05:29normalize our input Vector let's see now
- 1:05:31over here if I press dou yep got one
- 1:05:33press s minus one okay so all those work
- 1:05:35now if I press both W and D yep there
- 1:05:38you go now it says 71 when you combine
- 1:05:40both these and you do the math these do
- 1:05:42end up with a magnitude of one so with
- 1:05:44this our character will move at the same
- 1:05:46speed on both diagonals and straights
- 1:05:48okay so we have the input Vector all
- 1:05:50correct now let's actually apply some
- 1:05:52movement for that there are many ways of
- 1:05:54making a character controller for
- 1:05:55example example you can decide to use
- 1:05:56physics or not over here I want to keep
- 1:05:58the game simple so let's not use physics
- 1:06:00instead let's just move the player
- 1:06:02transform directly over here we have our
- 1:06:04input Vector okay great now we want to
- 1:06:06apply this to our character position so
- 1:06:08first we access the transform this one
- 1:06:11refers to the transform where this
- 1:06:12script is attached to this script was
- 1:06:15attached to the player so this is going
- 1:06:17to refer to the player transform then we
- 1:06:19want to modify the position so let's
- 1:06:20access the position and now for moving
- 1:06:22we don't want to just assign it if we do
- 1:06:25something like
- 1:06:27this like this the player would never
- 1:06:29leave the center of the world it would
- 1:06:30always be near 0 so instead we don't
- 1:06:33want to just assign it but instead we
- 1:06:35want to add onto it now if you're a
- 1:06:37complete beginner and you don't know
- 1:06:38this syntax then this one is exactly the
- 1:06:40same as this so transform. position
- 1:06:43equals transform. position plus input
- 1:06:46Vector so both these two lines are doing
- 1:06:48the exact same thing personally I prefer
- 1:06:50to use the shorthand I find that equally
- 1:06:53readable and more compact Okay so we
- 1:06:55have this and we add our input Vector to
- 1:06:57the transform position except we can
- 1:06:59also see a really nice error basically
- 1:07:02it's telling us that we are mixing two
- 1:07:03types our input is a vector 2 where we
- 1:07:06only have an X and A Y but transform.
- 1:07:08position is a vector 3 meaning it has an
- 1:07:11x y and Zed one simple solution is to
- 1:07:14cast our input Vector onto a vector
- 1:07:15three so we just convert this from one
- 1:07:18type into the other one and yep we don't
- 1:07:20have the error so let's test and now if
- 1:07:22I press W and yep the character does
- 1:07:24move Let's ignore the massive speed for
- 1:07:26now so it does move it does seem
- 1:07:29slightly correct except you can
- 1:07:31obviously notice that it's not correct
- 1:07:33we are moving on the x- axis on left and
- 1:07:35right that is correct but then we are
- 1:07:36moving up and down instead of forward
- 1:07:37and back basically we convert the vector
- 1:07:402 directly into a vector 3 so we are
- 1:07:42moving on the X and Y axis but in our 3D
- 1:07:44game we really don't want the characters
- 1:07:46to fly so instead we want to move on the
- 1:07:48X Z axis so back in code here instead of
- 1:07:51directly casting this down into a vector
- 1:07:533 Let's construct a move Deer vector
- 1:07:56so let to a vector 3 let's call it our
- 1:07:59move Deer for our move Direction and
- 1:08:01over here we construct a new Vector 3
- 1:08:04and basically we're just going to assign
- 1:08:05the input y to the Zen on here so first
- 1:08:08of all for the X that one is correct so
- 1:08:09input vector. X then for the Y let's
- 1:08:12leave this one on zero and finally let's
- 1:08:14use the input vector. y as a Z On The
- 1:08:16Move direction also now at this point
- 1:08:18you might be questioning if we're using
- 1:08:20a vector 3 here why don't we also use a
- 1:08:23vector 3 up here and then just assign
- 1:08:25the said directly that's certainly a
- 1:08:27possibility and for making a super quick
- 1:08:29prototype I might even do that myself
- 1:08:31but the proper answer to that is once
- 1:08:33again all about writing good clean code
- 1:08:35the input logically only has two axes
- 1:08:38there's no Z axis on your keyboard so
- 1:08:40logically it makes no sense for the
- 1:08:42input to have three axis and beyond that
- 1:08:44you should keep the logic separate so
- 1:08:46you should first get the input and then
- 1:08:48actually move the object we're going to
- 1:08:50see the benefit of that separation when
- 1:08:52we refactor this code to work with the
- 1:08:53new input system doing that that will in
- 1:08:55turn make enabling game pad j6 support
- 1:08:58super easy because we have the input
- 1:09:00Vector separated from the actual
- 1:09:01movement so all of that to say let's do
- 1:09:03things properly let's keep the input
- 1:09:06Vector separate from the movement Vector
- 1:09:08so we just translate the XY onto X Zen
- 1:09:11and then we just apply this into our
- 1:09:12transform position okay so let's test so
- 1:09:16now if I press D go right go left and
- 1:09:18press W and S and there you go okay
- 1:09:20great so it is indeed moving Left Right
- 1:09:22forward and back okay great so it is
- 1:09:24working but as you can see it's moving
- 1:09:26insanely fast you might think the issue
- 1:09:28here is just applying some sort of
- 1:09:29movement speed multiplier except there's
- 1:09:31actually one sneaky issue here here on
- 1:09:34the game view on the top right corner
- 1:09:35we've got a stats button and over here
- 1:09:37we can see a whole bunch of things
- 1:09:39specifically we can look at the frame
- 1:09:40rate we can see that it's running at 144
- 1:09:43frames per second over here on the left
- 1:09:45side on this button I have vsync enabled
- 1:09:48this will cap the frame rate to the
- 1:09:49monitor's refresh rate so that is why
- 1:09:52I'm seeing 144 Herz I can over here
- 1:09:54disable V sync and yep look at that goes
- 1:09:56all the way up to 700 basically now the
- 1:09:58game is running as fast as my computer
- 1:10:00can run it and if I press the movement
- 1:10:02keys and look that now it's moving even
- 1:10:04faster now I've completely lost track of
- 1:10:07where my player is this is not what we
- 1:10:09want we don't want the player to move at
- 1:10:11different speeds depending on the frame
- 1:10:12rate we want it to always move at the
- 1:10:14same speed regardless of frame rate so
- 1:10:17when you do any kind of movement Logic
- 1:10:18on an update you always need to make
- 1:10:20sure to multiply by time. Delta time
- 1:10:23what this variable contains is the
- 1:10:25number of seconds elapse since the last
- 1:10:26frame for example let's add log to this
- 1:10:29we don't need input Vector so let's log
- 1:10:31just the time. Delta time okay so we can
- 1:10:33see there that is basically telling us
- 1:10:35how many seconds it is taken to render a
- 1:10:37single frame once again note how I have
- 1:10:40vsync enabled so I'm running at 144
- 1:10:42frames per second and now if I disable
- 1:10:44it let's see what happens to that number
- 1:10:45so if I disable and you have look at
- 1:10:47that that number is now much much
- 1:10:48smaller and the game is now running much
- 1:10:50much faster so by incorporating this
- 1:10:52value into our calculation we are going
- 1:10:54to be taking into count the frame rate
- 1:10:56does making sure that the movement is
- 1:10:58always frame rate independent right now
- 1:11:00with this frame rate if I move you can
- 1:11:01see I'm moving at this speed and now if
- 1:11:03I enable vsync change the frame rate and
- 1:11:05I move and I'm still moving at the exact
- 1:11:07same speed okay that's great except
- 1:11:10obviously it's not exactly great it's
- 1:11:11moving way too slow so let's also
- 1:11:13incorporate a movement speed now for
- 1:11:15this once again most beginner tutorials
- 1:11:17will teach you to go all the way up here
- 1:11:18and find a public float move
- 1:11:21speed maybe defaulted to some valum like
- 1:11:247f some like that then you have this
- 1:11:27field and then down here you simply use
- 1:11:29it in the calculation so movement here
- 1:11:31move multiplied by move speed and by
- 1:11:33time. time so this is what most
- 1:11:36tutorials would teach you by making it
- 1:11:38public up here what you're doing is
- 1:11:39you're enabling access from the editor
- 1:11:42so if you go over here in the editor
- 1:11:43over there on the player we can see the
- 1:11:45move speed variable we can see this
- 1:11:46Expos and we can modify it this makes it
- 1:11:49really easy for testing and for
- 1:11:50iterating upon the value even while the
- 1:11:52game is running so the game is playing I
- 1:11:54can move and I have this move speed now
- 1:11:56I can modify this and yep now I got a
- 1:11:58different move speed so I can use this
- 1:12:00to quickly iterate and find the perfect
- 1:12:01value so it's great to have this
- 1:12:04variable exposed in the editor and this
- 1:12:06feature is indeed the reason why most
- 1:12:08beginner tutorials would teach you to
- 1:12:09make it public it's so you can see it in
- 1:12:11the editor that is indeed a very
- 1:12:13valuable thing being able to easily
- 1:12:15trate upon important values is always
- 1:12:16very useful however when you make
- 1:12:19something public when you do that you
- 1:12:21don't just expose the film to the editor
- 1:12:23you are exposing it to every other class
- 1:12:25in your entire code base so some other
- 1:12:27class could access this field and set
- 1:12:29the player's movement speed to something
- 1:12:30like zero and you would have no idea
- 1:12:32that was happening because the issue
- 1:12:34would not be on this code right here I
- 1:12:36have an entire video on this subject why
- 1:12:38you should not make everything public
- 1:12:40this is an extremely important topic to
- 1:12:42know about this one tiny change will
- 1:12:44massively improve the quality of your
- 1:12:45code definitely go ahead and watch that
- 1:12:48video to learn why such a bad thing and
- 1:12:50make sure you don't do it so to avoid
- 1:12:52all kinds of problems you should never
- 1:12:54make Fields public so very quickly the
- 1:12:56obvious alternative is make it private
- 1:12:58making it private means that only this
- 1:13:00class only the code in here only this
- 1:13:02can modify this field so you know for
- 1:13:04certain that no other class can ever
- 1:13:05modify this however making it private
- 1:13:08also means the editor cannot modify this
- 1:13:09field so we've lost our very useful
- 1:13:12iteration approach so what we can do to
- 1:13:14expose it just to the editor is to keep
- 1:13:16it private and then we add the attribute
- 1:13:18serialized field this way this field is
- 1:13:21still private meaning that it can only
- 1:13:22be modified by the code inside the
- 1:13:24player class
- 1:13:25but with this attribute over here in the
- 1:13:28editor yep we do have an editable field
- 1:13:30so only the code in thatass and the
- 1:13:32editor can modify it nothing else can
- 1:13:34touch it nothing else can read or write
- 1:13:36which is exactly what we want one of the
- 1:13:38main rules in writing good clean code is
- 1:13:40minimizing complexity and one of the
- 1:13:42easier ways to minimize complexity is
- 1:13:43simply to minimize access by making this
- 1:13:46F private we are minimizing complexity
- 1:13:48because it doesn't matter how complex
- 1:13:50our game is maybe our code base is a
- 1:13:52thousand classes long it doesn't really
- 1:13:54matter because only this class can ever
- 1:13:55touch this field so if we have a bug
- 1:13:58related to movement speed we know for
- 1:13:59certain it has to be inside this code
- 1:14:01and nothing else so we minimize the
- 1:14:03things we need to keep in our head which
- 1:14:05is always a very good thing okay so with
- 1:14:07all that said we have our movement speed
- 1:14:09and down here we are incorporating it
- 1:14:10into our calculation just with this we
- 1:14:12have our character working with a
- 1:14:14variable movement speed and by using
- 1:14:16Delta time we have our movement
- 1:14:17correctly being frame rate independent
- 1:14:20so here's our character and using the
- 1:14:21keys I can walk around and yep the
- 1:14:23character moves in any direction so we
- 1:14:24have movement fully working while using
- 1:14:26the Legacy input manager like I said
- 1:14:29we're going to learn how to refactor our
- 1:14:30code to use the new input system
- 1:14:32learning how to refactor is an extremely
- 1:14:33important skill to improve your own
- 1:14:35programming skills it is something that
- 1:14:37you should always do when necessary it
- 1:14:39will massively help you improve the
- 1:14:40quality of your code so we're going to
- 1:14:42do that but before we get to that let's
- 1:14:44actually do something a bit more fun and
- 1:14:46add some proper visuals and animations
- 1:14:48to our player in the next
- 1:14:50lecture hello and welcome I'm your code
- 1:14:52Mak in this lecture we're going to
- 1:14:54replace our barding capsule visual with
- 1:14:56a nice proper character mesh okay so in
- 1:14:58the included assets project files over
- 1:15:01here if we go inside the prefab visuals
- 1:15:03we see a nice player visual let's
- 1:15:05position it inside the player game
- 1:15:07object so let's drag it inside again
- 1:15:09because we separate the logic and the
- 1:15:11visuals this is going to be pretty easy
- 1:15:13we don't need to modify the parent game
- 1:15:14object at all we just drop the visual as
- 1:15:16a child that's it also again very
- 1:15:18important make sure the visual is over
- 1:15:20here on local position 0000 0 only the
- 1:15:22parent game object should move the
- 1:15:24visual itself should never move if you
- 1:15:25notice some weird positions as your
- 1:15:27player moves and rotates always check to
- 1:15:29make sure that the child visual is on
- 1:15:310000 okay so with this let's delete the
- 1:15:33old capsule deleted okay so here we have
- 1:15:36a pretty simple but really nice
- 1:15:37character visual it's really just two
- 1:15:39spheres stacked on top of one another
- 1:15:41with a bunch of eyes very simple for the
- 1:15:43visual itself the material is using just
- 1:15:45a solid color so here it is inside the
- 1:15:47assets material you can see a bunch of
- 1:15:49player bodies with different colors
- 1:15:51these different colors they won't be
- 1:15:52used in the upcoming multiplayer video
- 1:15:54basically each player will have a
- 1:15:55different color also by the way if
- 1:15:57you're a complete beginner here's a
- 1:15:58quick lecture on materials these are
- 1:16:00materials and if we collick select we
- 1:16:01can see a bunch of sets related to that
- 1:16:03material basically the materials have a
- 1:16:05Shader and then a bunch of properties
- 1:16:07now the Shader is the actual code that
- 1:16:09runs on the graphics card that says how
- 1:16:11an object should be rendered by default
- 1:16:13you have a whole bunch of included
- 1:16:14shaders we're using the universal render
- 1:16:16pip line so you should mostly be using
- 1:16:17the ones inside the urp and by default
- 1:16:20you probably want to be using the
- 1:16:21standard light Shader then of course you
- 1:16:22can also build your own custom shaders
- 1:16:24when excellent tool for doing that is
- 1:16:26Shader graph which I have covered in
- 1:16:27detail in a previous video it's a fully
- 1:16:29visual tool that you can use to make
- 1:16:30shaders without having to write any
- 1:16:32Shader code it's a great tool I've also
- 1:16:34made a bunch of tutorials on all kinds
- 1:16:36of effects you can make although right
- 1:16:37now we're not going to be using custom
- 1:16:39shaders we're going to do that later on
- 1:16:40the course but for now we're going to
- 1:16:42stick with default light Shader so
- 1:16:43materials have a combination of shaders
- 1:16:45and the properties on that Shader for
- 1:16:47example over here for the default light
- 1:16:48Shader you can see that it has over here
- 1:16:50a base map that it has a color field
- 1:16:52this is what you can change to apply a
- 1:16:54different color to your player also as
- 1:16:55to how you apply a material to an object
- 1:16:57over here on the player visual you can
- 1:16:59see the objects are made up of a sphere
- 1:17:01so this is the mesh and then the mesh
- 1:17:02render this is the one that has the
- 1:17:04material so both these are what stores
- 1:17:07the shape as well as the visual for the
- 1:17:08object the mesh is just 3D shape but
- 1:17:11just by itself the mesh filter doesn't
- 1:17:12actually render anything so it needs a
- 1:17:14mesh render which needs a material
- 1:17:15attached to it so for example over here
- 1:17:17on the hierarchy let's right click on
- 1:17:18empty space and let's create a brand new
- 1:17:20Cube just to see it so yep there you go
- 1:17:22it does create an object and as you can
- 1:17:23see it has a mesh fter and a mesh render
- 1:17:26now to apply a different material you
- 1:17:27can click on this little circle icon and
- 1:17:29it shows you all the materials in that
- 1:17:31project alternatively you can grab the
- 1:17:33material directly from the project
- 1:17:34window so for example the player body
- 1:17:36just grab it and drop it in there or you
- 1:17:38can also drop the material over here on
- 1:17:40scene view as you can see as I Mouse
- 1:17:41over different objects it applies that
- 1:17:43material to a different object although
- 1:17:45note that only works over here on scene
- 1:17:47view it does not work on game view so
- 1:17:48this basically sets the material over
- 1:17:50there on the object now one more very
- 1:17:52important thing on materials if you have
- 1:17:54multiple meshes all using the exact same
- 1:17:56material and then you modify the
- 1:17:57material it will change the visual on
- 1:17:59all meshes using that material so for
- 1:18:01example if I modify the color here put
- 1:18:03it on some different there you go all
- 1:18:05three instances all three objects that
- 1:18:07are all using the exact same material
- 1:18:09they all update with the new color if
- 1:18:10for example you wanted the head to be a
- 1:18:12different color from the rest then you
- 1:18:14would just create new material so you
- 1:18:15can right click on the project window
- 1:18:17let's create a new material then you can
- 1:18:19give it name give it colors use
- 1:18:21different shade or whatever and then use
- 1:18:22this one for something different so
- 1:18:24that's pretty much the basics for
- 1:18:25materials and by the way if you're a
- 1:18:26complete beginner and you have questions
- 1:18:28remember to post them in the comments
- 1:18:29and I'll do my best to help like I said
- 1:18:31I want to keep this video moving I'm
- 1:18:32trying to teach as much as possible
- 1:18:34while still keeping the video a
- 1:18:35reasonable length so if you need any
- 1:18:36further clarification on anything
- 1:18:38specific just go ahead and ask in the
- 1:18:39comments okay so when materials out of
- 1:18:41the way here we have our player with
- 1:18:42visual let's just get rid of our Cube
- 1:18:44okay and just with this if we test and
- 1:18:47yep over here we already have a nice
- 1:18:48player visual walking around okay great
- 1:18:51except the player isn't actually
- 1:18:52rotating ideally the visual should be
- 1:18:54facing the walking direction so if I
- 1:18:56walk down it should be rotated to face
- 1:18:58down so let's add that doing that is
- 1:19:00actually going to be pretty simple let's
- 1:19:02go into our script here we are on the
- 1:19:03player script and over here we already
- 1:19:05have the movement Direction so we're
- 1:19:07going to use this in order to make sure
- 1:19:09to rotate the game object to face this
- 1:19:11move Direction and for rotating a
- 1:19:13transform there are many many ways to do
- 1:19:14it one obvious one is to modify the
- 1:19:17transform. rotation however this one as
- 1:19:19you can see works with querian for me
- 1:19:21even though I've been doing Game Dev for
- 1:19:23over 10 years I still find qu is quite a
- 1:19:25bit confusing so I normally don't use
- 1:19:27this method another method is to modify
- 1:19:29the transform. oiler angles this one is
- 1:19:32much more intuitive and makes more sense
- 1:19:33to me it works with regular Oiler angles
- 1:19:36which is much easier to understand if
- 1:19:37you don't know that name it really just
- 1:19:39means the angles that go from Z to 360
- 1:19:41then for another method you can also use
- 1:19:43the function transform. look at this one
- 1:19:45makes a transform look at a certain
- 1:19:47point so it can be a transform Target
- 1:19:49can be a vector 3 for one position
- 1:19:51anything like that so this is a very
- 1:19:52useful function we could calculate a
- 1:19:54point right in front of our move
- 1:19:55Direction and look at it or finally the
- 1:19:58method that I personally like to use for
- 1:19:59this specific purpose which is just
- 1:20:01modify the transform. forward this one
- 1:20:03has the normalized vector representing
- 1:20:05the forign AES and importantly you can
- 1:20:07get it and you can also set it so you
- 1:20:09have both read and write you can read it
- 1:20:11to get the current transform forward but
- 1:20:13you can also write to it to essentially
- 1:20:14rotate the transform so we can just
- 1:20:16assign this to our forward Vector also
- 1:20:18by the way you also have transform. up
- 1:20:21and transform. right both these work
- 1:20:23exactly the same way for example
- 1:20:24transform. right this one is extremely
- 1:20:26useful for 2D games but over here we're
- 1:20:28working in 3D so we want transform.
- 1:20:30forward and all we need is the forward
- 1:20:31Vector which is really just the move
- 1:20:33Direction so let's set this one equals z
- 1:20:34move there okay so just like this it
- 1:20:36should already work let's also just
- 1:20:38clean up the log we no longer need to
- 1:20:39see the Delta time okay so let's like
- 1:20:41this okay here we are and as I move and
- 1:20:43Y there you go look that the player
- 1:20:45object does indeed rotate to face the
- 1:20:47move Direction okay so it's already
- 1:20:48looking great all right awesome however
- 1:20:50it also looks a bit odd with how it's
- 1:20:52instant so I move left and right look
- 1:20:54that it instantly rotates so there's no
- 1:20:56smoothing nothing it's way too junky so
- 1:20:59let's add some nice simple smoothing and
- 1:21:00for that let's use a really awesome
- 1:21:02really useful math function called lurp
- 1:21:04it helps you interpolate between two
- 1:21:06values I made a quick video showcasing a
- 1:21:08bunch of uses for it you can lurp floats
- 1:21:10Vector 3 quion or just about anything
- 1:21:13it's really perfect for making some
- 1:21:14smooth movement or smooth rotation so
- 1:21:16for that we can access the function
- 1:21:18inside the vector 3 class so we can find
- 1:21:20lurp then here we actually have two
- 1:21:23options we've got lurp this one
- 1:21:26interpolates and we've got slurp this
- 1:21:28one interpolates but with a spherical
- 1:21:30interpolation basically if you're
- 1:21:31dealing with rotations like what we have
- 1:21:33here then we want to be using slurp
- 1:21:35whereas if you're dealing with just
- 1:21:36positions then you want to use slurp so
- 1:21:38here let's use slurp this one as you can
- 1:21:40see takes an a a b and a t like I said
- 1:21:43this interpolates between A and B based
- 1:21:45on T so for example if T is zero then it
- 1:21:48won't return the value a if T is one
- 1:21:50then will return the value B if T is5
- 1:21:53then will return the point in between A
- 1:21:55and B if you want to learn some more
- 1:21:56about interpolation and the math behind
- 1:21:58this then I highly recommend you look at
- 1:22:00my video on splines splines are
- 1:22:01basically just a whole bunch of lbs put
- 1:22:03together so anyways over here we can add
- 1:22:05some smoothing to our Rotation by just
- 1:22:06using the current transform. forward as
- 1:22:09our a then for the B this one is our
- 1:22:12Target so let's use the move there and
- 1:22:14finally for T let's use time. Delta time
- 1:22:17meaning that with this over time the
- 1:22:18character won't rotate towards our
- 1:22:20Target movement Direction so just with
- 1:22:22this let's test so here if I move to the
- 1:22:24right and yep look at that it is indeed
- 1:22:26rotating it's way too slow but yep it is
- 1:22:28rotating smoothly all right so let's
- 1:22:30just add a bit more speed so over here
- 1:22:32let's just find a float for the rotate
- 1:22:34speed let's put it at something like 10f
- 1:22:37then we just multiply it so time do time
- 1:22:39multiply by our speed let's see and move
- 1:22:41and yep there you go look at that much
- 1:22:42much better okay great so as you can see
- 1:22:45everything works as I move the character
- 1:22:47does rotate to face the move Direction
- 1:22:49all right great so here we have our
- 1:22:51character with a nice visual all
- 1:22:52rotating to face the move Direction now
- 1:22:54the next step is we want to add some
- 1:22:56nice animations so let's do that in the
- 1:22:58next
- 1:22:59lecture hello and welcome I'm your Cod
- 1:23:01Maki in this lecture we're going to add
- 1:23:03some animations to our player character
- 1:23:05now I have already included some
- 1:23:07pre-made animations with a pre-made
- 1:23:09animator over here inside the access
- 1:23:10folder but let's first do it from
- 1:23:12scratch just so you'll learn how to do
- 1:23:13it first to animate we're going to need
- 1:23:15the animator component if we go inside
- 1:23:17the player visual game object once again
- 1:23:19remember all the visuals go on the
- 1:23:21visual game object so for adding the
- 1:23:22animated component we want it on the
- 1:23:24Visual and not on the logic component so
- 1:23:26anyways over here as you can see by
- 1:23:27default I already attached it with the
- 1:23:30assets included but let's do it from
- 1:23:31scratch so let's remove this by default
- 1:23:33now let's add a new component let's call
- 1:23:35it an animator also one very very
- 1:23:38important thing here it's the animator
- 1:23:39component not the animation component
- 1:23:42these two are completely different the
- 1:23:44animation component this one is actually
- 1:23:46related to unity's Legacy animation
- 1:23:48system from a very long time ago it's
- 1:23:50only here pretty much for backwards
- 1:23:51compatibility and for super simple use
- 1:23:53cases so most of the time make sure
- 1:23:55you're using the animator component okay
- 1:23:57so to drive this animated component we
- 1:23:59need an animated controller let's go
- 1:24:01into our project files and let's create
- 1:24:02and create a brand new animator
- 1:24:04controller let's call this my player
- 1:24:06animator then let's select the player
- 1:24:08Visual and just drag the controller on
- 1:24:10there okay again if you have issues and
- 1:24:12you cannot drag the animator onto the
- 1:24:13film make sure you're using the animator
- 1:24:15and not the animation component okay so
- 1:24:17with this we have assigned our animator
- 1:24:19controller and now let's double click on
- 1:24:21it to open the animator window and if
- 1:24:22you don't see it then go into window
- 1:24:24then go into animation and open up the
- 1:24:26animator window and also if you still
- 1:24:28don't see anything then maybe you might
- 1:24:29have some issues with your layout if
- 1:24:31that's the case then go onto the top
- 1:24:33right corner layout and go back into the
- 1:24:34default and then back into your own
- 1:24:36layout and finally if you still don't
- 1:24:37see anything on this window if you don't
- 1:24:39see default states make sure you have
- 1:24:41the object selected in the hierarchy so
- 1:24:43with that you should be able to see
- 1:24:44these states so this is our animator
- 1:24:45controller now I have a really detailed
- 1:24:47overview of the animator and the
- 1:24:49animation windows in my ultimate unity
- 1:24:51overview course so you can go watch
- 1:24:52those lectures for some really in-depth
- 1:24:54explanations about everything this does
- 1:24:56basically the animator is a state
- 1:24:57machine so you have various States and
- 1:24:59you can create transitions between each
- 1:25:01state by default you have these three
- 1:25:03special States there's the entry State
- 1:25:05exit and any state these are used for
- 1:25:07making transitions but we don't really
- 1:25:08need to worry about them just for now
- 1:25:10first let's just make a basic new
- 1:25:11animation and for that the easy way to
- 1:25:13do it is to open up the animation window
- 1:25:15so let's go up top into window go into
- 1:25:17animation and open up the animation
- 1:25:19window so here it is again that's a
- 1:25:21different window that's animation not
- 1:25:23animator and for me for for this window
- 1:25:24I like to dock it down here so there's a
- 1:25:26nice timeline so I think this is good
- 1:25:28okay and now if we select the object in
- 1:25:30the Hier key that has our animator then
- 1:25:32we can see the text here so to begin
- 1:25:33animating we've got a nice button to
- 1:25:35create an animation so let's go ahead
- 1:25:36and click on this and now let's give it
- 1:25:38a name for now let's first make the idle
- 1:25:40animation so let's just call this idle
- 1:25:42and if just like that we have created an
- 1:25:44animation you can see the animation
- 1:25:46window down here has changed we now see
- 1:25:48a nice timeline showing the time and
- 1:25:50also on the animated controller you can
- 1:25:51see the new animation was added as a
- 1:25:53brand new state so a new state was
- 1:25:55created and if you click to select it on
- 1:25:57the right side on the inspector you see
- 1:25:59the motion so the actual animation
- 1:26:00selected and you can also see that
- 1:26:02there's an arrow pointing from the entry
- 1:26:03onto the anal state so that means this
- 1:26:05one is going to be the default State
- 1:26:07when the animated controller starts it
- 1:26:08will start playing right on this state
- 1:26:10let me just point out one more thing
- 1:26:12related to animations so on the project
- 1:26:14window we can see yep here is our
- 1:26:16animation that we just created and you
- 1:26:17can see the inspector looks just like
- 1:26:19this now if your inspector looks
- 1:26:21differently that might be because you
- 1:26:22accidentally created the Legacy
- 1:26:24animation that has to do with the
- 1:26:26previous animation system that I talked
- 1:26:27about the one that is Legacy that should
- 1:26:29really no longer be used so if you see a
- 1:26:31different inspector then a quick way to
- 1:26:32fix it is to click on these three dots
- 1:26:34on the inspector these three dots then
- 1:26:36you change the inspector into debug
- 1:26:38inspector and over here you see a toggle
- 1:26:40for legacy so for the animations that we
- 1:26:42want to use right now we do not want to
- 1:26:44be using Legacy animations so make sure
- 1:26:45this one is untoggle if in your case
- 1:26:47toggled just un toogle it then go back
- 1:26:49into the normal inspector and now yep it
- 1:26:51should look just like this okay so we
- 1:26:53have our animation and now it's on our
- 1:26:55animat controller now let's actually
- 1:26:57make an animation so let's select the
- 1:26:59animation window and again let's make
- 1:27:01sure to select the object so let's
- 1:27:02select the player visual game object so
- 1:27:04here on the animation window we see this
- 1:27:06nice little red button this one enables
- 1:27:07or disables recording so if you click on
- 1:27:09it you can see yep the timeline is now
- 1:27:11red meaning that we are now recording
- 1:27:13and now we can do anything to any chn
- 1:27:15objects and it won't record any changes
- 1:27:17we make now note what I said that's very
- 1:27:19important it needs to be child objects
- 1:27:21if you select for example the parent
- 1:27:22game object then all of a sudden it's
- 1:27:23stop recording so you can only animate
- 1:27:26child objects so let's select the player
- 1:27:28visual let's enable recording then let's
- 1:27:30expand the player visual let's make sure
- 1:27:32that our timeline is on zero so drag it
- 1:27:33all the way to the left and now for
- 1:27:35example let's grab the head object and
- 1:27:37let's move it just a tiny tiny bit
- 1:27:39basically just move it enough in order
- 1:27:41to make sure that the position over here
- 1:27:42is in red meaning that we have recorded
- 1:27:44a key frame then let's drag the timeline
- 1:27:46by a little bit let's go over here to
- 1:27:48frame three this one is actually going
- 1:27:50to be half a second and it's going to be
- 1:27:52that because over here on the samples
- 1:27:53this is the frame rate for the animation
- 1:27:55so at 60 that means we have 60 frames
- 1:27:57this makes 1 second so 30 frames would
- 1:27:59be half a second you can also zoom out
- 1:28:01by scrolling over here or dragging the
- 1:28:03handles down here so let's go into 30
- 1:28:05half a second and now this one let's
- 1:28:06move the head by a little bit something
- 1:28:08like this as you can see down there we
- 1:28:09can note that it record the new key
- 1:28:11frame and now if we h on the play button
- 1:28:13we can preview the animation and yep
- 1:28:14look at that it does do exactly that so
- 1:28:16it starts off down and then moves up
- 1:28:18okay so that's great but we don't want
- 1:28:19to snap back so let's actually add
- 1:28:21another key frame right at the end so
- 1:28:23let's stop playing the the animation and
- 1:28:25to make sure we have a perfect Loop
- 1:28:26let's just click to select the key frame
- 1:28:28let's press contrl + C then let's go
- 1:28:30down into the 1 second Mark let's press
- 1:28:32contrl + V and there we go there's the
- 1:28:34exact same key frame so now if we head
- 1:28:36on play yep there you go we have our
- 1:28:37nice seamless Loop so the head goes up
- 1:28:39and down and repeats forever all right
- 1:28:41awesome okay so that's great now let's
- 1:28:44also do one thing let's also record a
- 1:28:45key frame on the body however we don't
- 1:28:48want it to move at least not in this
- 1:28:50idle animation we just want to have a
- 1:28:52static key frame so let's the body and
- 1:28:55let me actually move it a bit to the
- 1:28:56side just to make sure to record and now
- 1:28:58manually we can modify things over here
- 1:29:00to modify the actual key Frame data so
- 1:29:02on this one I don't want it to move so
- 1:29:03let's put it all the way back at zero
- 1:29:05just make sure we have a nice key frame
- 1:29:07recording now the reason why we are
- 1:29:08recording the body position even without
- 1:29:10moving it is because the walk animation
- 1:29:12will indeed move the body but when we
- 1:29:14get back to idle we want the body to go
- 1:29:16back to this exact position so that is
- 1:29:18why we need a key frame here okay so
- 1:29:19that's done so we can stop recording so
- 1:29:21let's click on the red button again okay
- 1:29:23great by the way one more note to make
- 1:29:25sure that the animation Loops go into
- 1:29:27the project window and over here select
- 1:29:28the animation and make sure Loop time is
- 1:29:30enabled it should be there by default
- 1:29:32okay so the animation is set up and if
- 1:29:34we look in the animator it's already the
- 1:29:36default state so if we head play we
- 1:29:38should be able to see the addal
- 1:29:39animation playing non-stop so let's hit
- 1:29:41play and you there it is the Addle
- 1:29:42animation with the head moving up and
- 1:29:44down everything works perfectly all
- 1:29:45right awesome okay so next up let's make
- 1:29:48a walk animation now for me when I'm
- 1:29:50making an animation that is based on
- 1:29:51another one I like to actually duplicate
- 1:29:53it inste of starting from scratch so
- 1:29:54over here on the project window let's
- 1:29:56select the utle animation and let's
- 1:29:58duplicate it so contrl D let's rename
- 1:30:00this one to the W animation and now if
- 1:30:02we select the player Visual and then we
- 1:30:04go into the animation window over here
- 1:30:06we see a nice little drop- down menu for
- 1:30:08all of the animations except right now
- 1:30:10we don't see the won animation we only
- 1:30:11see the idle animation that is because
- 1:30:13this menu only shows animations that are
- 1:30:15attached to the animator so first we
- 1:30:17need to add the animation onto the
- 1:30:18animator component and how we do that is
- 1:30:20actually super simple let's just open up
- 1:30:22the project window and just drag the
- 1:30:23walk animation and drop it here that's
- 1:30:25it so with this we have attached a new
- 1:30:27state to the animat controller and now
- 1:30:28if once again we select the object in
- 1:30:30the Hier key go into the animation click
- 1:30:32the drop down menu and yep now we do see
- 1:30:34the won animation so let's click to
- 1:30:35select this one and now for this one
- 1:30:37let's make the animation so let's look
- 1:30:38in scene View and make it bounce just up
- 1:30:40and down so I'm going to enable record
- 1:30:42go back here and for the body this one
- 1:30:44already has a key frame so let's go up
- 1:30:46here move it a little bit and then copy
- 1:30:48the key frame put it the same one at the
- 1:30:49end something like this so there you go
- 1:30:51it just goes up and down let's actually
- 1:30:53put it offset so it look a bit better so
- 1:30:54something like this by the way in a bit
- 1:30:56we're going to replace these animations
- 1:30:57with the ones that I made previously so
- 1:30:59don't worry about making the animations
- 1:31:00perfect unless you want to do that okay
- 1:31:02so there you go that's the animation
- 1:31:03although for walking should be much
- 1:31:05faster so here's a quick animated tip
- 1:31:07this top bar here lets you select all of
- 1:31:09the key frames within a certain time so
- 1:31:10if I click to select note how it selects
- 1:31:12both those key frames and also if you
- 1:31:14click and drag once on top of here you
- 1:31:16can select multiple key frames so for
- 1:31:17example to select everything just click
- 1:31:19and drag to select all of them and now
- 1:31:21you see these nice little vertical bars
- 1:31:23so if you click on the those and then
- 1:31:24you drag them you can basically modify
- 1:31:26the time of all the animations and
- 1:31:27everything matches up so for example
- 1:31:29let's make this one super fast let's put
- 1:31:30it just 20 frames there you go now it's
- 1:31:32a much faster walk animation okay great
- 1:31:34let's click on the right to stop
- 1:31:35recording all right and back in the
- 1:31:37animator so over here we have both
- 1:31:39animations and now what we need is to
- 1:31:40make a transition going from idle into
- 1:31:43wonk otherwise the won animation will
- 1:31:45never play so how we make a transition
- 1:31:46is also super simple let's right click
- 1:31:48on the idle State let's make a
- 1:31:50transition then now we have a nice
- 1:31:52little arrow under the mouse and now if
- 1:31:54we go into the walk and click on it
- 1:31:55there you go we have a nice transition
- 1:31:57now we can click on the transition
- 1:31:58itself to selected and over here in the
- 1:32:00inspector we see a bunch of transition
- 1:32:02options so let's expand the settings yep
- 1:32:03there you go everything now like I said
- 1:32:05I covered all of these options in a lot
- 1:32:07of detail in my ultimate unity overview
- 1:32:09course so if you want to learn more go
- 1:32:11watch that here let's just learn the
- 1:32:12basics for how to achieve our goal in
- 1:32:14making a simple player animator the
- 1:32:16important one is over here the exit time
- 1:32:18basically if this one is toggled then
- 1:32:19this transition will be triggered
- 1:32:21automatically meaning it won't play the
- 1:32:22out animation and immedi transition into
- 1:32:24the wonk animation so for example if we
- 1:32:26hit play and look at it quickly you
- 1:32:28there go there's the idle and you have
- 1:32:29transitions into wonk and now it stays
- 1:32:31there forever okay so that's good but
- 1:32:32not exactly what we want we want the
- 1:32:34walk animation to only play When the
- 1:32:36character is walking and when it stops
- 1:32:37we want it to go back into the idle
- 1:32:39animation now for that we need to use
- 1:32:41animator parameters so back in our
- 1:32:43animator on the top left corner we see
- 1:32:45something called layers we don't need to
- 1:32:46worry about that for now and the next we
- 1:32:48we see parameters then we can click on
- 1:32:50the plus button order to create a brand
- 1:32:51new parameter and you can see all the
- 1:32:53various types that we we can create now
- 1:32:54for woning we want something that we can
- 1:32:56set to either true or false so let's go
- 1:32:58with a nice bullion and for name let's
- 1:33:00call it is woning again pay very close
- 1:33:02attention to the capitalization this is
- 1:33:04extremely important just like code is
- 1:33:06walking is different from is walking so
- 1:33:08make sure the capitalization is perfect
- 1:33:10okay so with that we have our nice
- 1:33:11parameter now let's click on transition
- 1:33:13going from idle into won and now let's
- 1:33:15untake exit time we don't want this
- 1:33:17transition to trigger automatically and
- 1:33:19as soon as we do we see this nice little
- 1:33:21warning basically it's telling us that
- 1:33:22this transition will never happen so
- 1:33:24over here we have the nice conditions if
- 1:33:26we click on the plus icon we can add
- 1:33:28some conditions and for this one we want
- 1:33:30this transition to happen from idoling
- 1:33:31to walk when the parameter is walking is
- 1:33:33set to true so that's it this is our
- 1:33:35transition now let's just do the reverse
- 1:33:37so let's right click on the walk make
- 1:33:39Transition go back into idle let's click
- 1:33:41to select transition get rid of the exit
- 1:33:43time and conditions when is Walking is
- 1:33:45set to false okay so just like this our
- 1:33:47basic animation logic should be working
- 1:33:49so let's test so here we are and the
- 1:33:51character is playing the an animation by
- 1:33:53the way can look at the animator while
- 1:33:55the game is running so let me just drag
- 1:33:56the animator window just drag it and put
- 1:33:58it on the side of the game view so we
- 1:34:00can see both at the same time okay great
- 1:34:02and right now note how it's not updating
- 1:34:04so there's nothing moving over here on
- 1:34:06the animator component that is because
- 1:34:07like I said you must select the object
- 1:34:09so on the Hier key make sure you select
- 1:34:10the player Visual and yep there you go
- 1:34:12now you do see that updating so make
- 1:34:13sure the object is selected in the Hier
- 1:34:15key and now over here we see a nice
- 1:34:17little progress bar showing the addal
- 1:34:18animation constantly playing and looping
- 1:34:20okay great and another important thing
- 1:34:21is over here the parameters you can
- 1:34:23manual ually change the state of these
- 1:34:25while the game is running so for example
- 1:34:26if I click it's going to trigger the is
- 1:34:28walking parameter which should trigger
- 1:34:29this transition and should go into W so
- 1:34:31if I click and Y there you go
- 1:34:33transitions into the won animation and
- 1:34:34now yep it is playing the wonking
- 1:34:36animation and if I click to untick it
- 1:34:38look at over there what happens untake
- 1:34:40and there you go transitions back into
- 1:34:42idle all right awesome so as you can see
- 1:34:44we have all of our logic working we have
- 1:34:46the animator with both of our states and
- 1:34:48by changing this parameter we can change
- 1:34:49which animation is playing now of course
- 1:34:51the goal is not to trigger this manually
- 1:34:53by clicking on it but rather doing it
- 1:34:54through code but at least for now we
- 1:34:56know that our animator is fully set up
- 1:34:58again if you want more detail on the
- 1:34:59animator and animation windows and
- 1:35:01everything related to animations then
- 1:35:03check out those lectures in my ultimate
- 1:35:04D overview course and also later on for
- 1:35:06more advanced use case I have a video on
- 1:35:08the animation rigging package this one
- 1:35:10is for more advanced use cases for
- 1:35:11making Dynamic procedural animations
- 1:35:13it's really fun so definitely check it
- 1:35:15out but only after finishing this course
- 1:35:16that one is a much more advanced tool
- 1:35:18for now let's continue here so we want
- 1:35:20to trigger our parameter but do it
- 1:35:21through code and again here we have yet
- 1:35:23another clean code question technically
- 1:35:25we could add that code directly over
- 1:35:26here on the player script we could just
- 1:35:28grab the animated component and change
- 1:35:30the parameter and in this case for this
- 1:35:32very simple game that would actually not
- 1:35:33necessarily be a very bad approach since
- 1:35:35the game is so simple with so few
- 1:35:37animations but like I said I want to
- 1:35:39teach you proper good practices so let's
- 1:35:41make it properly and actually separate
- 1:35:43the animations from the logic for that
- 1:35:44let's go into our project right click in
- 1:35:46our scripts folder create a new C script
- 1:35:48let's call it the player animator let's
- 1:35:50select the player visual game object and
- 1:35:52attach the component okay okay so now
- 1:35:54here first let's grab the animator now
- 1:35:56one approach is like we've seen we could
- 1:35:58just make a serialized field and drag
- 1:35:59the reference in the editor that's one
- 1:36:01approach or alternatively since the
- 1:36:03animator is attached to the same game
- 1:36:05object as this script then we can just
- 1:36:06do a get component both approaches are
- 1:36:08really valid so here let's use get
- 1:36:10component just to see a different
- 1:36:11approach so we just have a field for our
- 1:36:13animator so animator and then we just do
- 1:36:16a private void awake and on a w let's do
- 1:36:18get component of type animator and we
- 1:36:21set our animator variable again like I
- 1:36:23mention very important make sure you
- 1:36:24don't mix animator and animation these
- 1:36:27are two different components we want the
- 1:36:29animator okay so with this we have a
- 1:36:31reference to our animator component and
- 1:36:33now how we modify the parameter is
- 1:36:34actually very simple we just access the
- 1:36:37animator and then we have a bunch of set
- 1:36:38functions you can see we have one for
- 1:36:40each type so we've got a set bow set
- 1:36:42float then down here a set trigger set
- 1:36:44Vector so function to set any parameter
- 1:36:46type now we made the bullan so let's use
- 1:36:48the set B and this one as you can see
- 1:36:50takes the name for the animator
- 1:36:51parameter by the way strings are a hor
- 1:36:53horrible horrible way of identifying
- 1:36:55things but sadly this system really does
- 1:36:57require strings to identify the
- 1:36:58parameter we want to change if you're
- 1:37:00wondering why strings are bad for
- 1:37:01identifying things the reason is because
- 1:37:03it's very easy to make a mistake for
- 1:37:05example if you use is walking here then
- 1:37:07this will work however if you instead
- 1:37:09write is walking then all of a sudden
- 1:37:11does not work if you write is walking
- 1:37:13like this doesn't work like this doesn't
- 1:37:15work and even though it doesn't work it
- 1:37:17will also not throw any compiler errors
- 1:37:19that is because for the compiler a
- 1:37:20string is a string it's always valid but
- 1:37:22then when the code runs this one is
- 1:37:23going to be different than our parameter
- 1:37:25which is named the Exel like this always
- 1:37:26remember that strings are case sensitive
- 1:37:28so that's one reason why you should
- 1:37:30never use strings to identify things
- 1:37:32it's very very easy to make tons of
- 1:37:34mistakes that are then very difficult to
- 1:37:35find out but like I said in this
- 1:37:37animator system we have to use strings
- 1:37:39there's no other way in order to
- 1:37:40minimize our usage of strings one thing
- 1:37:42we can do is for example let's find find
- 1:37:44a constant up here so let's make a
- 1:37:46private make it Con for a Conant meaning
- 1:37:48this will never change make it up type
- 1:37:50string and call it is walking again
- 1:37:52refer back into the naming R section for
- 1:37:54constants we always use uppercase snake
- 1:37:57case so is walking and let's set it with
- 1:37:59is walking again make sure you don't
- 1:38:01make a mistake here make sure you type
- 1:38:03it exactly like you did on the animator
- 1:38:04then down here let's use is won and now
- 1:38:06if we do make a mistake so if we
- 1:38:08accidentally use something different now
- 1:38:10we do get a compiler error so at least
- 1:38:11we have a little bit of protection okay
- 1:38:13so this one takes a string for the name
- 1:38:15and then a simple bullion for the value
- 1:38:17so this going to be the value that we
- 1:38:18want to set to our parameter now for
- 1:38:20this one we want to set to True when the
- 1:38:21player is walking and false when it's
- 1:38:23not so for that we need to ask the
- 1:38:25player what it's doing so let's go over
- 1:38:27here into our player class and let's
- 1:38:29make a function to return just that so
- 1:38:31let's make it public because we're going
- 1:38:32to access it from another script we're
- 1:38:34going to return a bll and call it is
- 1:38:36walking now over here we just need to
- 1:38:37return if the player is walking so let's
- 1:38:39make a local field to store that safe so
- 1:38:41over here private ball is walking again
- 1:38:44note the capitalization for fields we
- 1:38:47start with camel case whereas for
- 1:38:49functions we have Pascal case so these
- 1:38:50are different okay so basically in order
- 1:38:52to Define if we we are walking that's
- 1:38:54very simple it's just down here we have
- 1:38:55the movement Direction so we are walking
- 1:38:57if the move direction is different from
- 1:38:59Vector 3.0 which by the way Vector 3.0
- 1:39:02is just a shorthand for writing 0 0 so
- 1:39:05if the movement direction is different
- 1:39:06from zero then we are indeed walking so
- 1:39:08we Define that we update that field on
- 1:39:10every update and then over here we just
- 1:39:11return it okay just like this and now
- 1:39:13back in our player animated component
- 1:39:15over here first we need a reference to
- 1:39:17the player so let's add it here let's
- 1:39:18add a serialized field of type player
- 1:39:22and we need to compile this in order
- 1:39:23drag the reference so let's just comment
- 1:39:25out this line just to make sure the code
- 1:39:26compiles now here with the code compile
- 1:39:28let's drag the reference of our player
- 1:39:30okay that's it and then over here for
- 1:39:32the animator set is walking let's go
- 1:39:34into the player and let's ask is walking
- 1:39:36and of course we don't want to do this
- 1:39:38just on awake we want to do it on every
- 1:39:40single frame so let's do a private void
- 1:39:42update and on update let's do this all
- 1:39:45right that's it so this should be
- 1:39:46working let's test so here we are
- 1:39:48starting off as Idle and now as I move
- 1:39:50yep there you go it is playing The
- 1:39:51Walking animation and now if if I stop
- 1:39:54and you there go back into Idol all
- 1:39:55right Awesome everything does work
- 1:39:57perfectly okay great we can even look at
- 1:39:59the animator to see the state change so
- 1:40:01here with both side by side and with the
- 1:40:03object selected in the hierarchy right
- 1:40:05now you can see is walking is false so
- 1:40:06it's on idle and as I move that one says
- 1:40:08true that one goes into walk and now I
- 1:40:10let go if there go back into false back
- 1:40:13into idle all right awesome so with this
- 1:40:15everything is working perfectly if
- 1:40:17you're having issues make sure you pay
- 1:40:19attention to the capitalization so make
- 1:40:21sure the name you wrote here is the
- 1:40:23exact exactly the same one that you
- 1:40:24wrote here and it's exactly the same
- 1:40:26that you're using here all right so all
- 1:40:28of our animations are working perfectly
- 1:40:30now if you want you can go ahead and
- 1:40:31make your own animations or you can use
- 1:40:33the ones that I pre-built so in the
- 1:40:35included project files inside the assets
- 1:40:37here we've got the animations and we've
- 1:40:39got the player with the idle and the
- 1:40:40walk animations if we double click on
- 1:40:42this to look at it you can see yep it
- 1:40:44looks exactly the same so there's a
- 1:40:46parameter called is walking and our
- 1:40:47transition so everything is exactly the
- 1:40:49same just over here let's select the
- 1:40:51player Visual and on the prefab like we
- 1:40:52saw we already had the animated
- 1:40:54component we just remove that one from
- 1:40:55the prefab in order to build it off from
- 1:40:57scratch but if you want to use my
- 1:40:59animations then we can just go ahead
- 1:41:00remove the animator that we added and
- 1:41:02then right click on this one on the
- 1:41:03remove component let's revert back to
- 1:41:05changes and there you go here we have
- 1:41:06our animator with the player controller
- 1:41:08so that's the one in the included
- 1:41:10animations and just like this if we h on
- 1:41:12play and actually over here I found an
- 1:41:14issue although in your case there
- 1:41:15shouldn't be any issue because I have
- 1:41:17updated the assets but this is a good
- 1:41:18time to teach you about any issues with
- 1:41:20animations so if you select the
- 1:41:22animation and you select the animation
- 1:41:23and over here you might see some of them
- 1:41:25in yellow saying missing basically the
- 1:41:27way that animations work is based on the
- 1:41:29actual name of the object if it cannot
- 1:41:31find an object with the exact same name
- 1:41:32then it cannot load the same animation
- 1:41:34so my problem is that when I initially
- 1:41:36made the assets package I made this
- 1:41:38animation and the object was previously
- 1:41:40named face and then I renamed it thee so
- 1:41:42now it no longer loads so if you ever
- 1:41:44have problems with loading animations
- 1:41:45just make sure the names perfectly match
- 1:41:47so in my case I can just click in here
- 1:41:49in order to rename this key frame on the
- 1:41:50animation and I'm just going to use the
- 1:41:52name that I renamed named it so head and
- 1:41:54just like this yep the animation does
- 1:41:56play correctly so just a nice quick tip
- 1:41:58if you ever have problems with
- 1:41:59animations always remember that the
- 1:42:00stored key frames they're all stored
- 1:42:02based on name so if you rename the thing
- 1:42:04in here or over here on the game object
- 1:42:06if you rename you're going to have
- 1:42:07missing animations but if you make sure
- 1:42:09the names match and the animation should
- 1:42:11load perfectly so let's head on play and
- 1:42:13there you go there's the add animation
- 1:42:14and if I move yep there's the nice walk
- 1:42:16animation so everything still works
- 1:42:18perfectly because it's only using the
- 1:42:19exact same parameters all right awesome
- 1:42:21so like I said if you want feel free to
- 1:42:23make your own animations or use the ones
- 1:42:25that I've included for me I'm going to
- 1:42:27be using these ones so the ones that we
- 1:42:29made just for learning which I created
- 1:42:30down here so the M player animator and
- 1:42:32these animations I'm just going to
- 1:42:33delete these just to keep the project
- 1:42:35clean so just delete and just like that
- 1:42:37okay so now that we have our character
- 1:42:39fully working let's quickly handle our
- 1:42:42camera hello and welcome I'm your code
- 1:42:45monkey in this lecture we're going to
- 1:42:47quickly install C Machine this is a
- 1:42:48Unity tool that makes handling cameras
- 1:42:50super easy our game isn't really going
- 1:42:52to have a moving camera so this part
- 1:42:54isn't strictly necessary but s machine
- 1:42:56is a super useful tool so I definitely
- 1:42:58want you to learn about okay so let's
- 1:42:59begin by installing the package let's go
- 1:43:01into window open up the package manager
- 1:43:03then up top let's make sure we are in
- 1:43:05the unity registry make sure you're on
- 1:43:07the all Tab and now just scroll down
- 1:43:09until you find yep there it is C Machine
- 1:43:11okay so let's go ahead and install
- 1:43:13this all right it's installed so let's
- 1:43:15close this and now the way that sin
- 1:43:17Machine Works is by creating what is
- 1:43:19called a sin machine virtual camera so
- 1:43:21let's go up top into the game object
- 1:43:22menu then scroll down into sin machine
- 1:43:25and over here you can see that we can
- 1:43:26create a multitude of virtual camera
- 1:43:28types now just by the names you can see
- 1:43:30how this tool is insanely useful for
- 1:43:32example making a fre low camera doing
- 1:43:34that from scratch is a bit tricky but
- 1:43:35with s machine it is super easy for our
- 1:43:37case like I said we want the absolute
- 1:43:39most basic thing possible so let's just
- 1:43:41create an empty virtual camera okay
- 1:43:43that's it this creates a virtual camera
- 1:43:45over here in the Hier key and turn this
- 1:43:47object has a s machine virtual camera
- 1:43:49component and also importantly when we
- 1:43:50added this it also added over here on
- 1:43:52the camera if we scroll down we can see
- 1:43:54it has a C Machine brain component
- 1:43:56basically the way C Machine Works is it
- 1:43:58works on top of the main camera so it
- 1:44:00doesn't replace it it works on top of it
- 1:44:02and drives the main camera so now that
- 1:44:03we're using C Machine if we try
- 1:44:05modifying the main camera game object so
- 1:44:07for example over here if I try to drag
- 1:44:09the FI of view nope does not work I
- 1:44:11cannot move it if I try to move the
- 1:44:13position nope can't do it if I try to
- 1:44:14rotate it nope that does not work like I
- 1:44:16said when working with sin machine the S
- 1:44:18machine brain is what drives the main
- 1:44:20camera so rather than modifying the
- 1:44:21things over here on the camera itself
- 1:44:23what we need to do is change them on the
- 1:44:25virtual camera so over here we have
- 1:44:27pretty much the exact same options that
- 1:44:28we have on the main camera for example
- 1:44:30modifying the fov over here we've got
- 1:44:32the lens so we can modify the fov and if
- 1:44:34we look in the game scene as we modify
- 1:44:36this one yep it does modify the actual
- 1:44:38properties on the actual main camera now
- 1:44:39this has tons and tons of options
- 1:44:41related to everything the most important
- 1:44:42ones are all kinds of options down here
- 1:44:44for the body and the aim so this is
- 1:44:46where the camera is position and where
- 1:44:48it's looking at using this you can make
- 1:44:50a follow camera in 5 seconds it really
- 1:44:52is insanely useful if you want to learn
- 1:44:53about C Machine more detail I have a
- 1:44:55dedicated video on it I go through what
- 1:44:57all of these options do then I also have
- 1:44:59another super detailed video on how to
- 1:45:01make a camera system with pan Zoom
- 1:45:03scroll in both 2D and 3D and a bunch
- 1:45:05more features again all of it using S
- 1:45:07machine but in our case we really want
- 1:45:09to keep it simple so let's just position
- 1:45:10our virtual camera on the same settings
- 1:45:12that we had previously so first let's
- 1:45:14set the FI The View so for our game we
- 1:45:16want something narrow so let's go with
- 1:45:17just 20 then for the position let's put
- 1:45:19it above so zero on the X then 21.5 on
- 1:45:23the Y and minus 21.3 on the Zed then for
- 1:45:25the rotation 46 on the X and then zero
- 1:45:28on the others okay so our camera is
- 1:45:29positioned in the exact same position
- 1:45:31and if we head on play yep everything
- 1:45:32still works the same the camera is
- 1:45:33looking from the same point of view and
- 1:45:35the character still works everything's
- 1:45:36still exactly the same now since we're
- 1:45:38using cin machine we can easily add some
- 1:45:39things on top of this like for example
- 1:45:41we can add some noise to our sin machine
- 1:45:43camera to make it smoothly move a little
- 1:45:45bit this one is a fun simple effect that
- 1:45:47can make our game feel a bit more
- 1:45:48Dynamic especially in games like this
- 1:45:50where we have a fixed overhead view how
- 1:45:52we do that is over here on the in
- 1:45:53machine virtual camera we've got a film
- 1:45:55for noise so let's click and let's
- 1:45:56select basic multi Channel pein and then
- 1:45:59over here we've got the noise profile so
- 1:46:00we can choose one of the included ones
- 1:46:02or we can create our own profile so for
- 1:46:04example let's go with handheld normal
- 1:46:05mild and by the way you can actually
- 1:46:07modify these settings while the game is
- 1:46:08playing so here it is the game playing
- 1:46:10and you can see what this effect does it
- 1:46:11adds a nice little wobble to the camera
- 1:46:13and then over here alude and frequency
- 1:46:15so we can play around these so you can
- 1:46:16make it really intense so something like
- 1:46:18this that is way too intense so there
- 1:46:20you go quite a lot so for something more
- 1:46:22subtle maybe put 0.5 and 0.5 there you
- 1:46:24go just a slight little movement in the
- 1:46:26camera so this would help make the game
- 1:46:27a little bit more Dynamic so this could
- 1:46:29be a fun effect although actually in my
- 1:46:31case in order to make sure that the
- 1:46:32video doesn't get way too compressed I'm
- 1:46:34actually going to Z this on my end so
- 1:46:36just set the channel noise to none but
- 1:46:37you can see how easy it is to add
- 1:46:39complex Cammer features when using C
- 1:46:41Machine and of course when using C
- 1:46:42Machine if you want you can use it to
- 1:46:43make your game a lot more unique now for
- 1:46:45me I want to design here where the
- 1:46:47camera is fixed but let's say for
- 1:46:48example you wanted the camera to
- 1:46:50actually follow the player like I said
- 1:46:51go watch that dedicated video to to
- 1:46:53learn all about C Machine but over here
- 1:46:55very quickly let me just show you how to
- 1:46:56do that but at the same time don't
- 1:46:58bother following this part it's just to
- 1:46:59show what C Machine can do that I'm
- 1:47:00going to revert back to this state so
- 1:47:02first of all for testing one great thing
- 1:47:03about C Machine is you can have multiple
- 1:47:05virtual cameras you can have as many as
- 1:47:07you want and then the priority and the
- 1:47:09game object enabled state is what
- 1:47:10defines which camera is actually being
- 1:47:12used so for example on this second one
- 1:47:14let's make it follow the camera and put
- 1:47:15the priority on 20 so that it's above
- 1:47:17then over here for the body I'm going to
- 1:47:18select transposer let's put it with
- 1:47:21worldspace it requires a follow Target
- 1:47:23so let me drag the player as the follow
- 1:47:25Target and put it slightly above and
- 1:47:28behind Okay so it's pretty similar as
- 1:47:30before then for the aim let me also drag
- 1:47:32the aim player Target and just with this
- 1:47:34it should already work so if I head on
- 1:47:35play y there you go look at that the
- 1:47:37camera is now moving and falling the
- 1:47:39player so I can move the player anywhere
- 1:47:40and yep the camera Falls alone so as you
- 1:47:42can see it's this simple to really make
- 1:47:43some complex camera movement doing some
- 1:47:45complex camera logic just like this
- 1:47:47would require a ton of work manually but
- 1:47:49with s machine it is super easy then you
- 1:47:51can even play around with other prior
- 1:47:52priority or enable and disable and there
- 1:47:54you go C Machine even transitions
- 1:47:56between the state of all your virtual
- 1:47:58cameras so as you can see lots and lots
- 1:47:59of things you can make with your camera
- 1:48:01very easily all thanks to S machine like
- 1:48:03I said in my case I just want a fix
- 1:48:05overhead camera so I'm just going to
- 1:48:06delete this secondary virtual camera and
- 1:48:08there you go just this one on top
- 1:48:09looking at the player looking down with
- 1:48:11a low fov and Yep this is the exactly
- 1:48:13the kind of camera that I want for my
- 1:48:15game okay so that's in machine it's a
- 1:48:17really awesome tool for making camera
- 1:48:18handling much much easier so this was a
- 1:48:21quick lecture all about learning about
- 1:48:22in machine now let's handle the test
- 1:48:24that was actually left undone quite a
- 1:48:25while ago let's finally learn how to
- 1:48:27refactor code and implement the new
- 1:48:29input system so let's do that in the
- 1:48:31next
- 1:48:32lecture hello and welcome I'm your Cod
- 1:48:34monkey in this lecture we're going to
- 1:48:36refactor our code from the Legacy input
- 1:48:38manager onto the new input system so the
- 1:48:41simple character controller that we made
- 1:48:42is working perfectly fine with the
- 1:48:44Legacy input manager like I said this
- 1:48:46one is excellent for making quick
- 1:48:47prototypes and demos as you can see it's
- 1:48:49super easy to use but now let's quickly
- 1:48:52refactor this code to use the new input
- 1:48:53system instead also like I said in the
- 1:48:55beginning of this course here I'm going
- 1:48:57to be focused primarily on building this
- 1:48:58game so for example for any Unity tools
- 1:49:01that I use like the new input system I'm
- 1:49:02going to cover enough to be able to use
- 1:49:04a tool and Achieve our goals in building
- 1:49:06this game but of course every tool does
- 1:49:08a lot more than just what we're going to
- 1:49:09use so definitely make sure to watch a
- 1:49:11dedicated videos Link in the description
- 1:49:13for example the input system tutorial is
- 1:49:1540 minutes long covering everything you
- 1:49:16need to know about system whereas here
- 1:49:18we're just going to learn enough to know
- 1:49:19how to use it so let's refactor this
- 1:49:21code to make it work with with new input
- 1:49:23system except before we work with new
- 1:49:25input system let's just refactor this
- 1:49:27code so we can completely decouple the
- 1:49:29input from the player class again we
- 1:49:31want to focus on writing good clean code
- 1:49:34so we should keep all of our input logic
- 1:49:35in its own class that other scripts can
- 1:49:37access remember the goal with clean code
- 1:49:40is to minimize and manage complexity so
- 1:49:42every class should do one thing and just
- 1:49:44one thing meaning that the player class
- 1:49:46should only handle the player and then
- 1:49:48the input lass should only handle the
- 1:49:50input the only reason why I put this
- 1:49:52over here in beginning is exactly to
- 1:49:53teach you about refactoring and how it's
- 1:49:55a very common thing that you should be
- 1:49:56doing all the time this is exactly how I
- 1:49:59build my own games I start by making a
- 1:50:01prototype and I write the input directly
- 1:50:03inside the player class then at some
- 1:50:04point I refactor the code to split them
- 1:50:06up so don't be afraid to refactor code
- 1:50:09it's a Perfectly Natural part of the
- 1:50:10game da process and actually a very very
- 1:50:12good thing okay so let's make a script
- 1:50:15just to manage our inputs let's make a
- 1:50:17new C script call this game input let's
- 1:50:21create an empty game object give it this
- 1:50:22same name input as always keep things
- 1:50:24clean so put it on 0 0 0 Let's attach
- 1:50:27the script and open okay so here's our
- 1:50:29script and let's get everything related
- 1:50:31to the inputs on the player for the
- 1:50:33input we are culating the input Vector
- 1:50:35then getting the actual inputs from the
- 1:50:37keyboard and returning the input Vector
- 1:50:39so let's put this on the other script so
- 1:50:42over here let's make a new function
- 1:50:44let's make it public since we want to
- 1:50:46access it from the player we're going to
- 1:50:48return a vector 2 and let's call it get
- 1:50:50movement vector
- 1:50:53now here let's really just copy paste
- 1:50:54the exact same code that we have on the
- 1:50:56player so let's copy paste all of this
- 1:50:58let's go and paste it here okay so we
- 1:51:00get the input Vector we get the inputs
- 1:51:03we normalize it and then return the
- 1:51:04input
- 1:51:05Vector okay so that's it super simple
- 1:51:08also by the way here we have an
- 1:51:10interesting question which is do we
- 1:51:12normalize the input over here or do we
- 1:51:14do it over here on the player both
- 1:51:16options can be valid you can make it so
- 1:51:18that the game input class returns a
- 1:51:20regular input or or you can make it
- 1:51:23return a normalized vector you can use
- 1:51:25either option but whatever you do make
- 1:51:27sure you are explicit so over here I am
- 1:51:29going to normalize input inside the game
- 1:51:31input class however I'm also going to
- 1:51:33make sure to rename this function so
- 1:51:35instead of get movement Vector get
- 1:51:36movement Vector normalized that way it
- 1:51:39is 100% clear this Returns the movement
- 1:51:41Vector as a normalized vector okay great
- 1:51:44so now let's use this in our player over
- 1:51:47here in our player class we need some
- 1:51:48reference to our input class now later
- 1:51:51on in this course I'm going to teach you
- 1:51:53about the Singleton pattern but for now
- 1:51:55let's just do a simple direct reference
- 1:51:57again remember don't make it public make
- 1:52:00it a serialized fi private so over here
- 1:52:03let's make a serialized fi private of
- 1:52:05type game input and let's call it just
- 1:52:07game
- 1:52:09input okay so we have this we're going
- 1:52:11to drag it in the editor then over here
- 1:52:13we simply grab the vector 2 for the
- 1:52:15input Vector we simply go into this one
- 1:52:18and we get the movement vector
- 1:52:19normalized and okay that's it no more
- 1:52:21errors let's just make make sure to save
- 1:52:23all of our scripts and back in the
- 1:52:24editor let's go into the player and just
- 1:52:26drag the reference for the game input
- 1:52:28okay so just like this everything should
- 1:52:30still work everything should work
- 1:52:32exactly the same as previously Let's
- 1:52:34test and make sure so here we are moving
- 1:52:36and yep everything still works I can
- 1:52:38move in any direction okay so far so
- 1:52:40good and what we have done here is
- 1:52:42essentially we have refactored our code
- 1:52:44and completely separated the input from
- 1:52:46the player class this is an excellent
- 1:52:48thing so again don't be afraid to
- 1:52:49refactor code also what we did here of
- 1:52:52putting the code in a separate class and
- 1:52:54then doing a quick test to make sure
- 1:52:55that everything still works the same as
- 1:52:57previously this is exactly what you
- 1:52:58should do whenever you do some kind of
- 1:53:00reorganizational refactoring in the end
- 1:53:02you want to end up with the exact same
- 1:53:04behavior as previously just with a code
- 1:53:06organized in a different way okay so now
- 1:53:08that we have the separate game input
- 1:53:10class now we can very easily refactor
- 1:53:12the Legacy input manager onto the new
- 1:53:14input system so the first thing we need
- 1:53:16is to install the package so let's open
- 1:53:18up the package manager let's make sure
- 1:53:20up here we are in the unity registry
- 1:53:22make sure we are in all and let's scroll
- 1:53:24down to find the input system so here it
- 1:53:27is let's go ahead and
- 1:53:29install Okay the package is installed
- 1:53:31and right away we see this message
- 1:53:33basically it's asking us if we want to
- 1:53:35enable the new input system now you
- 1:53:37could click on yes but let's actually go
- 1:53:39ahead and click on no we're going to
- 1:53:40enable it manually so click on no then
- 1:53:43let's close this window and now let's go
- 1:53:45up here into edit then let's go into
- 1:53:47project settings then on the left side
- 1:53:50let's go into player and now let's
- 1:53:51scroll down expand over here the other
- 1:53:54settings tab and keep scrolling down
- 1:53:56until we see yep here it is the active
- 1:53:58input handling this is where you can
- 1:54:00select which input system you're using
- 1:54:02basically if you click yes on that
- 1:54:03window it would automatically set this
- 1:54:05option to use the new input system so it
- 1:54:08would only enable that one and
- 1:54:09completely disable the Legacy input
- 1:54:11manager but like I said the Legacy input
- 1:54:13manager is still pretty useful so
- 1:54:14normally for me I prefer to enable both
- 1:54:16of them so let's go ahead click on both
- 1:54:19and this will restart the editor so okay
- 1:54:21let's go all right the editor has restar
- 1:54:23so now the new input system is now
- 1:54:25enabled okay so the way that this system
- 1:54:28works is by creating something called an
- 1:54:29input actions asset so on the project
- 1:54:32files let's click on the plus icon let's
- 1:54:34create something and let's find the
- 1:54:36input actions so we need to scroll down
- 1:54:38here so click on the little arrow to go
- 1:54:40down and find the input actions creates
- 1:54:42this file let's call this the player
- 1:54:44input
- 1:54:45actions okay now let's go ahead and
- 1:54:47double click on it and yep there you go
- 1:54:49out pops out the input system window
- 1:54:51basically this this one is where we're
- 1:54:53going to manage all of these settings
- 1:54:54for all of our inputs also by the way
- 1:54:56like I've mentioned if you're watching
- 1:54:57this in the future and for some reason
- 1:54:59the input system got a new update and
- 1:55:00change this window if so make sure you
- 1:55:02check the pin comment I'll keep it
- 1:55:04updated with any changes on anything in
- 1:55:06this course so over here we've got the
- 1:55:08action Maps then we've got the actions
- 1:55:11and then we've got properties now action
- 1:55:13maps are how you can have different maps
- 1:55:15for example one action map would be for
- 1:55:17the player whilst walking normally and
- 1:55:19you could have another one whilst
- 1:55:20driving a vehicle then for the
- 1:55:22individual actions in each action map
- 1:55:24and finally the properties for each
- 1:55:26action again if you want to learn about
- 1:55:28the entire input system itself in more
- 1:55:30detail go ahead and watch my dedicated
- 1:55:31video on it in order for this course to
- 1:55:33not to be 20 hours long I'm really only
- 1:55:35going to use enough to make sure that we
- 1:55:37can achieve our goal so over here we
- 1:55:39just need one action map so let's click
- 1:55:40on the plus icon let's name this the
- 1:55:42player and now for the actions right
- 1:55:44away we have a new action so let's just
- 1:55:47rename this one let's call this action
- 1:55:50move then with this action selected over
- 1:55:52here on the Action Properties we can
- 1:55:53select the action type again in the
- 1:55:56dedicated video I cover what all of
- 1:55:57these mean for movement we do not want a
- 1:56:00button we want movement in multiple
- 1:56:02directions so let's go with value then
- 1:56:04over here for the control type for this
- 1:56:06one let's go with a vector 2 and then
- 1:56:08let's expand our action over here we can
- 1:56:10see our bindings however we don't want
- 1:56:12this default binding so let's actually
- 1:56:14delete this one instead let's click on
- 1:56:15the plus icon and over here for the type
- 1:56:18first for the keyboard let's go with
- 1:56:19this one up down left right composite so
- 1:56:22this one adds essentially four bindings
- 1:56:24let's go ahead and name this
- 1:56:26was then for the up let's select the
- 1:56:28bindings so over here on the path let's
- 1:56:29click on it then we can either find it
- 1:56:31manually over here or click on listen
- 1:56:33and now press the W button yep there you
- 1:56:35go W then for down let's go ahead listen
- 1:56:38s then for the left listen a and for the
- 1:56:42right let's listen D okay great so with
- 1:56:46this our input asset is correctly set up
- 1:56:48one thing you must never forget is up
- 1:56:50here make sure to save the asset
- 1:56:52you can see this little Sisk here that
- 1:56:54means we have unsaved changes also
- 1:56:57alternatively there's an autosave there
- 1:56:59but for now let's just manually save the
- 1:57:00asset okay great so now let's see how to
- 1:57:03actually use this in our code there are
- 1:57:06many ways we can use the input system
- 1:57:08one way is by using the built-in player
- 1:57:10input component so for example on the
- 1:57:12player we would add the player input so
- 1:57:15you could add this one attach an input
- 1:57:17actions asset so this is our player
- 1:57:19input actions then over here we have
- 1:57:21various behaviors in order to be able to
- 1:57:22trigger our actions but in this course
- 1:57:25like I said I'm going to be using the
- 1:57:26exact same code quality that I used in
- 1:57:28my own Steam games so I will not be
- 1:57:30using this component so let's remove
- 1:57:31this instead I will be using the native
- 1:57:34C method so let's select the player
- 1:57:36input actions and over here on the
- 1:57:38inspector we see this nice toggle to
- 1:57:40generate a C Class let's go ahead enable
- 1:57:43it and for these fields we can leave
- 1:57:45them all on defaults that's okay let's
- 1:57:46just go ahead click on apply and now
- 1:57:49it's going to generate those scripts and
- 1:57:50compile them okay great basically what
- 1:57:52this is doing is autogenerating some C
- 1:57:54code and on the player input actions we
- 1:57:57can see over here yep we've got the
- 1:57:58generated script if you want you can
- 1:58:00even open this to see all of the source
- 1:58:02code now all this like it says here this
- 1:58:04was all autogenerated so don't make any
- 1:58:07modifications here if you change
- 1:58:09anything any manual changes won't be
- 1:58:11lost when you save some changes in the
- 1:58:12input asset so if you want go ahead and
- 1:58:15read through in order to see how all
- 1:58:16this works but in order to use it it's
- 1:58:18actually super simple you don't need to
- 1:58:20worry about this script first thing we
- 1:58:21need is to construct our script class
- 1:58:23that was autogenerating so let's do it
- 1:58:25over here in our game input let's make a
- 1:58:28private void awake and on awake let's
- 1:58:30construct it so let's do a new player
- 1:58:33input
- 1:58:34actions so we construct an object of
- 1:58:37this
- 1:58:40type so we have this although just like
- 1:58:43this it won't be active so we need to
- 1:58:44manually activate whatever action map we
- 1:58:47want so let's go inside and let's go
- 1:58:49inside the player so this is the action
- 1:58:50map that we created and let's call
- 1:58:52enable on it okay so just like this it's
- 1:58:55really already working all we need to do
- 1:58:57is modify our code over here on the get
- 1:58:59movement Vector so for that we're going
- 1:59:00to need to access this so let's actually
- 1:59:02make this a member variable so private
- 1:59:05let's store it up here instead of making
- 1:59:07a local variable in here okay so we have
- 1:59:10this one and then down here on the input
- 1:59:12Vector let's go inside the player input
- 1:59:14actions inside the player action map and
- 1:59:16then we called it move so we've got this
- 1:59:18one and then we defined it as a vector 2
- 1:59:21so over here we can call read value and
- 1:59:23this one takes in the type of the value
- 1:59:25now we Define it as a vector 2 so let's
- 1:59:27read it as a vector 2 and just like this
- 1:59:30this returns a vector 2 which is really
- 1:59:32going to be our input Vector so let's
- 1:59:33put it exactly like this and we can now
- 1:59:36get rid of the rest of it all right so
- 1:59:39that's it and just like this we should
- 1:59:40already have everything working exactly
- 1:59:42the same as previously so let's just do
- 1:59:44a debug.log just to make sure so let's
- 1:59:47test so here we are and the output is 0
- 1:59:500 now I press W there you go Plus plus
- 1:59:52one minus one left right and all of the
- 1:59:54ones in between all right awesome so we
- 1:59:57have the new input system all of it
- 1:59:59working flawlessly also by the way over
- 2:00:01here we can normalize the input just
- 2:00:03like we were doing previously so we do
- 2:00:04it over here through code or
- 2:00:06alternatively we can also go into the
- 2:00:08player input actions and over here
- 2:00:09there's something called a processor so
- 2:00:11you can go into this action add a
- 2:00:13processor and make it normalized so
- 2:00:15these processes here can be quite useful
- 2:00:18I covered them all in detail in the
- 2:00:19other dedicated video but over here
- 2:00:21let's stick with making it through code
- 2:00:22that works just as well okay so that's
- 2:00:24our refactoring done with that simple
- 2:00:26change we are now using the new input
- 2:00:28system so you can see how by refactoring
- 2:00:30our code to make sure to use the game
- 2:00:32input class when we change from the
- 2:00:34input manager onto the new input system
- 2:00:36when we made that change we did not have
- 2:00:38to touch a player class at all the
- 2:00:40player class just has the game input to
- 2:00:42get the movement vector and does not
- 2:00:44care what system he uses to get that so
- 2:00:46here we have a very practical very
- 2:00:48excellent example of the power of
- 2:00:49writing good clean code because we separ
- 2:00:52things correctly we manage to change
- 2:00:53something completely and not have to
- 2:00:55make any changes on any other class so
- 2:00:58now that we're using the new input
- 2:00:59system let's just quickly see one of the
- 2:01:01main benefits of this system which is
- 2:01:03easily supporting game pads and more
- 2:01:05keys for example a lot of people like
- 2:01:07using was but some people also like to
- 2:01:09use the arrow keys with this system that
- 2:01:12is super easy to add so let's go into
- 2:01:14the move let's add another one let's add
- 2:01:15another one up down left right composite
- 2:01:18let's call it arrow keys then let's just
- 2:01:20put them so let's listen on on the up
- 2:01:22Arrow then over here we've got the down
- 2:01:25arrow then we have the left arrow and
- 2:01:29finally we have the right arrow all
- 2:01:31right so we've got all the arrows and
- 2:01:33now we don't even need to touch any code
- 2:01:34at all let's just make sure to save the
- 2:01:36ENT which again in turn that is going to
- 2:01:38autogenerate the C class and going to
- 2:01:40compile okay so we don't need to touch
- 2:01:42any code at all let's just hit on play
- 2:01:44and now if I move we're using the was
- 2:01:46Keys yep still works and if I go into
- 2:01:48the arrow keys yep also still works all
- 2:01:50right great now for another one let's
- 2:01:52make it for a game pad so I just
- 2:01:55connected an Xbox controller and we can
- 2:01:57see over here on the log yep the game
- 2:01:59did identify it so this is the new input
- 2:02:01system in action let's once again open
- 2:02:03up the input actions and over here on
- 2:02:05the Move let's set another one and this
- 2:02:07time let's just make it a regular
- 2:02:09binding and now over here on the path
- 2:02:11once again if we want we can go down
- 2:02:13here and specifically find some
- 2:02:15joysticks so you can find any of them or
- 2:02:17once again let's just use the en listen
- 2:02:19now I'm just going to move the thumb
- 2:02:21stick on the controller yep there it is
- 2:02:22and now if you wanted you could go
- 2:02:24specific and make it just work with Xbox
- 2:02:25controllers or you can just use the
- 2:02:27generic left sick this will make it work
- 2:02:29with an Xbox controller or a PlayStation
- 2:02:31or really anything so let's go with this
- 2:02:33one and that's it nothing else we need
- 2:02:35to do let's just save the asset and
- 2:02:37that's it we don't need to touch any of
- 2:02:39our code to make our game playable with
- 2:02:40a controller so let's go ahead and test
- 2:02:43so here we are and first of all if I
- 2:02:45move the keys yep C Works move the arrow
- 2:02:47keys yep both of them works and now if I
- 2:02:49use my Gamepad and yep there you go
- 2:02:51everything works perfect perfectly all
- 2:02:53right awesome so as you can see this is
- 2:02:55one of the main benefits of the new
- 2:02:56input system it makes handling different
- 2:02:58inputs really super easily as you saw we
- 2:03:01didn't have to touch our code at all we
- 2:03:03just add new bindings and just like that
- 2:03:05our game is playable with all kinds of
- 2:03:07inputs so here you can really see just
- 2:03:10how powerful new input system is okay so
- 2:03:12with this our basic character movement
- 2:03:14is working great we can walk around
- 2:03:15everything looks great now in the next
- 2:03:18lecture let's apply some collisions to
- 2:03:19our player
- 2:03:22hey again here's another quick
- 2:03:23intermission I hope you've already
- 2:03:25learned a ton from the course have you
- 2:03:27seen the benefits of writing good clean
- 2:03:28code has the course already helped you
- 2:03:31understand some more advanced concepts I
- 2:03:32really hope the answer is yes to both
- 2:03:34those remember to follow the website
- 2:03:36page as you follow along I will be
- 2:03:38adding frequently asked questions to
- 2:03:39every lecture if you ever get stuck you
- 2:03:41can just download the project files for
- 2:03:43a lecture and compare with your own and
- 2:03:45definitely check out the related videos
- 2:03:47when I reference them this course is
- 2:03:49focused on making this game but you
- 2:03:50should definitely learn more about some
- 2:03:52of these Concepts in more detail and you
- 2:03:53can learn that in the videos that I
- 2:03:55mentioned by the way if you're watching
- 2:03:56this right now this is the secret call
- 2:03:59out so go ahead post a Time step in the
- 2:04:00comments with a nice monkey emoji I want
- 2:04:02to see how many people make it this far
- 2:04:05okay so that's it for now let's go to
- 2:04:06the next
- 2:04:08lecture hello and welcome I'm your Cod
- 2:04:10monkey in this lecture we're going to
- 2:04:12apply some collisions to our player
- 2:04:13movement okay so here we have our game
- 2:04:16so far we have our player walking around
- 2:04:18and everything looks pretty good however
- 2:04:20now let's create over here in in the
- 2:04:21hurac let's right click create a brand
- 2:04:23new Cube so there you go let's place it
- 2:04:26over here and push it down okay there's
- 2:04:29a cube make it just a little bit bigger
- 2:04:32so there's the cube and by default it
- 2:04:34has a box col component so it has
- 2:04:36physics and the player if I move and
- 2:04:38nope there's our issue the player is
- 2:04:40going right through the object now the
- 2:04:42player is not meant to be a ghost so
- 2:04:43let's fix this over here in our player
- 2:04:46script we are carrying the input Vector
- 2:04:49culating the move Direction and then
- 2:04:50just moving the transform so right now
- 2:04:52we're moving it no matter what now
- 2:04:54before we do that let's first do a test
- 2:04:56to see if any object is in the way and
- 2:04:58how we're going to do that is by firing
- 2:05:00a raycast this one is a physics
- 2:05:02operation that basically fires a laser
- 2:05:04from a certain point towards a certain
- 2:05:05direction and then tells you if it hits
- 2:05:07something how we do that is let's go
- 2:05:09inside the physics class and let's call
- 2:05:12the rcast
- 2:05:13function this one as you can see has
- 2:05:15many many versions of this function with
- 2:05:17all kinds of parameters let's use this
- 2:05:19one option number seven which takes a
- 2:05:21vector three for the origin a direction
- 2:05:23and a max distance so first for the
- 2:05:25origin that is from where we want to
- 2:05:27fire our recast let's put the player
- 2:05:29origin so that's transform. position
- 2:05:32then for direction this is going to be
- 2:05:34our move Direction so let's use our move
- 2:05:36there and finally for distance let's use
- 2:05:38some kind of player size player width
- 2:05:40something like that so let's define up
- 2:05:43here a float for the player size and put
- 2:05:45that 7
- 2:05:48units let's try out with a size just
- 2:05:50like this okay so basically this returns
- 2:05:52a bullion it's going to return true if
- 2:05:54it hits something and false if nothing
- 2:05:56is in the way so let's just do a bull
- 2:05:58call it can move and basically we can
- 2:06:01move if this Ray cast doesn't hit
- 2:06:02anything so we can move if this one is
- 2:06:04false so if the ray cast is false then
- 2:06:06can move is going to be true that's very
- 2:06:09simple so if we can move then we move
- 2:06:11the transform position otherwise we
- 2:06:13don't okay that's it super simple let's
- 2:06:16test so here we are I can move around
- 2:06:18and if I go towards the cube and nope no
- 2:06:20longer works so I can longer go inside
- 2:06:22that Cube okay great now in your case if
- 2:06:25it's not working first of all make sure
- 2:06:28that the cube make sure it is touching
- 2:06:29the floor we use the transform position
- 2:06:32as the origin which is right on the
- 2:06:33floor so if the box is raised up then
- 2:06:36you won't be able to go through so make
- 2:06:37sure the cube is touching the floor also
- 2:06:39make sure the cube has a box colider
- 2:06:41component it can be any type of collider
- 2:06:43but if you made a cube then it should
- 2:06:45have a box col by default and it should
- 2:06:47have the same shape as the visual and
- 2:06:49also remember that the 2D and the 3D
- 2:06:51physics systems those are completely
- 2:06:52separate they are completely different
- 2:06:54worlds so make sure you're using 3D
- 2:06:56components and not the 2D ones so for
- 2:06:58example if I add box cider 2D if I add
- 2:07:01this one then it will not work so make
- 2:07:03sure you're using the 3D and not the 2D
- 2:07:05components same thing over here on the
- 2:07:07script make sure you're using physics
- 2:07:09and not physics 2D also finally if
- 2:07:11you're still having issues make sure you
- 2:07:13check the player position again the
- 2:07:15player should be on a y of zero the only
- 2:07:17thing that might have an offset is the
- 2:07:19player visual although if you're using
- 2:07:20the same aset me then this one should
- 2:07:22also be on a y of zero so all of these
- 2:07:23on y of zero and then you can also check
- 2:07:26the floor by default this one has a mesh
- 2:07:28Lether but if it is exactly on y of zero
- 2:07:30with no rotation then it shouldn't cause
- 2:07:32any issues alternatively you can also
- 2:07:34just disable or remove the mes leather
- 2:07:36from the floor since we're not going to
- 2:07:37need that so with all of that yep
- 2:07:39everything works I can move the player
- 2:07:40but I cannot go through solid object all
- 2:07:43right awesome so it is working but for
- 2:07:46this particular use case a rast isn't
- 2:07:48necessarily the best method we should
- 2:07:49use basically a r cast is like I said
- 2:07:52kind of like a super thin laser but as
- 2:07:55you can see the player visually has an
- 2:07:56actual body shape so the visual and the
- 2:07:59logic are using completely different
- 2:08:00shapes if I go ahead and push towards
- 2:08:02the box you can see it works just fine
- 2:08:05however if the player is a bit more off
- 2:08:07to the side and the center of the player
- 2:08:09right in front of it is not the box and
- 2:08:10I move and yep there you go now I am
- 2:08:12going through the box the reason is
- 2:08:14because the ray cast being fired from
- 2:08:15the center of the player and like I said
- 2:08:17it's kind of like an infinitely thin
- 2:08:19laser so it has no shape so as long as
- 2:08:22the center of the player is not hitting
- 2:08:23the box and it can go through it whereas
- 2:08:26what we really want is for the visual
- 2:08:27and logic to have pretty much the same
- 2:08:29shape so let's not use a ray cast over
- 2:08:32here on the code instead of a ray cast
- 2:08:34we can use a physics query with an
- 2:08:36actual shape there are all kinds of
- 2:08:38casts you can use and as you can see all
- 2:08:40of them with different shapes so you've
- 2:08:41got a box cast if you want to have a box
- 2:08:43a capsule if you want a capsule or a
- 2:08:45sphere cast all of these work pretty
- 2:08:47much the exact same way except instead
- 2:08:49of a ray cast which fires an infinitely
- 2:08:51thin laser these are going to have an
- 2:08:53actual shape and for player controllers
- 2:08:55for the most part you really want to be
- 2:08:56using a capsule cast that's usually the
- 2:08:58generally accepted player shape although
- 2:09:00alternatively a box cast also can work
- 2:09:02very well in our case let's just go with
- 2:09:04a simple capsule cast this one to define
- 2:09:06a capsule has a 0.1 and a02 by the way
- 2:09:09if you have no idea what is a capsule
- 2:09:11then we can go over here in the H let's
- 2:09:12right click create a 3D object let's
- 2:09:14make it a capsule and there you go this
- 2:09:16is the capsule it's kind of like a
- 2:09:17stretch sphere so it has round the top
- 2:09:19round the bottom and then over here in
- 2:09:21the middle it's just a cylinder and over
- 2:09:23here for the rast takes a 0.1 and a 2 so
- 2:09:26that is going to be the bottom of the
- 2:09:27capsule and the top of the capsule
- 2:09:29basically with those two points we can
- 2:09:30Define the height of the actual capsule
- 2:09:33okay so let's just get rid of this
- 2:09:34capsule let's just delete it and over in
- 2:09:36the code let's put those now for point
- 2:09:39one it is indeed going to be the
- 2:09:40transform position since that is the
- 2:09:42point at the bottom and for the second
- 2:09:44point for this one it's essentially
- 2:09:46going to be the player head so we can
- 2:09:49take the transform. position so this is
- 2:09:51the bottom and we can essentially just
- 2:09:53lift it up so let's add a vector 3. up
- 2:09:56and multiply by some kind of player
- 2:09:58height so let's define up here a float
- 2:10:00for the player height and I tested it in
- 2:10:03the editor and the player is about to
- 2:10:04unit install so over here let's go ahead
- 2:10:07and move it up by that much okay so next
- 2:10:09we want the radius so this is pretty
- 2:10:12much the player size that we defined
- 2:10:13previously so let's use the same thing
- 2:10:16but as always let's make sure to write
- 2:10:17good clean code since now we are
- 2:10:19referring to a radius let's actually
- 2:10:21rename this to be a bit more clear and
- 2:10:23by the way here's a quick Visual Studio
- 2:10:25tip you can right click on a symbol and
- 2:10:28then you can click on the rename option
- 2:10:30alternatively use a shortcut controlr
- 2:10:32controlr if you do that then now you can
- 2:10:34change the name so for example player
- 2:10:35radius and note how it changes every
- 2:10:37single instance of that variable so this
- 2:10:40renaming feature is extremely useful
- 2:10:42always make sure to rename something if
- 2:10:44you find the name that works best Okay
- 2:10:46so let's rename this to player radius
- 2:10:49then we have Direction so that is as
- 2:10:50usual going to be our move Direction and
- 2:10:52then finally we have the move distance
- 2:10:55for that we can use the actual move
- 2:10:56distance so that is going to be the
- 2:10:58movement speed multiplied by time. Al
- 2:11:00the time so I just find here a float for
- 2:11:03the move
- 2:11:05distance and we just do that just move
- 2:11:07speed time. Delta time we have the move
- 2:11:10distance and we use it both in here as
- 2:11:12well as down here okay so here we have
- 2:11:15our capsel cast the rest logic is
- 2:11:17exactly the same so if this one is false
- 2:11:19that means it didn't hit anything so if
- 2:11:20it didn't had anything that we can move
- 2:11:22and then we move the transform okay
- 2:11:24let's test and over here now if I go
- 2:11:27towards the box and yep still works EXA
- 2:11:28the same as previously that's great and
- 2:11:30now if I go towards the edge and make
- 2:11:31sure that the center is not hitting the
- 2:11:33box and now I try to move forward and
- 2:11:35nope now we no longer go inside the cube
- 2:11:37so even on the edges everything still
- 2:11:39works perfectly all right awesome so it
- 2:11:42works it looks good but it also is a
- 2:11:44little bit janky for example let's
- 2:11:46stretch this cube out a little bit so
- 2:11:48let's put it just on One Direction so
- 2:11:51stret like this let's see now if I move
- 2:11:54towards it then nope I cannot go through
- 2:11:56it so that is correct and if I move left
- 2:11:58and right yep that's also correct that
- 2:11:59works however if I now press W and D at
- 2:12:02the same time in order to move
- 2:12:04diagonally and nope right now it does
- 2:12:05not move the reason is because the
- 2:12:07diagonal Vector that one is indeed
- 2:12:09hitting the collider but usually in
- 2:12:11games when you move diagonally and you
- 2:12:13cannot move in One Direction then it
- 2:12:14tries to essentially hug the wall and
- 2:12:16move around it so if I press W and D it
- 2:12:18should essentially be moving straight to
- 2:12:20the right so let's solve that so here in
- 2:12:22our code we're making our capsule cast
- 2:12:24okay that's great then we need to test
- 2:12:26if we cannot move so let's do if we
- 2:12:29cannot move so we can move is
- 2:12:33false if so then that means we cannot
- 2:12:35move towards this
- 2:12:39direction and if we can then essentially
- 2:12:41we basically want to split the movement
- 2:12:43Direction and just move on the X or just
- 2:12:45on the Zed so first let's attempt just
- 2:12:48the X movement so attempt only X
- 2:12:51movement let's create a new Vector
- 2:12:543 let's call it move the year X and we
- 2:12:57make a new Vector 3 Let's Take in the
- 2:12:59move Deer dox then zero on all the
- 2:13:02others so we only want to test moving in
- 2:13:04the X Direction and then let's do
- 2:13:06literally the same thing so let's get R
- 2:13:09can move try to move under this
- 2:13:11direction so let's go instead of move
- 2:13:12Deer move deer on the X so we do that
- 2:13:15capsule cast and if we can move then
- 2:13:18that means we can move only on the xaxis
- 2:13:22so can move all on the X and if so let's
- 2:13:26set the move there equals the move there
- 2:13:29X so if we can move then down here when
- 2:13:31we use the move there we're going to
- 2:13:32move only on the X and if we cannot move
- 2:13:36then that means we cannot move only on
- 2:13:38the X and if so then let's attempt only
- 2:13:41Zed movement so over here again let's do
- 2:13:44the exact same thing so let's copy this
- 2:13:47let's just change this one so instead of
- 2:13:48move the X we've got move the on the Zen
- 2:13:51so over here we use zero on the X zero
- 2:13:53on the Y and accessally move there and
- 2:13:55get the Zen then let's use this movement
- 2:13:57Direction over there and finally the
- 2:14:00same thing so if we can
- 2:14:02move then that means we can move only on
- 2:14:05the Zen and let's set the move there
- 2:14:07equals the move there Z and if not then
- 2:14:11we cannot move in any
- 2:14:14direction okay so that's it now this
- 2:14:16might seem a bit confusing but it
- 2:14:17becomes a lot more clear When You See It
- 2:14:19In Action again remember the scenario
- 2:14:21we're trying to solve which is when
- 2:14:22moving diagonally so for example when
- 2:14:24we're moving forwards into to the right
- 2:14:26if we do that then let's say this one is
- 2:14:28going to hit something so we cannot move
- 2:14:30so if we are trying to move both
- 2:14:31forwards and to the right then we're
- 2:14:33going to only attempt the X movement so
- 2:14:34we're only going to try moving to the
- 2:14:36right and then we're going to see yep
- 2:14:38going to the right that does work so we
- 2:14:39can move and we're going to move just to
- 2:14:41the right all right so let's test and
- 2:14:43see if all of this is working all right
- 2:14:45so here we are and if I move straight to
- 2:14:46the wall and nope there is a limit so I
- 2:14:48cannot move anymore okay great now if I
- 2:14:50move just left and just right and it
- 2:14:52does work now if I press W and then D
- 2:14:55and yep there you go now it does hug the
- 2:14:56wall and continues to move same thing if
- 2:14:59I go on the left over here if I press D
- 2:15:01no I cannot go through it now if I press
- 2:15:03D and S at the same time and there you
- 2:15:04go it hugs the wall and moves around so
- 2:15:07now our controller is much more easy
- 2:15:09much more understandable okay so this is
- 2:15:12great now this is one of those tiny
- 2:15:13things that makes your character
- 2:15:14controller feel much more responsive so
- 2:15:16that's great however we also do see one
- 2:15:19more issue right now you can see that
- 2:15:21I'm right next to the wall and if I
- 2:15:23press A and D then look at that I'm
- 2:15:24moving with this spin however now if I
- 2:15:27press W and D look at that now I'm
- 2:15:29moving diagonally and it's actually
- 2:15:30moving slower basically this is the same
- 2:15:32issue that we saw previously where we
- 2:15:34had to normalize the input so we didn't
- 2:15:36go faster in diagonals basically now we
- 2:15:38have the opposite problem since we are
- 2:15:40normalizing the vector we are cutting
- 2:15:42down on the left right vector and with
- 2:15:44that basically if we are moving
- 2:15:45diagonally then we are essentially going
- 2:15:47slower whereas if I stop moving
- 2:15:49diagonally just move left right it moves
- 2:15:51a different speed now solution for this
- 2:15:53is really super simple over here in our
- 2:15:55code when we are constructing the move
- 2:15:57Deer X and move Deer Z when we do this
- 2:15:59very simple let's just normalize it so
- 2:16:01if this one is less than one then it
- 2:16:03will be going into one so let's
- 2:16:04normalize that one and that one okay
- 2:16:06that's it let's test and if I'm here
- 2:16:08move forward and hug the wall left right
- 2:16:10yep it does work and if I stop moving
- 2:16:12diagonally and just go left right yep
- 2:16:14all still works with the exact same
- 2:16:15speed all right awesome okay so that's
- 2:16:19really it as you can see it's super
- 2:16:21simple to add Collision detection to
- 2:16:22your movement scripts you just do a
- 2:16:24physics query to test if our character
- 2:16:26should move and just move it by the way
- 2:16:28if you want to learn more about
- 2:16:29collisions and physics queries there's a
- 2:16:31bunch of interesting videos that you can
- 2:16:33watch for example one is on various
- 2:16:35methods of finding a Target then another
- 2:16:37one is on various methods of handling
- 2:16:39projectiles and finally another one is a
- 2:16:41very quick checklist on why collisions
- 2:16:43are not working basically there's lots
- 2:16:45of really interesting things you can do
- 2:16:46with physics so make sure you understand
- 2:16:48these functions okay so now that we have
- 2:16:50all of this working let's first just
- 2:16:52clean up our scene so over here our
- 2:16:54default queue we don't want this so
- 2:16:56let's just get rid of this and with this
- 2:16:58we are ready to build our first kitch
- 2:16:59encounter and let's do that in the next
- 2:17:02lecture hello and welcome I'm your Cod
- 2:17:05Mony in this lecture we're going to
- 2:17:06begin building one of our main game
- 2:17:08mechanics we're going to make a kitchen
- 2:17:10counter and handle the logic for the
- 2:17:12player to be able to interact with that
- 2:17:14counter okay so let's begin by making
- 2:17:16our kitchen counter and just like we did
- 2:17:18when we made the player let's first make
- 2:17:20an empty game object and place the
- 2:17:21visual inside of it so let's right click
- 2:17:23on the Hier key create an empty game
- 2:17:25object call this the clear counter so
- 2:17:27it's going to be clear on top so we can
- 2:17:29place and pick up objects let's make
- 2:17:31sure to reset our transform so let's put
- 2:17:33it on 0000 let's move it just a little
- 2:17:35bit just so it's not exactly on top of
- 2:17:36the player okay now inside let's add the
- 2:17:39visuals so let's go inside the assess
- 2:17:40folder and then over here we've got the
- 2:17:43pref visuals and inside we've got the
- 2:17:44counters visuals and over here let's
- 2:17:46find the clear counter visual so let's
- 2:17:48go ahead and drag it inside the game
- 2:17:50object again make sure the chall visual
- 2:17:52is on 0 0 the local position okay great
- 2:17:55now just like we did in the last lecture
- 2:17:57where we added Collision detection that
- 2:17:59shouldn't already be working by default
- 2:18:01but in order for it to work it needs a
- 2:18:02physics collider however note how the
- 2:18:05visual over here there's no collider and
- 2:18:06inside there's no collider there's only
- 2:18:08visuals again this is the same thing
- 2:18:10that relates to separating logic and
- 2:18:12visuals basically the visual prefab this
- 2:18:14one only has visual components so only
- 2:18:16meshes animations and that sort of thing
- 2:18:19and the main Parent Game object this is
- 2:18:20the one that is going to have all the
- 2:18:22lgic components so that means any kind
- 2:18:24of scripts Behavior as well as any
- 2:18:26colliders so over here on the parent
- 2:18:28game object let's add a new component
- 2:18:30let's find a box collider again make
- 2:18:32sure you add a box collider not a box
- 2:18:34cider 2D and I chose a box CID just
- 2:18:37because this is the shape that makes
- 2:18:38most sense for our counter and now let's
- 2:18:40scale the Box glider again that's the
- 2:18:42Box glider not the transform so leave
- 2:18:43that one with a scale of 111 that's good
- 2:18:46and over here on the box leather for the
- 2:18:47size let's put it up with a size that
- 2:18:50fits the visual so 1.5 1.5 1.5 and
- 2:18:54finally we just need to lift it up a bit
- 2:18:56over here on the scene view you can see
- 2:18:57those little green tiny lines these
- 2:18:59refer to the Box L shape so let's lift
- 2:19:02it up by a little bit in order to make
- 2:19:04it perfect let's put it up by 0.5 on the
- 2:19:06way all right so there you go that one
- 2:19:08does have the perfect shape if we test
- 2:19:10just like this it should already be
- 2:19:12working so okay so here's my player and
- 2:19:14if I move towards it and yep there you
- 2:19:15go it does work so it is a solid object
- 2:19:17I cannot go through it okay great let's
- 2:19:20let's just visually rotate the CER so
- 2:19:23let's do that and again for rotation
- 2:19:24let's make sure we rotate the parent
- 2:19:26game object and not the visual we want
- 2:19:28the visual to be on rotation 0 00 0 okay
- 2:19:30great so on the parent game object let's
- 2:19:32just rotate it around by the way here's
- 2:19:34a quick y tip if you want to rotate hold
- 2:19:36down control and then click to rotate
- 2:19:38and now instead of rotating on every
- 2:19:40angle it goes on a 15 angle increment so
- 2:19:43just hold down this way you can easily
- 2:19:45get it to 180° so just for fun just to
- 2:19:47make it face the player okay great so
- 2:19:49now let's interact with this counter and
- 2:19:51doing this is actually super simple we
- 2:19:54already learned how to do a rast to
- 2:19:55handle collisions and for interactions
- 2:19:57that's exactly the same thing so let's
- 2:20:00go into our player script and we're
- 2:20:02going to do a recast to handle that but
- 2:20:05before we do let's organize our code
- 2:20:07here let's make a proper function to
- 2:20:08handle our movement so let's make it
- 2:20:10private this since this is going to be a
- 2:20:12local function return void and call it
- 2:20:14handle
- 2:20:16movement and then inside let's put all
- 2:20:18of this code so let's copy all of this
- 2:20:20put it in there and then on update we
- 2:20:22simply call this function okay great and
- 2:20:25now let's make another function so
- 2:20:26private void let's call it handle
- 2:20:32interactions and we just call this
- 2:20:34function on our update okay great
- 2:20:37everything is much more organized so now
- 2:20:39here let's do a
- 2:20:40rast so once again go inside physics do
- 2:20:43a rast for the origin let's start on
- 2:20:46transform. position for this obviously
- 2:20:49we want the move Direction so one
- 2:20:51approach would be to make this a field
- 2:20:53variable sorted up here so that way we
- 2:20:54can ACC in both functions however if you
- 2:20:57remember how we handled the whole issue
- 2:20:59with the diagonals basically we're
- 2:21:00modifying the move Direction so if we're
- 2:21:03moving diagonally then this one modifies
- 2:21:04to only move left or right we don't want
- 2:21:07that for the interaction we want pretty
- 2:21:08much the exact same one even if it's
- 2:21:10pointing towards a solid object so let's
- 2:21:12not make this a member variable and
- 2:21:13reuse it instead let's just grab it
- 2:21:15again create it again over here so we
- 2:21:18get it and we want this one even if it's
- 2:21:19pointing towards a object so let's use
- 2:21:21this as our move Direction and now for
- 2:21:24the distance let's define a fixed
- 2:21:25distance so something like two units
- 2:21:28would work and also here's another very
- 2:21:30important lesson with regards to writing
- 2:21:32good clean code so you would think to
- 2:21:34write code like this so let's put the
- 2:21:35two right in here that would work
- 2:21:37everything would work perfectly but then
- 2:21:40let's say you get back to this code
- 2:21:41after one week would you remember what
- 2:21:43this 2f means the answer is probably not
- 2:21:46you would probably very easily forget
- 2:21:47exactly what this means so because of
- 2:21:49that you should never never use numbers
- 2:21:51directly in the code like this instead
- 2:21:53you can either make a field up here if
- 2:21:55you want to make it customizable or much
- 2:21:57simpler is actually what we already did
- 2:21:59previously so let's define a local
- 2:22:00variable with a proper name so let's
- 2:22:03define a float and this one is going to
- 2:22:05represent our interact distance so let's
- 2:22:07call it exactly that interact distance
- 2:22:09and let's put 2f and over here instead
- 2:22:12of using a number let's just use that
- 2:22:14variable now if we were to get back to
- 2:22:16this code after a long time it would be
- 2:22:18extremely clear what this parameter
- 2:22:19represents
- 2:22:21the technical term for what we did here
- 2:22:23is called Magic numbers and I've also
- 2:22:24covered them in detail in another quick
- 2:22:26video but as a rule always remember very
- 2:22:28simply never use magic numbers okay so
- 2:22:31with this we have our recast it's
- 2:22:33pointing forwards for this distance but
- 2:22:35this is actually not very useful because
- 2:22:37the rast this one only returns a bullion
- 2:22:40so all this tells us is if there's
- 2:22:42something in front or not it does not
- 2:22:44actually get us the actual object
- 2:22:46reference so for that let's use a
- 2:22:48different version of the raycast
- 2:22:49function so as you can see we've got all
- 2:22:51kinds of versions in order to get the
- 2:22:53object reference let's use this version
- 2:22:55right here this one which has an out
- 2:22:57parameter for a rast head note the out
- 2:23:00keyword here this is important this
- 2:23:02means that this is an output parameter
- 2:23:04whereas the other parameters those are
- 2:23:06all essentially inputs that you give to
- 2:23:07the function whereas this output this is
- 2:23:09basically a value that the function
- 2:23:11outputs so let's use this so we've got
- 2:23:13the origin we've got the direction then
- 2:23:15we've got the ray asset in order to use
- 2:23:17it we need to make sure to write the out
- 2:23:18keyword here and then also very
- 2:23:20important we need to write the type so
- 2:23:22let's call it breakast hit and then the
- 2:23:25name so let's call it breakast hit
- 2:23:28basically what we're doing here is
- 2:23:29essentially defining a variable of this
- 2:23:31type with this name we're defining it
- 2:23:33and giving it to the function
- 2:23:34immediately so we can use it afterwards
- 2:23:36if you don't include the type if you
- 2:23:37just include the name then you get an
- 2:23:39error because this name rake asset this
- 2:23:41was never defined alternatively you can
- 2:23:43Define it before you pass it in over
- 2:23:44here you can do rast it rast it and just
- 2:23:48like this it works because you are
- 2:23:49defining it here and using here but in
- 2:23:51order to make the code a bit more
- 2:23:52compact you can just Define it here in
- 2:23:54the same place where you get it okay so
- 2:23:56let's use this and with this the
- 2:23:58function s return is just a bulling so
- 2:23:59just hit something or not but then we've
- 2:24:02got the rasset output this won't be
- 2:24:04filmed with data from the Collision if
- 2:24:06we do hit something we can inspect this
- 2:24:08to see what that it contains so you can
- 2:24:10right click on top of the type and then
- 2:24:12go to definition and up here we do see
- 2:24:15the definition for the rastet struct you
- 2:24:17can see this is a structure to get
- 2:24:18information back from a rast
- 2:24:20you can inspect this to see all of the
- 2:24:22kinds of things that this one returns
- 2:24:24for example you have a vector 3 point
- 2:24:26for the impact point in World space
- 2:24:27where the ray actually had a collider
- 2:24:29you can get the normal of the surface
- 2:24:31and so on so you can get all kinds of
- 2:24:33things for our use case what we want is
- 2:24:35to identify the object that we hit and
- 2:24:37for that we can use the transform so
- 2:24:38this going to be the transform of the
- 2:24:40rigid body or the collider that was hit
- 2:24:42so let's just do a quick test if we hit
- 2:24:44something let's do a log on that object
- 2:24:46so let's do an if so if this one is true
- 2:24:48then that means we hit something so if
- 2:24:50so let's do a debug. log go inside the
- 2:24:52rast hit and log the transform okay so
- 2:24:55like this we should be able to see on
- 2:24:56the console if we do hit something let's
- 2:24:58also do an else just to be able to
- 2:25:00easily see when we hit something so on
- 2:25:03else let's just log an empty Dash and in
- 2:25:06our game in order to make sure that our
- 2:25:07Collision is working that we are
- 2:25:08correctly detecting it let's just
- 2:25:10duplicate this object but before we do
- 2:25:12let's make this a proper prefab if you
- 2:25:14have an object of a certain type that
- 2:25:15you want to create multiple instances of
- 2:25:17it you should be using a prefab rather
- 2:25:19than just duplic an object that way with
- 2:25:21the prefab if you make any changes to
- 2:25:22that prefab it applies to all of the
- 2:25:24copies of that prefab so let's first
- 2:25:27make this one a prefab and again since
- 2:25:29this is our first prefab let's first
- 2:25:30make a nice folder to keep things
- 2:25:32organized so folder for our prefabs and
- 2:25:35to make game object prefab is super
- 2:25:36simple you just click and drag directly
- 2:25:38from the hierar key and drop it inside
- 2:25:40the folder there you go there's our
- 2:25:41prefab and now let's just duplicate this
- 2:25:44make sure it has a different name so it
- 2:25:45has one so that's enough with this we
- 2:25:47should be able to see it just for
- 2:25:48testing let's put it just off this side
- 2:25:50okay so let's see so here we are and on
- 2:25:52the console we see a dash so by default
- 2:25:54we are not hitting anything okay so that
- 2:25:55makes sense now if I move towards this
- 2:25:57object and if there you go it does
- 2:25:59identify that object and if I stop
- 2:26:01moving it stops identifying okay great
- 2:26:03now if I move towards this one and if
- 2:26:05there you go this is the one with the
- 2:26:06name of one and this is one with the
- 2:26:07name of none all right awesome so just
- 2:26:10like this we are correctly identifying
- 2:26:11what object is in front except we also
- 2:26:14have an issue so if I move towards the
- 2:26:16object then yep it does work but if I
- 2:26:18stop moving whilst I'm still facing that
- 2:26:20object right now it's returning none now
- 2:26:22the reason for that is because of the
- 2:26:23move dat that we're using here if we're
- 2:26:25not moving in any direction then
- 2:26:27basically this Vector will be 0000 Z so
- 2:26:29we're going to be firing a ray cast
- 2:26:31towards no direction at all so obviously
- 2:26:32it's not going to hit anything the
- 2:26:34solution to that is super simple we just
- 2:26:36need to keep track of the last interact
- 2:26:38move Direction so let's go up here
- 2:26:40Define a field for that so let's make a
- 2:26:42private let's make a vector 3 and call
- 2:26:44it the last interact Direction and then
- 2:26:47down here when we have our handle
- 2:26:49interaction so we get the movement here
- 2:26:50okay that's great so then we just check
- 2:26:52if the move direction is different from
- 2:26:55Vector 3.0 by the way this is a constant
- 2:26:58a short hand for 0 0 so if it is not
- 2:27:00zero then that means we are moving in
- 2:27:02some
- 2:27:04Direction so if so let's set the less
- 2:27:07inter direction to this move Direction
- 2:27:09and basically if it is not if move Deer
- 2:27:10is zero then we are not going to modify
- 2:27:12this so this one is only going to
- 2:27:13contain the unless inter Direction then
- 2:27:16down here instead of using the move
- 2:27:17Direction Let's just use this one so
- 2:27:19that way even when we stop moving we are
- 2:27:21still going to be using the L inter
- 2:27:22Direction okay so with this let's test
- 2:27:25so here we are and if I move towards it
- 2:27:27yep it works and if I stop moving and
- 2:27:29yep it still works all right great so we
- 2:27:31can move towards it Point towards a
- 2:27:32certain object and then yep it still
- 2:27:34works okay great now let's actually
- 2:27:37interact with this counter and to do
- 2:27:39that let's make a class for the counters
- 2:27:41itself so let's make a new script in new
- 2:27:43C script let's call it the same name so
- 2:27:45clear
- 2:27:48counter okay there's our script
- 2:27:51now very importantly for attaching the
- 2:27:53script remember that we have two
- 2:27:55instances of our prefab if you just
- 2:27:58select it in the Hier key and you just
- 2:27:59drag it on there if you do that then
- 2:28:01you're not actually adding this script
- 2:28:03to the prefab itself you're only adding
- 2:28:05it to this specific instance of that
- 2:28:07prefab so if you look at this one yep it
- 2:28:09has a script but this other one which is
- 2:28:11a copy of the same prefab this one does
- 2:28:12not have it also over here on the
- 2:28:14inspector you can see the little script
- 2:28:16icon has a nice little plus that means
- 2:28:18it is something that you are adding on
- 2:28:19top top of the prefab so that means this
- 2:28:21script is not present on the base prefab
- 2:28:24basically this is not what we want we
- 2:28:26don't want just this object to have this
- 2:28:28script we want all instances of this
- 2:28:30prefab to have this script so instead
- 2:28:32let's get rid of this one from here we
- 2:28:34want to modify the prefab itself so one
- 2:28:37way to do that is to select the prefab
- 2:28:39on the project window so here it is the
- 2:28:40ason prefab and now we can drag the
- 2:28:42script on there so that works or another
- 2:28:45alternative is select the prefab in the
- 2:28:47Hier key and on the inspector over here
- 2:28:49we see a nice button to open the prefab
- 2:28:51and if we actually go into scene view
- 2:28:53then we can see what that does so with
- 2:28:55the object selected so this is an
- 2:28:56instance of that prefab but if we click
- 2:28:58on open then essentially we are opening
- 2:29:00and we are working inside the prefab so
- 2:29:02now if we make sure to add our script
- 2:29:05and let's go back outside this prefab so
- 2:29:07on the top left corner over here we can
- 2:29:08see where we are so we were inside our
- 2:29:10scene and then we are inside the clear
- 2:29:12counter prefab so if we click on the
- 2:29:14scenes we can go back now it tells us
- 2:29:16that we made some changes through the
- 2:29:17prefab so let's save them and yep we
- 2:29:19added that script and we can see both
- 2:29:21instances of the prefab they both have
- 2:29:22the same script and we can see on there
- 2:29:24on the icon that this is not an override
- 2:29:26this is an actual script at on the base
- 2:29:28prefab so whenever working with prefabs
- 2:29:30always make very sure that you are
- 2:29:32adding it on the right place if you want
- 2:29:34something on the bass prefab make sure
- 2:29:36you either add it on the prefab itself
- 2:29:38or go inside the prefab by double
- 2:29:39clicking on it or select an instance in
- 2:29:41there and open to go inside the prefab
- 2:29:43so always keep in mind differences
- 2:29:45between a prefab and an instance of a
- 2:29:47prefab okay so we have our script let's
- 2:29:49open it and over here let's just make
- 2:29:51one super simple function so let's make
- 2:29:54it public because we want to call this
- 2:29:55from our player class let's return void
- 2:29:57and just call it
- 2:30:00interact okay that's it super simple for
- 2:30:02now let's just do a debug.log and just
- 2:30:04say interact okay so that's it and now
- 2:30:08over here on the player when we have our
- 2:30:09handle interactions function so we
- 2:30:11interact we do our recast and we find
- 2:30:13out if we hit something so when we do
- 2:30:15the first thing that we should do is
- 2:30:17identify what this transform is so is
- 2:30:19this something just like a dumb Cube or
- 2:30:21is it an actual counter now when it
- 2:30:23comes to identifying things this is
- 2:30:25another place where a lot of beginner
- 2:30:27tutorials would teach you to use the
- 2:30:28unity tag system so that's over here in
- 2:30:31the editor when you select any object
- 2:30:33over here in the inspector you can see a
- 2:30:34tag so you can see untagged and you can
- 2:30:36add all kinds of tags this is something
- 2:30:38that a lot of beginning tutorials teach
- 2:30:40but Unity tags are horrible you should
- 2:30:42never never use them I covered in more
- 2:30:44detail why that is in the advanced
- 2:30:46concepts video the main reason is
- 2:30:48because of well pretty much the same
- 2:30:50thing that I mentioned a while ago when
- 2:30:51we were handling animator parameters so
- 2:30:53we were doing this and I talked about
- 2:30:55how this one takes a string and how
- 2:30:56strings are horrible way for identifying
- 2:30:58objects they are very brittle very
- 2:31:00errone it's very easy to make mistakes
- 2:31:03and tags have the exact same problems
- 2:31:04because tags are strings so we do not
- 2:31:07want to use tags to identify objects
- 2:31:09instead over here on the player script
- 2:31:11let's use a different method for
- 2:31:12identifying objects and the best way to
- 2:31:14do that is to Simply get our counter
- 2:31:16component so we have our transform and
- 2:31:19then from ins inside that transform we
- 2:31:20can call the function try get component
- 2:31:23this one then takes the type of
- 2:31:24component and again note how this is an
- 2:31:27out parameter so let's put out and we
- 2:31:29want to test if this is of type clear
- 2:31:31counter so clear counter and call it
- 2:31:33clear counter and this one basically
- 2:31:35does the same thing as a rast so it
- 2:31:37returns a bullan so either true or false
- 2:31:40so if this one is true then that means
- 2:31:42that object has that component so over
- 2:31:44here we know has clear
- 2:31:46counter by the way if you're not
- 2:31:48familiar with tri get component this is
- 2:31:50pretty much the same thing as the
- 2:31:51regular get component except it
- 2:31:53automatically handles the null check for
- 2:31:55you so if we just do this it's exactly
- 2:31:57the same thing as this so you do an if
- 2:32:00rast hit let's access the transform get
- 2:32:05component component of type clear
- 2:32:10counter naturally this one is not inside
- 2:32:12ni but let's store this clear counter
- 2:32:15equals this then you do if this one is
- 2:32:17not null then we know has a clear
- 2:32:21counter so basically what we have up
- 2:32:23here is the exact same thing that we
- 2:32:24have down here so just using triy get
- 2:32:26component just a bit more Compact and I
- 2:32:28find much easier to read than to always
- 2:32:30get the component and test if it is not
- 2:32:32known over here we just have one
- 2:32:33function with a nice out parameter and
- 2:32:35everything works perfectly so that's the
- 2:32:37traget component I much prefer that
- 2:32:38method so let's use that by the way on
- 2:32:40the traget component over here you can
- 2:32:42see it has a type inside some angled
- 2:32:44brackets basically these are called C
- 2:32:46generics these are an extremely powerful
- 2:32:49C tool
- 2:32:50I have a dedicated video on them and
- 2:32:52I've used them in tons of videos
- 2:32:53definitely go ahead and learn about them
- 2:32:55basically this lets you write code that
- 2:32:57works with many classes not just one
- 2:32:59specific type in this case the triy get
- 2:33:01component can work with any type of
- 2:33:03component so it can be Unity built-in
- 2:33:05component or it can be components that
- 2:33:06you made yourself then if it finds a
- 2:33:08type it returns through so for right now
- 2:33:11it's not strictly necessary to know the
- 2:33:13specifics about how C generics work but
- 2:33:15definitely make sure you add that video
- 2:33:17to your queue and watch it afterwards C
- 2:33:19generic are an extremely useful C
- 2:33:21feature okay so we do this and basically
- 2:33:23if we are inside of here then we know
- 2:33:25this object has a clear counter and we
- 2:33:26have our clear counter reference so over
- 2:33:28here it's super simple let's just call
- 2:33:30the interact function all right so
- 2:33:32that's really it let's just get rid of
- 2:33:34the else we no longer want that log so
- 2:33:35we should be able to see a log whenever
- 2:33:37we call our interact in a counter all
- 2:33:39right so here we are and if I move
- 2:33:41around okay that's good over here the
- 2:33:42console is empty all right now if I move
- 2:33:44towards the counter yep there you go I'm
- 2:33:46interacting with it and if I move
- 2:33:47towards this one yep there you go
- 2:33:48interacting all right right great so
- 2:33:50with this we are correctly identifying
- 2:33:52the object and interacting with it now
- 2:33:54let's just do one final thing over here
- 2:33:56we are doing a rast to find the counter
- 2:33:59and right now we are doing a ray cast
- 2:34:01towards any object that has any kind of
- 2:34:03physics C so maybe that's our counter or
- 2:34:06maybe just a random wall for example if
- 2:34:08we had an invisible wall in front of our
- 2:34:10counter then this code would not work
- 2:34:13that's because this Ray cast and this
- 2:34:14Ray cast hit it only Returns the very
- 2:34:17first object that it does hit so if the
- 2:34:19counter was behind the wall then the rec
- 2:34:20asset object here would be a reference
- 2:34:22to that wall object perhaps that's what
- 2:34:24you want or perhaps not in that scenario
- 2:34:27one thing you can do is instead of using
- 2:34:28raycast you can use the function raycast
- 2:34:31all and difference for this one is
- 2:34:33instead of returning just a bullan just
- 2:34:35true or false instead it returns an
- 2:34:36array of all the objects that it hit
- 2:34:38with that Ray cast then you could cycle
- 2:34:40through them and identify the objects so
- 2:34:43that's one approach or another option is
- 2:34:45over here on the recast if we look at
- 2:34:48these function versions we can see that
- 2:34:50some of them has what it's called a
- 2:34:52layer mask basically you can set a
- 2:34:54certain game object to a specific layer
- 2:34:57and then if you using a layer mask then
- 2:34:58you can make sure this rast will only
- 2:35:00hit objects within that layer anything
- 2:35:02not on that layer will be ignored for
- 2:35:04that rcast this is super useful so let's
- 2:35:06learn how it works for a layer mask we
- 2:35:09can go up here and Define a type of
- 2:35:11layer mask so let's make another
- 2:35:12serialized field private let's make it
- 2:35:15of type layer mask let's call it the
- 2:35:17counters layer mask
- 2:35:20okay so we have this and then down here
- 2:35:22when we have our recast let's use it so
- 2:35:25let's find the function that matches up
- 2:35:27these parameters with the layer mask so
- 2:35:29here it is we have the origin then we
- 2:35:31have Direction The Rake has hit the max
- 2:35:33distance and then finally we have our
- 2:35:35layer mask so let's use our counters
- 2:35:36layer mask okay great now back in the
- 2:35:39editor let's select our player game
- 2:35:41object and yep there we see our field of
- 2:35:43type layer mask and you can see how we
- 2:35:45can select all kinds of layers and how
- 2:35:47we set these layers to an object is
- 2:35:49let's just select our clear counter
- 2:35:52although again we want to make sure that
- 2:35:53this change applies to all counters not
- 2:35:56just this one specific instance so let's
- 2:35:57go inside the prefab and over here we've
- 2:35:59got a field for our layer and you can
- 2:36:01see we've got a bunch of default layers
- 2:36:03and then we can add some more so let's
- 2:36:05add some layers and over here let's go
- 2:36:06to the first empty one and let's call it
- 2:36:08counters okay we've added the layer so
- 2:36:11let's go back select our object and now
- 2:36:13on the layer let's put it on the
- 2:36:14counters now it asks you if you want to
- 2:36:16modify the layer for all child objects
- 2:36:19now since we made sure to keep the logic
- 2:36:20and physics components only on the
- 2:36:22parent object let's just modify this one
- 2:36:24and leave the other ones on the default
- 2:36:26so let's just modify this object only
- 2:36:28okay so with that our counter is now on
- 2:36:30the counters layer let's leave the
- 2:36:32prefab make sure to save it okay great
- 2:36:34and now if we go back into the player
- 2:36:35and over here on the counters layer mask
- 2:36:37yep we do see the counters layer so
- 2:36:39let's just click to selected by the way
- 2:36:41this drop down menu you can actually
- 2:36:42select multiple so you can select all
- 2:36:44kinds of layers so this is multi select
- 2:36:46but we only want to counter so only like
- 2:36:48this and just like this if we do test
- 2:36:51and now if I move towards it and if
- 2:36:52there you go got the nice interact on
- 2:36:54both them so everything still works
- 2:36:55exactly the same but now if we had
- 2:36:57another physics Le in front of it it
- 2:36:59would still work because we're using a
- 2:37:01layer mask to only recast against
- 2:37:02counter objects all right great now I
- 2:37:05should point out another way to work
- 2:37:07with layers is with something called a
- 2:37:08bit mask that's a bit more advanced
- 2:37:10usually the layer mask is much easier to
- 2:37:12follow but if you want to learn about
- 2:37:14bit mask go ahead and watch that video
- 2:37:16and also another quick note in this game
- 2:37:18we're only going to interact with one
- 2:37:19single object type it's only going to be
- 2:37:21a counter even though we're going to
- 2:37:23have multiple types of counters but for
- 2:37:25games where you want to interact with
- 2:37:27multiple objects like for example having
- 2:37:29an interact action to talk with an NPC
- 2:37:31and another one to open a door or push a
- 2:37:33button for those kinds of multiple
- 2:37:35interactions to build a system like that
- 2:37:36make sure you'll look into my how to
- 2:37:38interact with objects video it covers
- 2:37:40how to do all of that how to interact
- 2:37:42with all kinds of objects it's all based
- 2:37:44on C interface which we're actually
- 2:37:45going to use in a few lectures and also
- 2:37:47have a dedicated video on that topic so
- 2:37:49keep following this course but then make
- 2:37:51sure to watch those videos add them to
- 2:37:53your watch list and make sure you do
- 2:37:54watch them watch that how to interact
- 2:37:56video it is something that is necessary
- 2:37:58in so many games and most tutorials
- 2:38:00don't actually teach you the correct way
- 2:38:01of doing it anyway so back in our game
- 2:38:03we are correctly identifying an
- 2:38:05interacting with each counter but
- 2:38:07obviously we don't want to interact
- 2:38:09automatically just like this instead we
- 2:38:10want to press a nice button to interact
- 2:38:12so that means we're going to need to
- 2:38:14create an interact input action so let's
- 2:38:16do all of that in the next lecture
- 2:38:19hello and welcome I'm your codemy in
- 2:38:21this lecture we're going to create a
- 2:38:23proper interact input action and in
- 2:38:25doing so we're also going to learn about
- 2:38:27a very powerful C feature called events
- 2:38:30okay so here we have our game so we have
- 2:38:32the player and if we move towards the
- 2:38:34counter yep we are correctly identifying
- 2:38:36it and interacting with it except of
- 2:38:38course we don't want the interaction to
- 2:38:39happen automatically it should be on a
- 2:38:41player input so let's make our interact
- 2:38:43action let's go inside our player input
- 2:38:46action so let's double click on it and
- 2:38:48let's make a brand new action so we've
- 2:38:49got the move and now we're going to have
- 2:38:50another one so let's click on the plus
- 2:38:52icon for this one let's call it interact
- 2:38:55and for this one action type we do want
- 2:38:56it to be a button okay great then on the
- 2:38:59default binding let's go into path let's
- 2:39:01listen and by default let's bind it to
- 2:39:03the E key just like so many games so
- 2:39:05let's go ahead select this one and once
- 2:39:07again let's make sure to save the asset
- 2:39:09and let the C Class be generated okay
- 2:39:12now over here in our game input script
- 2:39:14in order to listen that is very simple
- 2:39:16so we go inside the player input actions
- 2:39:18then inside the player action map and
- 2:39:21then we can find the interact action and
- 2:39:23then over here we can see a whole bunch
- 2:39:25of events that we can interact with
- 2:39:27we've got these three cancel performed
- 2:39:30and started these are the three phases
- 2:39:32of every input again I cover these
- 2:39:34stages in detail in the input system
- 2:39:36video the important thing is that these
- 2:39:38are C events which I also covered in
- 2:39:41another dedicated video essentially they
- 2:39:43are a way for how you can write code to
- 2:39:45then get notified when something happens
- 2:39:47rather than running code on every signal
- 2:39:49update constantly testing something for
- 2:39:51example over here on the movement
- 2:39:53movement is a Prett constant action so
- 2:39:55it does make sense to ask the input on
- 2:39:57every single update if any movement is
- 2:39:59pressed but for an action like the
- 2:40:01interact the player is only going to
- 2:40:03press that say once every 5 seconds so
- 2:40:05it makes no sense to constantly check
- 2:40:07for that action on every single update
- 2:40:10instead we just want to be notified when
- 2:40:12that action is triggered and that is
- 2:40:14exactly what an event does again watch
- 2:40:16the dedicated video to learn all about C
- 2:40:18events in detail they are insanely
- 2:40:20powerful and we will be using them more
- 2:40:21and more as we go through this course
- 2:40:23for now here are the absolute Basics
- 2:40:26events have Publishers and subscribers
- 2:40:28the publisher creates and fires the
- 2:40:30event when something happens and the
- 2:40:32subscriber un listens that event and
- 2:40:34gets the UN listening function called
- 2:40:35when the event is fired now on the
- 2:40:37generated C Class we've got these three
- 2:40:39events the one that we want for this
- 2:40:42case is the performed event so let's go
- 2:40:44into this one and basically we want to
- 2:40:46add a listener to that event and we can
- 2:40:48subscribe to that by doing plus equals
- 2:40:50so this assigns a listener to that event
- 2:40:53and now Visual Studio has a nice
- 2:40:54shortcut so if you press on Tab yep
- 2:40:56there you go it automatically creates
- 2:40:57the function now if you're not using
- 2:40:59visual studio you can just manually
- 2:41:01write this function the only thing you
- 2:41:02need to make sure is that the function
- 2:41:04signature perfectly matches the event
- 2:41:05signature as usual we can inspect event
- 2:41:08so we can right click on it and go to
- 2:41:09definition and up here is the definition
- 2:41:12and you can see that this is an event of
- 2:41:14type action with a comback context
- 2:41:17action is what is called a delegate I
- 2:41:19also have a video on delegates if you
- 2:41:20want to learn more about them in detail
- 2:41:22for now we don't really need to worry
- 2:41:24about what is delegate we just need to
- 2:41:25use it so in order to subscribe to the
- 2:41:27event we need to make sure that this one
- 2:41:29returns void because an action returns
- 2:41:31void and needs to have a parameter of
- 2:41:33this type comback context if I erase
- 2:41:36this parameter y there you go now we
- 2:41:38have an error because the function
- 2:41:39signature does not match so it always
- 2:41:41needs to match exact same signature okay
- 2:41:44and also one more note over here when
- 2:41:45subscribing to the event make sure you
- 2:41:47only add the function name meaning you
- 2:41:49do not add parenthesis we do not want to
- 2:41:51call the function we just want to pass
- 2:41:52in the function itself as a reference
- 2:41:55okay so now when the player presses the
- 2:41:56interact action it's going to fire off
- 2:41:58this event which in turn we'll call this
- 2:42:00function so over here let's do a debug.
- 2:42:02log just to see what this contains for
- 2:42:04example let's print out the comback
- 2:42:06context okay so let's see so here we are
- 2:42:09and if I press on E yep there you go
- 2:42:10I've got a nice event okay great so with
- 2:42:13this we know when the player presses the
- 2:42:14key now the next step is how do we get
- 2:42:16the player class how do we get this one
- 2:42:18to know when this is performed and the
- 2:42:20answer is we're going to do the exact
- 2:42:22same thing we're going to make an event
- 2:42:24over here on the game input class and
- 2:42:25the player won't listen to that which in
- 2:42:27turn the game input grabs from the input
- 2:42:29system again the whole point is
- 2:42:31separating our concerns so the player
- 2:42:33does not care about the input system
- 2:42:35does not care about the interact action
- 2:42:36it only wants to know when something
- 2:42:38related to interact happens so over here
- 2:42:40let's make that nice event first of all
- 2:42:42let's make it public because we want the
- 2:42:44player to access it then we need to add
- 2:42:46the vent key next we add the D type like
- 2:42:50I said you can learn more about
- 2:42:51delegates in my dedicated video you can
- 2:42:53create your own custom Delegate for your
- 2:42:55event or you can just follow the C
- 2:42:57standard and just use the standard event
- 2:43:00handler and this one exists inside
- 2:43:02system so let's make sure to go up here
- 2:43:05and add using system and this one has
- 2:43:07the event handler class this one is
- 2:43:09pretty much the C standard for events as
- 2:43:12you can see it returns void it has an
- 2:43:14object for the sender and an event ARX
- 2:43:16parameter like I mentioned in the events
- 2:43:18video you are not forced to use this
- 2:43:20delegate you can use whatever delegate
- 2:43:21you want like for example you saw that
- 2:43:23the performed used an action delegate so
- 2:43:26you can use anything you want it's just
- 2:43:27that the event handler is the C standard
- 2:43:29so it's easier to follow unless you have
- 2:43:32a specific reason to deviate from the
- 2:43:33standard you should probably use this
- 2:43:35one so let's use this and then finally
- 2:43:37for the name usually you start the name
- 2:43:39with on and then whatever happened so in
- 2:43:41our case let's go with on interact
- 2:43:45action okay so we have defined our vent
- 2:43:47and now for firing it
- 2:43:49let's go down here into when we have the
- 2:43:51interact performed and let's go into the
- 2:43:53event and for finding it is pretty much
- 2:43:55exactly the same thing as calling a
- 2:43:56regular function so we just call it with
- 2:43:58parenthesis then usually for the object
- 2:44:00sender this is a reference to whoever is
- 2:44:02sending this event so usually the this
- 2:44:04keyword and then for the event ARS this
- 2:44:06is in case you want to send some
- 2:44:08arguments with the event in our case we
- 2:44:10don't really need to send any extra data
- 2:44:11for this one just firing the event is
- 2:44:13going to be enough so for that we can
- 2:44:15use the Conant event rx. mty okay so
- 2:44:18that's it with this we are firing an
- 2:44:20event except just like this we're
- 2:44:21actually going to have one potential
- 2:44:23error if we have no subscribers no
- 2:44:26listeners to this event then essentially
- 2:44:28this field won be null so this one over
- 2:44:30here is going to trigger a null
- 2:44:31reference exception let's do a quick
- 2:44:33test just to see this happening so here
- 2:44:35if I press on E yep there you go we have
- 2:44:37a no reference exception so when working
- 2:44:39with events you need to first test if
- 2:44:41there are any listeners and only then do
- 2:44:43you actually trigger the event so you do
- 2:44:46if this one is not known if it is not
- 2:44:48known that means that there are some
- 2:44:49subscribers so we can fire the event so
- 2:44:52like this it will work but there's an
- 2:44:53even more compact way to do this which
- 2:44:55is perfect for events so instead of this
- 2:44:59we've got our uninter action then we can
- 2:45:01add a question mark this is called the
- 2:45:03non-conditional operator basically the
- 2:45:06code is going to execute from left to
- 2:45:08right and then when it gets to this
- 2:45:10question mark it's going to evaluate the
- 2:45:12left side and if it is null then the
- 2:45:14execution W stop right here on the
- 2:45:16question mark and will not throw any
- 2:45:18errors whereas if this one is not null
- 2:45:20then it continues executing to the right
- 2:45:22except with this syntax we have an error
- 2:45:24We cannot put parentheses directly after
- 2:45:26the question mark but what we can do is
- 2:45:29simply just call invoke and that does
- 2:45:31the exact same thing that calls a
- 2:45:32function so what we have here is exactly
- 2:45:35the same thing that we had
- 2:45:44previously so what we have over here and
- 2:45:46over here these are the exact same thing
- 2:45:49it just this one is much nice much more
- 2:45:51Compact and especially for events this
- 2:45:53one is super useful okay so with this we
- 2:45:55are correctly firing for our event now
- 2:45:57let's actually listen to it so let's go
- 2:46:00over here into the player class and
- 2:46:02let's listen to our event let's do it on
- 2:46:05a private void start make it on start
- 2:46:07and not on awake this is a very
- 2:46:08important rule which I'm actually going
- 2:46:10to cover in detail in the next lecture
- 2:46:12but for now just make sure to listen on
- 2:46:13start and not on awake so over here we
- 2:46:15access the game input then let's access
- 2:46:18the on interact action event and as
- 2:46:20usual let's listen to it so let's use
- 2:46:22press tab to listen to it so it is
- 2:46:24exactly over here that we want to run
- 2:46:25our interact code so let's go down into
- 2:46:28the handle interaction code that we had
- 2:46:29previously so this one so let's copy
- 2:46:32paste all this code put it up here so we
- 2:46:36get the interaction go to the object and
- 2:46:37Trigger the interact now obviously code
- 2:46:39duplication is a big no no so we're only
- 2:46:42duplicating our code just for a quick
- 2:46:44test just to make sure it works once
- 2:46:46again refactoring is super useful so
- 2:46:48we're going to refactor this code to get
- 2:46:49rid of code duplication in the next
- 2:46:51lecture but for now we just want to test
- 2:46:53to make sure that this does work so
- 2:46:55let's just remove the interact over here
- 2:46:56from the handle interactions so the only
- 2:46:58interact function being called is over
- 2:47:00here when we have our actual input so
- 2:47:03let's test and see if we can press to
- 2:47:04interact with the counter all right so
- 2:47:06here we are and as I move around if I
- 2:47:08approach the counter yep there you go we
- 2:47:09no longer have the automated interaction
- 2:47:12and now if I'm facing the counter and I
- 2:47:14press the interact key yep there you go
- 2:47:15here we have our nice interaction all
- 2:47:17right awesome so I can approach I can
- 2:47:19interact and do whatever I want all
- 2:47:22right so here we learned about C events
- 2:47:24these are super powerful so if this is
- 2:47:26the first time you're hearing about them
- 2:47:28then you've just added an awesome new
- 2:47:30tool to your toolbox definitely make
- 2:47:31sure you watch my dedicated video to
- 2:47:33learn about them in more detail events
- 2:47:35are super useful the next thing we're
- 2:47:37going to need is just a visual to
- 2:47:38highlight the current selected counter
- 2:47:40so let's do that in the next lecture
- 2:47:43hello and welcome I'm your code monkey
- 2:47:45in this lecture we're going to add a
- 2:47:46visual to our selected counter and in
- 2:47:48doing so we're also going to learn about
- 2:47:50the very useful Singleton pattern okay
- 2:47:52so over here we already have the logic
- 2:47:54to identify the counter in front of the
- 2:47:56player and we can interact with it
- 2:47:58however once the logic works there is no
- 2:48:00visual indicator at all so let's add
- 2:48:02that now as usual the super quick and
- 2:48:04dirty way of doing it would be pretty
- 2:48:06simple over here on the player script we
- 2:48:08could just directly enable a visual mesh
- 2:48:10on the target counter so down here on
- 2:48:12the handle interaction when we have this
- 2:48:14over here we can tell the clear counter
- 2:48:16to enable some kind of visual
- 2:48:18technically the would work but that
- 2:48:19would be some pretty dirty code we would
- 2:48:22basically be making the player
- 2:48:23responsible for enabling some kind of
- 2:48:25visual which would mean that we were
- 2:48:27mixing logic with visuals again we
- 2:48:29always want to try separating the logic
- 2:48:31from the visuals as much as possible to
- 2:48:33keep our code nice and organized so
- 2:48:35instead of doing the quick andary route
- 2:48:37let's do it properly back in the editor
- 2:48:39let's create a brand new C script call
- 2:48:42this the selected counter Visual and now
- 2:48:45let's go into the prefab again let's go
- 2:48:48inside it so let's select the clear
- 2:48:49counter on the hierarchy then on the
- 2:48:51inspector let's open up go inside the
- 2:48:53prefab and now let's select the visual
- 2:48:55inside it and let's duplicate this so
- 2:48:56you can press contrl D to duplicate it
- 2:48:59let's name this one selected and then
- 2:49:01inside there's a visual with a mesh
- 2:49:03filter and a mesh render so over here
- 2:49:05let's swap out the material so let's
- 2:49:08click on the circle icon and now
- 2:49:10included in the assets is this material
- 2:49:12counter selected so it's all the way yep
- 2:49:15up here the counter selected basically
- 2:49:17it's just a solid white colar with a low
- 2:49:19Alpha so on the kitchen counter inside
- 2:49:22the select game object let's make sure
- 2:49:23to use this one with this we have kind
- 2:49:25of like a ghost visual so if we enable
- 2:49:28in dis this game object we can see the
- 2:49:29difference Also let's do one tiny thing
- 2:49:32which is right now we duplicated the
- 2:49:34actual visual meaning that these objects
- 2:49:36are exactly the same they have the exact
- 2:49:38same size and when that happens you
- 2:49:40might end up with some rendering bugs if
- 2:49:42two meshes are on the exact same
- 2:49:44position you might sometimes see the
- 2:49:45colar constantly flip back and forth so
- 2:49:48in order to make sure that doesn't
- 2:49:49happen let's make this one the selected
- 2:49:51a tiny tiny bit bigger so over here with
- 2:49:54the select game object selected on the
- 2:49:56inspector over here we've got the scale
- 2:49:58and also we've got this nice little
- 2:49:59button here if it's like this then we
- 2:50:01can modify each proportion differently
- 2:50:03from one another whereas if we click now
- 2:50:06these are all linked so now modifying
- 2:50:08one will modify all of them so let's put
- 2:50:10this on
- 2:50:111.01 meaning this one is going to be
- 2:50:14literally just 1% bigger so that's
- 2:50:16enough of a difference to make sure we
- 2:50:17don't have any rendering Bo
- 2:50:19and by default let's also start with the
- 2:50:20visual hidden so let's do that not on
- 2:50:23the parent select game object but rather
- 2:50:24on the kitchen counter inside of it
- 2:50:26let's make sure to disable this game
- 2:50:28object by the way the quick shortcut is
- 2:50:30shift alt and a you can enable or
- 2:50:32disable the object very useful so let's
- 2:50:34start with this one disabled so that
- 2:50:36it's hidden and basically the goal is
- 2:50:38that when this counter is selected we're
- 2:50:40going to enable it and show this Visual
- 2:50:42and when it's not selected we're going
- 2:50:43to disable it okay so over here on the
- 2:50:46selected let's set the script that we
- 2:50:47made so the selected coun vision all
- 2:50:49right so let's open it now here first
- 2:50:51thing we need to know is know which
- 2:50:53counter is selected meaning we need to
- 2:50:55know which counter the player is
- 2:50:56currently looking at so let's go over
- 2:50:58here onto the player script and let's
- 2:51:00basically just use some simple logic to
- 2:51:02keep track of the selected counter so
- 2:51:04over here let's make a field so a
- 2:51:06private let's make it of type clear
- 2:51:09counter and just call it the selected
- 2:51:12counter then down here we have our
- 2:51:15handle interactions logic okay so we do
- 2:51:17all of this we try to find a counter in
- 2:51:19front and if we do find it then we have
- 2:51:21it here so here let's just check if it's
- 2:51:23different so if this clear counter if
- 2:51:25the one in front is different from the
- 2:51:27current selected then let's set the
- 2:51:29selected to this
- 2:51:31one and let's also make sure to
- 2:51:33essentially unselect so we want to make
- 2:51:35sure to set this one to null when
- 2:51:37there's nothing in front of the player
- 2:51:38so if the ray cast does not hit anything
- 2:51:40then there's nothing in front of the
- 2:51:41player so let's set the select the
- 2:51:43counter back into n and also if there is
- 2:51:45something but that something does not
- 2:51:46have the clear counter script then it's
- 2:51:48also not counter so over here let's also
- 2:51:50do an else selected counter equals null
- 2:51:52so basically if there's a counter in
- 2:51:54front of the player then it's going to
- 2:51:55set it if not then it's going to be n
- 2:51:57let's just do a simple debug onlog to
- 2:51:59check on the selected counter okay and
- 2:52:02also just briefly now that we've made
- 2:52:04this selected counter logic actually up
- 2:52:06here when we have our interact action
- 2:52:09like we saw we were previously copying
- 2:52:11some duplicated code but now we no
- 2:52:13longer need this since we already know
- 2:52:15the selected counter so over here when
- 2:52:16we've got the interact action let's just
- 2:52:19check if we do have a select counter so
- 2:52:21if it is not null if so then we go there
- 2:52:24and we call the interact function so
- 2:52:25that's it we no longer need all of this
- 2:52:27logic okay that's great so let's test
- 2:52:30back in the editor let's go back into
- 2:52:31scenes let's make sure to save the
- 2:52:33prefab make sure the script was attached
- 2:52:35save it and let's head on play and right
- 2:52:37now if I'm down here yep there you go
- 2:52:39we've got null and as I approach yep
- 2:52:41there you go that one is a clear counter
- 2:52:42and if I move towards this one yep it's
- 2:52:44that one okay so basically we are
- 2:52:45keeping track of the cord let select the
- 2:52:47counter now basically we just need to
- 2:52:49notify the visual whenever this one
- 2:52:51changes so when this one is pointing at
- 2:52:53that one or pointing at no or pointing
- 2:52:54at that one we need to know when that
- 2:52:56happens and for that we basically have
- 2:52:58two options now one option is pretty
- 2:53:00much what I mentioned a while ago which
- 2:53:02is over here we have the select counter
- 2:53:04so we can run some kind of logic on the
- 2:53:06select counter we can do that over here
- 2:53:08on the player then perhaps over here the
- 2:53:11counter would fire off some kind of
- 2:53:12event saying it has been selected and
- 2:53:15then the counter visual would listen to
- 2:53:16that event and update itself now that
- 2:53:19approach would be useful if we wanted to
- 2:53:20add some kind of logic on the clear
- 2:53:22counter while selected and that approach
- 2:53:24would also have the benefit where the
- 2:53:26visual counter would only listen to
- 2:53:27events on its own counter so that's one
- 2:53:30approach pretty much a very direct
- 2:53:31approach but another one is very simple
- 2:53:34the player would simply fire off an
- 2:53:36event whenever the selected counter
- 2:53:37changes and then all of the counter
- 2:53:39visuals would listen to that event then
- 2:53:42they would identify if the event relates
- 2:53:43to that counter and if so update their
- 2:53:45state now the benefit of this approach
- 2:53:48is that the logic doesn't get bothered
- 2:53:49with any selection logic so over here
- 2:53:51the clear counter script never really
- 2:53:53knows if it's selected or not and that's
- 2:53:55a good thing because it doesn't need to
- 2:53:56know although the potential con with
- 2:53:58that approach is that all of these
- 2:54:00selected counter visuals are all going
- 2:54:01to listen to the same event so both
- 2:54:04approaches have pros and cons here let's
- 2:54:06go with the second approach where all
- 2:54:07the counters listen to a player event
- 2:54:10the potential performance con doesn't
- 2:54:11really matter on a game of this scale
- 2:54:13we're only going to have about a dozen
- 2:54:15counters so even if 11 of them are just
- 2:54:18wasting on listening to the event it's
- 2:54:20really not going to matter and going
- 2:54:22with this approach will actually help us
- 2:54:23learn about the Singleton pattern which
- 2:54:25is extremely useful so first let's go
- 2:54:27over here onto the player class and
- 2:54:29let's make the event that we're going to
- 2:54:30fire so as usual let's make it public so
- 2:54:33we can access it let's make it an event
- 2:54:35and as usual let's also use the standard
- 2:54:37event handler let's make sure to add
- 2:54:40using system so here Visual Studio adds
- 2:54:42it automatically okay and let's call
- 2:54:44this on selected counter changed
- 2:54:53also this is a great moment to learn
- 2:54:54about the event args this is how you can
- 2:54:57extend a c event in order to pass in
- 2:54:59some more data so how you do it by
- 2:55:02following the C standard is very simple
- 2:55:04we just create a class so over here
- 2:55:06let's make a public class then for name
- 2:55:09usually you include the name of the
- 2:55:11event with event ARS at the end so in
- 2:55:13this case on selected counter changed
- 2:55:16and then event arcs then then on this
- 2:55:18class we make it extend event
- 2:55:21arcs and finally inside the class we add
- 2:55:24whatever data we want like for example
- 2:55:26we want the current selected counter so
- 2:55:28let's make a public clear counter and
- 2:55:31put the selected
- 2:55:33counter okay so we have this nice event
- 2:55:36ARs with a bunch of extra data and then
- 2:55:38over here on the event handler we use
- 2:55:39the version that takes a generic and we
- 2:55:41pass in our event arcs again I covered
- 2:55:44the generics in more detail in a
- 2:55:45separate video definitely go watch that
- 2:55:47one if if you haven't seen it yet C
- 2:55:49generics are one of C's most powerful
- 2:55:51features okay great so we now have our
- 2:55:54nice event now let's fire it off so
- 2:55:57let's go down here to when we're
- 2:55:58modifying the selected counter so here
- 2:56:00it is we've got all of these ones so
- 2:56:02when we modify let's fire off the event
- 2:56:04so we go into this event and as usual
- 2:56:05let's use the question mark and then
- 2:56:07call invoke then for the object sender
- 2:56:09it's going to be this so pretty much a
- 2:56:10standard and then for our custom event
- 2:56:12TS let's construct an object of that
- 2:56:14type so construct a new object and then
- 2:56:17inside we pass in the selected counter
- 2:56:19and we set it to this selected counter
- 2:56:21now don't be confused by the fact that
- 2:56:22we're using the exact same name if you
- 2:56:24actually Mouse over the cursor Visual
- 2:56:26Studio actually helps you by telling you
- 2:56:28which object refers to this so with the
- 2:56:30cursor here note how all of these are
- 2:56:32highlighted but this one is not
- 2:56:33highlighted that's because this field
- 2:56:35this is the field inside the unselected
- 2:56:37counter change vent ARS whereas this one
- 2:56:39out here is the object that we're
- 2:56:41referencing in here so even though these
- 2:56:43two have the exact same name here we're
- 2:56:45accessing the field inside of that and
- 2:56:46we're assigning it to the reference that
- 2:56:48we have have down here okay so that's
- 2:56:49really it we're firing off the event
- 2:56:51when the selected changes and we're
- 2:56:52passing it in and let's also make sure
- 2:56:54to do it over here so let's copy and
- 2:56:56paste some code and there you go just
- 2:56:58like this except of course we can
- 2:57:00already see a bunch of code duplication
- 2:57:02usually that means it's time to refactor
- 2:57:04so let's do that pretty quickly let's go
- 2:57:06down and make a brand new function so
- 2:57:09let's make a private void let's call it
- 2:57:11set selected counter and we're going to
- 2:57:14receive a clear counter for the selected
- 2:57:17counter
- 2:57:20then over here we just set this do
- 2:57:21selected counter so we're modifying the
- 2:57:23member variable with the one that we
- 2:57:24receive on the parameter and then let's
- 2:57:27also fire off the event so let's copy
- 2:57:28paste the event just like this the exact
- 2:57:31same thing okay so that's it and now up
- 2:57:33there instead of code duplication we
- 2:57:35just do this so over here we set the
- 2:57:37clear counter just call the function
- 2:57:39pass in that one and get rid of this and
- 2:57:42on that one just pass in null just like
- 2:57:45this get rid of all of this and here the
- 2:57:47same thing just pass and null all right
- 2:57:50so with this our code is much cleaner
- 2:57:51and everything still works EXA the same
- 2:57:53so here we have everything done on the
- 2:57:55player side let's just get rid of our
- 2:57:57log we no long need this so we're still
- 2:57:59handling the selected counter logic and
- 2:58:01then down here we're firing off the
- 2:58:03event now what we need to do is go over
- 2:58:05here into the selected counter Vision
- 2:58:06script and here what we want to do is to
- 2:58:09listen to that event and in order to do
- 2:58:10that we need a reference to the player
- 2:58:12object now so far when we've been
- 2:58:14listening to events like for example on
- 2:58:16the player class up here we were
- 2:58:18listening to some events on the game
- 2:58:20input so there you go the UN interact
- 2:58:21action so for the game input reference
- 2:58:24we just added as a serialized field we
- 2:58:27did this and then we dragged the
- 2:58:28reference directly and technically we
- 2:58:30could do the same thing over here on the
- 2:58:31selected counter visual but we're going
- 2:58:33to have like a dozen counters in our map
- 2:58:35so it would be pretty tedious to drag
- 2:58:37and drop the player reference to every
- 2:58:39single one of them so instead of using a
- 2:58:41serialized field another approach is to
- 2:58:43use a Singleton pattern this one is an
- 2:58:45extremely useful programming pattern
- 2:58:47it's it's very useful for things where
- 2:58:49you only have one instance of something
- 2:58:52in this case we're making this game
- 2:58:53single player so we're only ever going
- 2:58:55to have a single player by the way
- 2:58:57here's one obvious quick note like I
- 2:58:59mentioned in the beginning of this
- 2:59:01course after this video there's going to
- 2:59:03be another one converting this game into
- 2:59:05multiplayer and in that case we will
- 2:59:07have multiple player instances but this
- 2:59:09is also an excellent reminder of how
- 2:59:11refactoring code is perfectly fine for
- 2:59:13right now for this game it is intended
- 2:59:15as single player so for now we're going
- 2:59:17to use the single pattern then in the
- 2:59:19future when we convert this to
- 2:59:20multiplayer we will simply refactor that
- 2:59:22logic again don't be afraid of
- 2:59:25refactoring code it's a Perfectly
- 2:59:27Natural part of programming and game
- 2:59:28development okay so let's implement the
- 2:59:30single pattern this is actually super
- 2:59:32simple the name sounds intimidating but
- 2:59:34it really is very simple over here on
- 2:59:37the player script let's make a public
- 2:59:39field this one let's make it static if
- 2:59:43you don't know static basically it means
- 2:59:45that this field belongs to the player
- 2:59:47class itself and not to any instance of
- 2:59:49a player so for example if you had 100
- 2:59:51players you would have 100 instances of
- 2:59:54move speed you would have one for each
- 2:59:56player but there would only be a single
- 2:59:58static field because this static field
- 3:00:00belongs to the class itself and not to
- 3:00:02any instance so let's make a field of
- 3:00:04type player and then for the name the
- 3:00:06convention is to call it instance and
- 3:00:08the reason why I'm using Pascal case
- 3:00:10here so capitalized in the beginning the
- 3:00:13reason for that is because this is
- 3:00:14actually not going to be a field but
- 3:00:16instead it's going to be a property
- 3:00:18remember the naming rules that we
- 3:00:19covered in the beginning of this course
- 3:00:22it's very important you follow your
- 3:00:23naming rules always be consistent so
- 3:00:25your code is easier to understand so
- 3:00:27with that said since this is the first
- 3:00:29time we're using a property let me
- 3:00:30quickly explain what it is basically
- 3:00:32it's the exact same thing as a regular
- 3:00:34variable except you can add some logic
- 3:00:36when getting and setting that field so
- 3:00:38here let me write some quick code just
- 3:00:40to show the difference between a
- 3:00:41property in a regular field so for a
- 3:00:44regular field you would call this maybe
- 3:00:45instance field something like this so
- 3:00:47this is a regular field then you would
- 3:00:50have some kind of public
- 3:00:54static return the player and call it get
- 3:00:56instance
- 3:00:58field then over here you would return
- 3:01:00the instance field and then maybe
- 3:01:03another public static void set instance
- 3:01:06field where you receive a player for the
- 3:01:08instance
- 3:01:10field and you would set the player.
- 3:01:12instance field into this instance field
- 3:01:14so this is how you do this logic with
- 3:01:16fields and now with
- 3:01:18properties you would do public static
- 3:01:21player then call it
- 3:01:23instance then on the property itself you
- 3:01:25open up the currently
- 3:01:27brackets inside the property you put a
- 3:01:29get then you return something so for
- 3:01:32that something usually a property has a
- 3:01:34field underneath it so you'd have a
- 3:01:37private static
- 3:01:38player for the instance that's a
- 3:01:41different name from this one on the get
- 3:01:43you would return that and on the set you
- 3:01:48set the instance equals z value if
- 3:01:50you're confused here don't worry
- 3:01:52basically I'm just repeating just so you
- 3:01:54can see difference here we have a field
- 3:01:56with a get and a set function so regular
- 3:01:58functions and up here we have a property
- 3:02:00and inside the property the property
- 3:02:02itself has a get and set functions which
- 3:02:05can also do some logic so you can do
- 3:02:06some logic in between or you can just
- 3:02:09return the underlying value so basically
- 3:02:11using a property is pretty much the
- 3:02:13exact same thing as using a separate get
- 3:02:15and set function also one more bonus
- 3:02:18thing which is that c is smart enough to
- 3:02:21automatically create the underlying
- 3:02:22field for a certain property so if you
- 3:02:24just want to do a get and a set then you
- 3:02:26don't need to Define all this you can
- 3:02:28just Define a property and then inside
- 3:02:31you can just do get and
- 3:02:33set and there you go this code here
- 3:02:35works the exact same thing as we had
- 3:02:37previous one which in turn is the exact
- 3:02:38same thing as all the code we have here
- 3:02:40with a getter and a Setter function so
- 3:02:42here it is a valid functional C property
- 3:02:45now I have to say that personally I
- 3:02:47veryy very very rarely used properties
- 3:02:49in fact the only place where I use them
- 3:02:51is over here on the Singleton pattern
- 3:02:53for everything else I normally use
- 3:02:55regular Fields with get and set
- 3:02:56functions personally that's just the way
- 3:02:58that I like to code but that's really
- 3:03:00just personal preference so if you do
- 3:03:02like to use properties then go ahead and
- 3:03:04use them anyway so the reason why I like
- 3:03:07using a property specifically for the
- 3:03:08single pattern is because the implicit
- 3:03:11implementation allows you to do
- 3:03:13something really nice again remember the
- 3:03:15goal with clean code we want to minimize
- 3:03:18complexity and the best way to do that
- 3:03:19is minimize access here if we set this
- 3:03:22property and we set it as public then
- 3:03:24that means that any other class can both
- 3:03:26get and set so anyone else can have both
- 3:03:28read and write access so we have the
- 3:03:31exact same problems that I warned you
- 3:03:32about when I spoke about why you should
- 3:03:34not make everything public and of course
- 3:03:36if we make this private then at that
- 3:03:39point we kind of lose the purpose of our
- 3:03:40Singleton since no one else will be able
- 3:03:42to access this basically we want to be
- 3:03:44able to access this reference from
- 3:03:45classes outside of this one we just
- 3:03:47don't want those classes to also have
- 3:03:49right access now thankfully properties
- 3:03:52have an excellent thing which is you can
- 3:03:53Define accessors for here both the get
- 3:03:55and the set so we can make the property
- 3:03:57itself public which means by default
- 3:03:59both of these won't be public but then
- 3:04:02we can also add the accessor over here
- 3:04:03private which in turn means that the get
- 3:04:06won't be public so any other class can
- 3:04:07get this but private means that only
- 3:04:10this class can set it this way we have
- 3:04:12the exact level of accessibility that we
- 3:04:14want this is the reason why for this
- 3:04:16specific use case properties are are
- 3:04:17very useful with just this one line of
- 3:04:20code we already have our instense with
- 3:04:21the perfect level of accessibility so
- 3:04:24now that we have this field to set it
- 3:04:26let's make a simple awake so let's go
- 3:04:28over here private void awake and on
- 3:04:30awake we just set instance equals this
- 3:04:33however remember that a key point of the
- 3:04:35Singleton pattern is you only have a
- 3:04:37single instance of something so in this
- 3:04:40case we should never have more than one
- 3:04:41player if we do then something went
- 3:04:43wrong so we can add a nice safety
- 3:04:46feature here let's just just check if
- 3:04:48instance if it is not known meaning it
- 3:04:51has already been set to something if so
- 3:04:53then that's an error something bad
- 3:04:55happened similar to a debug.log error
- 3:04:58because this should never happen so
- 3:05:00let's say there is more than one player
- 3:05:03instance this way we have a nice safety
- 3:05:05check just in case something goes wrong
- 3:05:07all right so that's really it for the
- 3:05:09Singleton pattern we just Define a
- 3:05:11property with a public yet in a private
- 3:05:13set and on awake we just set the
- 3:05:14instance that's it as you can see it's
- 3:05:16super simple
- 3:05:18and now for the really useful part over
- 3:05:20here on the selected counter visual now
- 3:05:22we can access the Singleton instance in
- 3:05:24a super easy way let's make a private
- 3:05:27void start and on start we just access
- 3:05:29the player class and from the class we
- 3:05:31can access the static instance so we can
- 3:05:33access the Singleton and now we can
- 3:05:35listen to The unselected Counter event
- 3:05:37and over here by default Visual Studio
- 3:05:39gives this function the name of the
- 3:05:41event and also the property this isn't a
- 3:05:43very descriptive name so I like to
- 3:05:45rename this so control RR and just just
- 3:05:47rename the instance here instead of
- 3:05:49instance let's rename it to player okay
- 3:05:51great so over here we can listen to this
- 3:05:53event however here is yet another
- 3:05:56extremely important thing note how I
- 3:05:58made this on start that is very
- 3:05:59important if you do this over here on
- 3:06:02awake instead of start and over here on
- 3:06:04the player you're also setting the
- 3:06:05instance on awake if you do that
- 3:06:07basically there is a chance that this
- 3:06:09code will run before this code and if
- 3:06:11that happens well then this one the
- 3:06:12player instance has not been set yet so
- 3:06:14this will be null and it will throw a
- 3:06:16null reference exception now whether
- 3:06:18this happens or not is actually somewhat
- 3:06:20random it depends on the order in which
- 3:06:22Unity decides to run both these scripts
- 3:06:24if Unity decides to run the player first
- 3:06:27and this one second if that happens then
- 3:06:30there's no problem but if Unity decides
- 3:06:32to run this first and then this one then
- 3:06:33we have a problem let me do a quick test
- 3:06:35and see if in my case it triggers that
- 3:06:37error and if in my case it did trigger
- 3:06:39that error so here we have a non
- 3:06:41reference exception and yep it is being
- 3:06:43fired on this line now one solution to
- 3:06:45this problem is you can tell Unity spe
- 3:06:47spefically which order the script should
- 3:06:49run in so you can go up here into edit
- 3:06:51then go into the project settings then
- 3:06:54on the left side you've got something
- 3:06:55called The Script execution order and
- 3:06:57basically over here you can set the
- 3:06:59order in which all of these scripts run
- 3:07:01so if you were to make the player script
- 3:07:03run before the default time that would
- 3:07:05make sure that even though both these
- 3:07:06scripts are on awake this one would run
- 3:07:08before this one so that would fix that
- 3:07:10problem however you should really only
- 3:07:12use this approach in the last case
- 3:07:13possible where there really is no other
- 3:07:15way in this case we do have another a
- 3:07:17better way personally I have a very
- 3:07:19simple rule that I like to follow that
- 3:07:21helps solve this issue as you know Unity
- 3:07:23has both an awake and a start and all of
- 3:07:26the awakes on all the objects will all
- 3:07:28run before all of these starts so the
- 3:07:31simple rule that I follow is that I use
- 3:07:32awake for the initialization of that
- 3:07:34script and for any external reference
- 3:07:37for that I use it on start so in this
- 3:07:39case for initializing the player and
- 3:07:41setting the instance that relates to the
- 3:07:43initialization of the player so let's do
- 3:07:44it on awake whereas over here on the
- 3:07:46visual
- 3:07:48since here we're going to access the
- 3:07:49player which is an external reference
- 3:07:51for this one instead of doing it on Wake
- 3:07:53let's do it on start this way we are
- 3:07:56guaranteed to make sure that this
- 3:07:57instance has been set okay so with all
- 3:08:00of that here we have our instance so
- 3:08:01that works great and we have our event
- 3:08:03so that's great then here we have our
- 3:08:05event and inside we've got our event ARS
- 3:08:07so we can go inside the event arcs
- 3:08:09object and inside we have our selected
- 3:08:11counter so all we need to do is just
- 3:08:13compare which counter this visual
- 3:08:15belongs to so let's actually make a
- 3:08:17field up here so as usual let's make a
- 3:08:19serialized field of type clear
- 3:08:24counter so we have this one and before
- 3:08:26we go into the editor just make sure it
- 3:08:28compiles let's comment this out so now
- 3:08:30let's go back into the editor and over
- 3:08:32here let's rag the reference but again
- 3:08:34remember we're working with a prefab so
- 3:08:36let's click on open to go inside the
- 3:08:38prefab and now whil inside it let's
- 3:08:40select the selected game object and just
- 3:08:42drag the clear counter reference okay
- 3:08:44great let's go back outside and save the
- 3:08:47changes all right so now here in the
- 3:08:49code it's actually very simple so we
- 3:08:50just do an if if the selected counter
- 3:08:53matches this clear
- 3:08:54counter if so then we want to show this
- 3:08:57visual if not we want to hide it so
- 3:08:59let's also add a reference for that
- 3:09:00visual so let's add another serialized
- 3:09:02field of type game object for the visual
- 3:09:05game
- 3:09:07object then back in the editor again
- 3:09:09let's go inside the prefab and on the SL
- 3:09:11let's drag the child kitchen counter so
- 3:09:13drag that one that is the visual game
- 3:09:15object okay let's go back save and back
- 3:09:17in the code here let's make some simple
- 3:09:19show and hide functions so private void
- 3:09:22show and a private void
- 3:09:24hide and now on the show just go into
- 3:09:27visual game object and call set active
- 3:09:29so this enables or disables the game
- 3:09:31object so for show let's set it to true
- 3:09:33and for hiding let's set it back into
- 3:09:35false okay so now it's super simple if
- 3:09:37the selected counter is this counter
- 3:09:39then let's show the visual if it is not
- 3:09:41then let's hide the visual all right
- 3:09:43that's it super simple let's test so
- 3:09:46here we are and if I approach that
- 3:09:47counter yep there you go look at that
- 3:09:49the nice selected Visual and if I go
- 3:09:50into this one yep there you go I can see
- 3:09:52it all right great so here we haded a
- 3:09:56really nice visual to our selected
- 3:09:57counter and more importantly we'll learn
- 3:10:00about the super useful Singleton pattern
- 3:10:02as well as learning about C Properties
- 3:10:04and a very helpful rule for how to avoid
- 3:10:06code timing issues so this was a really
- 3:10:09detailed really important lecture if
- 3:10:11you're feeling confused about anything
- 3:10:13go ahead watch it again or just post a
- 3:10:14question in the comments and I'll do my
- 3:10:16best to help so with all of this this is
- 3:10:18all great we have the selected counter
- 3:10:20and we can see which one is actually
- 3:10:21being selected then by pressing a button
- 3:10:23we can actually interact with it so I
- 3:10:25can move and interact with any of these
- 3:10:27counters but right now just interacting
- 3:10:29with them doesn't really do anything so
- 3:10:31the next thing we need is to create some
- 3:10:33proper objects for all of our
- 3:10:34ingredients so we can later pick them up
- 3:10:36and drop them on counters so let's begin
- 3:10:38doing that in the next
- 3:10:40lecture hey again quick intermission
- 3:10:43you're past the 15 lecture marks so
- 3:10:45congratulations looking at my regular
- 3:10:47course stats it seems about 80% of
- 3:10:49people give up by this point so great
- 3:10:51job with sticking with it the difficulty
- 3:10:53and complexity is increasing over the
- 3:10:55lectures so I just want to check in to
- 3:10:56make sure you're understanding
- 3:10:58everything remember to post in the
- 3:11:00comments if you need extra clarification
- 3:11:01on anything and I'll do my best to
- 3:11:03answer also check the website to see
- 3:11:05what questions others have asked and of
- 3:11:07course remember this is your Learning
- 3:11:09Journey you're not competing with anyone
- 3:11:10but yourself so take your time re-watch
- 3:11:13some lectures if you need to just focus
- 3:11:15on learning okay let's go to the next
- 3:11:18lecture hello and welcome I'm your Cod
- 3:11:20monkey in this lecture we're going to
- 3:11:22learn how to create the kitchen objects
- 3:11:24like the various ingredients okay so far
- 3:11:26we have our player we can walk around I
- 3:11:29can approach each of these counters and
- 3:11:30I can interact with now the next goal is
- 3:11:32to create objects the player can pick up
- 3:11:34and drop when interacting with a clear
- 3:11:36counter so let's begin by making the
- 3:11:38actual objects so let's create a new
- 3:11:40empty game object call this one the
- 3:11:42Tomato then again as usual let's
- 3:11:44separate the visual so in the included
- 3:11:46assets let's go inside of it then we've
- 3:11:48got the preat visuals and we've got the
- 3:11:50kitchen objects visuals and inside we've
- 3:11:52got all of the ingredients so let's just
- 3:11:54find the Tomato Visual and drag it as a
- 3:11:56child of the tomato and again as usual
- 3:11:58make sure to put on position local
- 3:11:59position 0000 0 and for the main one
- 3:12:03let's put it on a y of zero and just
- 3:12:04push it a bit off to the side just so we
- 3:12:06can see okay great now this one is
- 3:12:09obviously not going to exist over here
- 3:12:10in our world instead we're going to
- 3:12:11spawn it so let's make it a prefab let's
- 3:12:14just drag it over here into our prefabs
- 3:12:16okay there it is
- 3:12:17let's delete it from our scene and
- 3:12:20actually on our prefabs let's make a
- 3:12:21nice folder to keep things nicely
- 3:12:23separated so inside the prefabs let's
- 3:12:26make a sub
- 3:12:27folder call it the kitchen objects let's
- 3:12:30put the tomato inside of it and let's
- 3:12:32also make another folder for the
- 3:12:34counters and let's put the clear counter
- 3:12:36inside of it okay so everything is
- 3:12:38nicely organized all right now that we
- 3:12:40have this let's go inside our clear
- 3:12:42counter script and over here let's add a
- 3:12:45simple reference to our prefab
- 3:12:47so let's make of type transform call it
- 3:12:50the Tomato
- 3:12:51prefab by the way here you could make
- 3:12:54this prefab reference of type game
- 3:12:55object which type you use in this
- 3:12:57scenario is pretty interchangeable I
- 3:12:59talked about those differences in
- 3:13:01another video so when using prefabs
- 3:13:03using them as transforms or game objects
- 3:13:05as pretty much personal preference and
- 3:13:07personally I just prefer to use them as
- 3:13:09transforms okay so we have this let's
- 3:13:11just make this a serialized field so we
- 3:13:12can set it in the editor and over here
- 3:13:15in the editor let's open up go inside
- 3:13:17the counter prefab and just drag the
- 3:13:19Tomato reference okay great let's go
- 3:13:21back outside save now back in the code
- 3:13:23here when the player interacts with it
- 3:13:25let's just spawn it so let's call
- 3:13:33incentious we don't want to spawn on
- 3:13:35this counter's origin remember that the
- 3:13:37counter the way we set it up the origin
- 3:13:39on the actal objects over there on the
- 3:13:40bottom we don't want to spawn the tomato
- 3:13:43inside the mesh that would not make
- 3:13:44sense instead what we want is to spawn
- 3:13:47up here so the next question is okay so
- 3:13:49how do we get this point on top of the
- 3:13:51counter one approach would be to use a
- 3:13:53vector 3 directly in the code that would
- 3:13:55work but not very usable so a more
- 3:13:57designer friendly method is to Simply
- 3:13:59use an empty game object as a Target so
- 3:14:01on the counter let's first go inside our
- 3:14:03prefab and over here let's create an mty
- 3:14:06game object inside of it let's call this
- 3:14:08the countertop Point let's make sure to
- 3:14:11leave this one as empty so no components
- 3:14:13just a transform and now let's just
- 3:14:15position it so let's lift it up just
- 3:14:17about enough so let's make sure we see
- 3:14:19so there you go just about that so let's
- 3:14:22put it on position a y of 1.3 all right
- 3:14:25so this point is going to be our spawn
- 3:14:27point let's make sure to save the prefab
- 3:14:30then back in the code here let's add a
- 3:14:31reference to our point and for reference
- 3:14:34let's also use a transform reference
- 3:14:36call it the countertop
- 3:14:38Point okay now let's just come this line
- 3:14:41just so the code compiles so we can drag
- 3:14:42the reference back in the editor inside
- 3:14:44the pref let's just drag the counter
- 3:14:46toop Point reference reference okay
- 3:14:47great so now here when we call
- 3:14:49instantiate let's instantiate it inside
- 3:14:52the counter top point so this will spawn
- 3:14:54the object so let's say the transform
- 3:14:56for the Tomato
- 3:14:58transform and then we go inside this one
- 3:15:00and let's just make sure we position it
- 3:15:02correctly so let's put it on a local
- 3:15:04position of vector 3.0 so this will put
- 3:15:06the object exactly on top of our
- 3:15:08countertop point also here very
- 3:15:10important don't make a mistake make sure
- 3:15:12you're modifying the local position and
- 3:15:14not the global position okay so with
- 3:15:17this let's test over here in the editor
- 3:15:19let's go back save our prefab and hit on
- 3:15:21play so here we are let's approach the
- 3:15:22counter and interact with it and Y there
- 3:15:24you go it does work the Tomato was
- 3:15:26indeed spawned all right awesome okay so
- 3:15:29with this we have pretty much our Basics
- 3:15:30working we can move up to a counter we
- 3:15:33can interact with it and spawn an object
- 3:15:35but now let's say that we want to spawn
- 3:15:37a different object so let's say now we
- 3:15:39want to spawn some cheese first of all
- 3:15:41let's make the actual object so on the
- 3:15:42Tomato let's press contr D to duplicate
- 3:15:44this one let's rename this to the che
- 3:15:47cheese block and let's go inside of it
- 3:15:50now in here inside of the Tomato visual
- 3:15:52let's drag here it is the cheese block
- 3:15:54visual so let's use this one instead
- 3:15:56okay there's our nice visual let's make
- 3:15:59sure to save the prefab and go back out
- 3:16:01and now let's say that we want this one
- 3:16:02to spawn a tomato and this one on the
- 3:16:04left to spawn some cheese so let's
- 3:16:06override the prefab and over here drag
- 3:16:08the cheese block and now if we h on play
- 3:16:11can go up to this one yep there's a
- 3:16:12tomato go up to this one and yep there's
- 3:16:14some cheese okay so it all looks great
- 3:16:17but now let's say we want to know what
- 3:16:18object we just spawned like what object
- 3:16:20is on top of this spawn transform just
- 3:16:22like this in the code all we have is a
- 3:16:24transform reference so with this the
- 3:16:27only way to know what type we spawned
- 3:16:28would be if we had different prefabs for
- 3:16:30every single object then we could
- 3:16:32compare them one by one and see which
- 3:16:34one this matches but then let's say what
- 3:16:36if we wanted an actual string for the
- 3:16:38object well then we would need to add
- 3:16:40tons of fields for all these strings for
- 3:16:42all the objects then what about an icon
- 3:16:45for each type once again we would need
- 3:16:47tons of fields each one for each icon
- 3:16:49but if we did it just like that with a
- 3:16:51bunch of lists then they would be
- 3:16:52separate that's not very good we should
- 3:16:54have a proper way of defining our object
- 3:16:56types and all the data related to them
- 3:16:59so this is exactly where scriptable
- 3:17:01objects come in these are objects you
- 3:17:03can create in your project files which
- 3:17:04are perfect for anything where you have
- 3:17:06multiple instances of a type like for
- 3:17:08example multiple weapons multiple armors
- 3:17:11multiple recipes or maybe multiple
- 3:17:13ingredients as usual I have a dedicated
- 3:17:15video on scriptable objects they are
- 3:17:17super useful definitely watch that for
- 3:17:19more detail over here and let's just use
- 3:17:20them so the first thing we're going to
- 3:17:22need is to actually Define the type and
- 3:17:24we do that in a c script so in our
- 3:17:26script folder let's create a new C
- 3:17:28script call this the kitchen object so
- 3:17:32now personally so is just what I like to
- 3:17:34append to my script B object definitions
- 3:17:37just to make it very clear that it's a
- 3:17:38script ball object however this is not a
- 3:17:40requirement it's just a naming rule that
- 3:17:42I like to follow and we're calling this
- 3:17:44kitchen object because we're going to
- 3:17:45use this to Define any kitchen object we
- 3:17:47want to interact with so that's going to
- 3:17:49be our ingredients like for example the
- 3:17:51tomato and cheese but also things like a
- 3:17:53plate and then potentially you could
- 3:17:55Implement things like a frying pen or
- 3:17:56frying signature or anything like that
- 3:17:58so this going to represent any kind of
- 3:18:00kitchen object the player can interact
- 3:18:02with Okay so let's make the script and
- 3:18:04now let's open it and over here okay
- 3:18:07first things first is this is not a mono
- 3:18:09Behavior instead let's extend script
- 3:18:12ball object and then technically you can
- 3:18:14have functions inside a scriptable
- 3:18:16object but for now let's just get rid of
- 3:18:18this so just an empty class and over
- 3:18:20here let's just Place whatever fields we
- 3:18:22need to store whatever data we want so
- 3:18:24like I said first we want a prefab so
- 3:18:26let's make a public transform for our
- 3:18:28prefab by the way here note how I am
- 3:18:30indeed using public this is pretty much
- 3:18:33the one exception to the rule I only use
- 3:18:35scriptable objects as read only data
- 3:18:37containers I never write to them so
- 3:18:39since I follow that rule I usually make
- 3:18:41the fields in the scriptable object
- 3:18:42public that way I can access them
- 3:18:44directly without having to make a public
- 3:18:46G but if you want do feel free to keep
- 3:18:48following the general rule of not making
- 3:18:50anything public you could definitely
- 3:18:52make this just a regular serialized film
- 3:18:54and expose with a get function that
- 3:18:55would work personally I just find it
- 3:18:57simpler to make it public since I know
- 3:18:59that as a personal rule I will never
- 3:19:01write to a scriptable object field okay
- 3:19:03so we have a transform for our prefab
- 3:19:05let's also add a Sprite for the icon
- 3:19:08Sprite and finally let's just add a
- 3:19:10simple string for the object name all
- 3:19:14right so we have our scriptable object
- 3:19:15definition we have all the fields for
- 3:19:17all the data we want to store now how do
- 3:19:20we actually create a script object for
- 3:19:22that let's go up here before the class
- 3:19:24name and we're going to add the
- 3:19:25attribute so let's add the square
- 3:19:27brackets and the attribute is the create
- 3:19:29asset menu this takes some optional
- 3:19:31parameters again I cover them in detail
- 3:19:33in the dedicated scriptable objects
- 3:19:35video for now let's just leave all the
- 3:19:37parameters as empty just use default and
- 3:19:39close the attribute okay so that's it
- 3:19:41let's save this and go back into the
- 3:19:43editor and over here if we go into the
- 3:19:45project window click on the plus icon
- 3:19:47and right up top yep we do see a kitchen
- 3:19:49object as so so if we select it yep
- 3:19:51there you go it creates a brand new
- 3:19:53object inside of our project files let's
- 3:19:55name this one tomato and obviously let's
- 3:19:58keep our project nice and organized so
- 3:19:59we don't want this inside the script
- 3:20:01folder instead let's make a proper
- 3:20:03folder so create a new folder call it
- 3:20:05our scriptable objects and then inside
- 3:20:08let's put a different folder for each
- 3:20:10type so let's make another subfolder
- 3:20:12call it the kitchen object so and let's
- 3:20:15place the tomato inside out of it okay
- 3:20:17now with the Tomato selected we can look
- 3:20:19in the inspector and we can see yep it
- 3:20:21does have all of the fields that we
- 3:20:23defined okay great so now we can just
- 3:20:25assign them so this is the Tomato let's
- 3:20:27drag the Tomato prefab for the econ
- 3:20:30Sprite let's find it so that are Sprites
- 3:20:32included in the regular assets so here
- 3:20:34is the Tomato Sprite so it's inside the
- 3:20:36assets then inside textures icons and we
- 3:20:39have all the icons and finally for the
- 3:20:41readable name let's just call it tomato
- 3:20:43all right so that's it here we have a
- 3:20:45really nice script object containing all
- 3:20:47the data required for our tomato okay
- 3:20:49awesome with that done we can now go
- 3:20:51back into our clear counter script and
- 3:20:54here instead of adding a field for our
- 3:20:55tomato pream instead of this let's sort
- 3:20:58a reference of type kitchen object so
- 3:21:00and let's call it kitchen objecto and
- 3:21:03then when spawning let's go inside our
- 3:21:05script B object and just spawn the
- 3:21:06prefab reference so this is going to be
- 3:21:09the kitchen object transform then over
- 3:21:13here in the editor let's go inside the
- 3:21:14clear counter and let's assign the
- 3:21:16Tomato Kitchen object okay so let's save
- 3:21:18it and test so here we are let's
- 3:21:21approach hit and yep there you go it
- 3:21:22still spawns e tomato okay great now
- 3:21:25let's make another type for our cheese
- 3:21:27block so let's create a brand new
- 3:21:29kitchen object as so qual it the cheese
- 3:21:31block and again let's assign first of
- 3:21:33all the prefab there it is then for the
- 3:21:35Sprite of the cheese block and finally
- 3:21:37this is the cheese block okay so now for
- 3:21:40example let's go into the second one and
- 3:21:42on the second counter let's override and
- 3:21:44say this one spawn a cheese block Let's
- 3:21:46test so here we are approach this one
- 3:21:48yep there's a tomato this one and yep
- 3:21:50there's some cheese okay great so
- 3:21:52everything is working so far however the
- 3:21:54original problem that we were trying to
- 3:21:56solve identifying the spawn prefab we
- 3:21:58still don't have a solution for that
- 3:22:00basically when we spawn a prefab we need
- 3:22:02to know from which scripal object this
- 3:22:04prefab came from so essentially what I
- 3:22:06like to do is just attach some reference
- 3:22:08to the scripal object in our prefab
- 3:22:10however again remember that scriptum
- 3:22:11objects are not mono behaviors so if I
- 3:22:14select the prefab and I try dragging
- 3:22:16these script object nope it does not
- 3:22:17work so what we can do is just create a
- 3:22:19new script so let's make a brand new C
- 3:22:22script let's call it kitchen
- 3:22:25object let's attach this to both prefabs
- 3:22:28so both the cheese and the block attach
- 3:22:29the same one to both them and let's open
- 3:22:33and over here very simple let's just add
- 3:22:34a serialized field for a kitchen object
- 3:22:36so a serialized field of type kitchen
- 3:22:40object so for the kitchen object so then
- 3:22:43let's also make a quick function to
- 3:22:45expose it so we're going to return kit
- 3:22:46object so get kitchen object so and we
- 3:22:49just return the kitchen object so yep
- 3:22:51just like this so now here in the editor
- 3:22:54for the Tomato yep we've got the field
- 3:22:55so let's say this one is a tomato and a
- 3:22:57cheese block this one is a cheese block
- 3:23:00now here obviously we need to make very
- 3:23:02very sure to drag the correct reference
- 3:23:04to the right scriptable object if you
- 3:23:05drag the wrong one like for example over
- 3:23:07here on the cheese you would say this
- 3:23:08one is a tomato if you did that then
- 3:23:10obviously you would get some very weird
- 3:23:12results so make sure to check and double
- 3:23:14check that you drag the right reference
- 3:23:17both over here on the prefiles make sure
- 3:23:19they are referencing the correct script
- 3:23:20object and on the script object itself
- 3:23:22make sure they are referencing the
- 3:23:23correct pref okay so now if we go here
- 3:23:26on the clear counter we spawn our object
- 3:23:28okay great then on this object we can do
- 3:23:31get component of type kitchen object and
- 3:23:34then we can just ask it to give us the
- 3:23:36kitchen object so so for example let's
- 3:23:38do a debug. log on this one so inside
- 3:23:42get the kitchen object the so and then
- 3:23:43let's print out the object name all
- 3:23:45right so here we are here let's interact
- 3:23:47with this one and yep there you go
- 3:23:48interacted and spawned the tomato and on
- 3:23:50this one yep interacted and spawned a
- 3:23:52cheese block okay awesome we spawned a
- 3:23:54transform prefab and we identify the
- 3:23:56spawned object is indeed this type of
- 3:23:58object all right so here we'll learn
- 3:24:00about one of the most powerful Unity
- 3:24:02features scriptable objects these are
- 3:24:04extremely useful for defining a type and
- 3:24:06then creating multiple instances of that
- 3:24:08type with whatever data we want so that
- 3:24:10can be some ingredients like we have
- 3:24:12here or it could be some weapons could
- 3:24:14even be some NPC data maybe some Quest
- 3:24:16data and so on it really is an insanely
- 3:24:19very useful feature definitely go ahead
- 3:24:21and watch a dedicated video on script
- 3:24:23objects then if you want you can also
- 3:24:25watch some more videos where I've used
- 3:24:26script Mo objects for example the
- 3:24:28Minecraft crafting system using script
- 3:24:30Mo objects or the hydr crafting system
- 3:24:32which again also uses script objects
- 3:24:35okay so this done it's working great now
- 3:24:37let's continue to the next lecture where
- 3:24:39we're going to help the kitchen object
- 3:24:41know where it belongs and help each
- 3:24:43counter know what kitchen object is on
- 3:24:45top of it
- 3:24:47hello and welcome I'm your Cod monkey in
- 3:24:49this lecture we're going to create a
- 3:24:51kitchen object parent meaning that the
- 3:24:53kitchen object will know where it is and
- 3:24:55the counter will know if something is on
- 3:24:57it this is important so that later on we
- 3:24:59can pick up a kitchen object from one
- 3:25:01place and drop it in another okay so
- 3:25:03here we have our player I can move
- 3:25:05towards this counter interact with it
- 3:25:06and yep spawn a tomato then on this one
- 3:25:08spawn some cheese okay great but I
- 3:25:11cannot do anything else in fact if I
- 3:25:13interact a bunch more times really all I
- 3:25:16did would just spawn a whole bunch more
- 3:25:17cheese so instead I want to be able to
- 3:25:19spawn some cheese and then pick it up so
- 3:25:22let's think about exactly what that
- 3:25:23means we want a kitchen object to
- 3:25:25essentially be placed on a specific
- 3:25:27Place based on the design that we're
- 3:25:29trying to implement we're never going to
- 3:25:30have a kitchen object just randomly
- 3:25:32strown around the wall we're not going
- 3:25:34to have tomatoes all over the floor
- 3:25:36instead the objects will always need to
- 3:25:38be placed somewhere and that somewhere
- 3:25:40can be either a counter or it can be
- 3:25:42being held by the player so essentially
- 3:25:44that means that each kitchen object is
- 3:25:45going to have some kind of parent that
- 3:25:47it's attached to we're going to make
- 3:25:49sure the counter knows if there is a
- 3:25:50kitchen object placed on top of it and
- 3:25:52we're also going to make sure the
- 3:25:53kitchen object itself knows where it is
- 3:25:56so first let's do that logic over here
- 3:25:57on the counter so on the clear counter
- 3:25:59script let's keep a field for a kitchen
- 3:26:03object so just a simple private of type
- 3:26:06kitchen object kitchen
- 3:26:09object then when the player interacts
- 3:26:11with it by the way we can get rid of
- 3:26:13these debug transforms debug logs we no
- 3:26:15long need them
- 3:26:16okay so when the player interacts so if
- 3:26:18the kitchen object is null if so then
- 3:26:21we're going to spawn it then when we
- 3:26:23spawn it let's assign it so this one
- 3:26:25equals the kitchen object get component
- 3:26:27of type kitchen object okay so if that
- 3:26:30one is no we spawn it and we assign it
- 3:26:33and just with this we should have fixed
- 3:26:34the issue where we can spawn infinite
- 3:26:36objects so over here I can interact and
- 3:26:39I interact a bunch more times and I look
- 3:26:42in the hierarchy inside the clear
- 3:26:44counter and I go inside the counter top
- 3:26:46Point nope there's only one tomato okay
- 3:26:48great so with this basically we made the
- 3:26:50clear counter know if there's something
- 3:26:52on top of it now let's do the other side
- 3:26:55so let's go into the kitchen object and
- 3:26:57make sure that it knows where it is so
- 3:26:59over here on the kitchen object script
- 3:27:01let's set a simple field for a counter
- 3:27:03so private of type clear counter for the
- 3:27:06clear
- 3:27:07counter and now let's just basically
- 3:27:09make two functions one to set it and
- 3:27:10when to get it so a public void set
- 3:27:12clear counter
- 3:27:18and we're going to receive a parameter
- 3:27:20of type clear counter okay great and
- 3:27:22then we're going to have a public return
- 3:27:24a clear counter for the get clear
- 3:27:26counter and we're just going to return
- 3:27:29our clear counter and on this one just
- 3:27:31set this do clear counter equals this
- 3:27:33clear counter all right so on this
- 3:27:35function we're assigning this field and
- 3:27:36on this function we're returning this
- 3:27:38field so now back on the counter script
- 3:27:41we get the kitchen object reference so
- 3:27:43on this one let's call set clear counter
- 3:27:45and pass in the this one and if it is
- 3:27:47not null so if there's something on top
- 3:27:49of this let's just do a debug.log let's
- 3:27:52go onto the kitchen object and get the
- 3:27:54clear
- 3:27:55counter so we should be able to click
- 3:27:57once and spawn an object and click twice
- 3:27:59and the second time we should be able to
- 3:28:01see the name of this clear counter all
- 3:28:03right so over here let's approach and
- 3:28:05click and yep it's spawn now click again
- 3:28:08and yep we've got the message this one
- 3:28:09is on the clear counter okay great so
- 3:28:12far so good so the counter knows if
- 3:28:15there's a kitchen object object on top
- 3:28:16of it and the kitchen object itself
- 3:28:18knows where it is now let's set some
- 3:28:20logic to be able to change a parent
- 3:28:22counter so over here on the clear
- 3:28:24counter script we basically just need to
- 3:28:26call the set clear counter function with
- 3:28:29a different counter reference so just
- 3:28:31for testing let's add a serialized field
- 3:28:33for the second counter so clear counter
- 3:28:35for the second clear
- 3:28:38counter now we're doing this just for
- 3:28:40testing just make sure the logic Works
- 3:28:41before we come up with a more General
- 3:28:43system so just for testing let's come up
- 3:28:45with with some input and again for
- 3:28:47testing using the Legacy input manager
- 3:28:49to get something quickly up and running
- 3:28:51is a great thing so let's quickly get a
- 3:28:53button input on the counter so let's
- 3:28:55make a private void update and for
- 3:28:57testing we only want the testing to work
- 3:28:59on one counter so let's also add up here
- 3:29:02just say B testing and then on update if
- 3:29:06we are testing and we have the input.
- 3:29:09get key down on let's say the T key so
- 3:29:13if you have that then we can run some
- 3:29:14kind of testing code so let's say for
- 3:29:16example if the kitchen object is not
- 3:29:18null so if we have something on top of
- 3:29:20this kitchen counter let's go into the
- 3:29:22kitchen object and call set counter and
- 3:29:25let's pass in the second clear
- 3:29:27counter so basically with this we should
- 3:29:30be able to interact to spawn an object
- 3:29:32and then press the T key and we should
- 3:29:34be able to see that object be set to a
- 3:29:36different parent so here in the editor
- 3:29:38let's just set that let's say this one
- 3:29:40is our main counter so let's drag a
- 3:29:42reference to the second one the second
- 3:29:43clear counter drag it and make this one
- 3:29:45the testing SC s and also just to verify
- 3:29:47that it worked over here let you a get
- 3:29:49on the clear counter all right so let's
- 3:29:52test and see okay so here we are let's
- 3:29:54approach this one interact and there you
- 3:29:56go spawn tomato and now if I interact
- 3:29:58again yep it says tomato is on this
- 3:30:00clear counter now if I press the testing
- 3:30:02key yep there you go the Tomato was
- 3:30:04moved onto the other counter okay so the
- 3:30:07parent changed the logic worked however
- 3:30:09obviously we have two big issues the
- 3:30:11first one is just the visual you can see
- 3:30:13the object is still placed on top of
- 3:30:14this counter even though techly now it
- 3:30:16belongs to this one and the second issue
- 3:30:18is that this counter still thinks that
- 3:30:20it owns this kitchen object and this
- 3:30:22other counter does not know that it now
- 3:30:24owns this object so we need to sort all
- 3:30:26of that first for the visual it's
- 3:30:28actually very simple here when spawning
- 3:30:31we are spawning it inside the counter
- 3:30:32top point and then setting the Lo
- 3:30:34position to zero so whenever we move to
- 3:30:37a different second parent when we do
- 3:30:39that we can just ask that second parent
- 3:30:41to return the counter top point and move
- 3:30:42it there so for that let's make a
- 3:30:44function to return that
- 3:30:46so public we're going to return
- 3:30:48transform so get the kitchen object
- 3:30:50follow transform so this going to be our
- 3:30:53counter top point so let's return the
- 3:30:56counter top
- 3:30:57point then let's go into the function on
- 3:31:00the kitchen object when we set the clear
- 3:31:01counter so over here on the kitchen
- 3:31:03object on this function so we set the
- 3:31:05clear counter then let's modify this
- 3:31:07transform. parent go into the new clear
- 3:31:10counter in order to get the kitchen
- 3:31:12object follow transform and again let's
- 3:31:14make sure to set the local position
- 3:31:15position back into Vector
- 3:31:183.0 okay so with this when we set the
- 3:31:20clear counter to a different one it
- 3:31:22should automatically teleport to the
- 3:31:24other counter so let's test so here we
- 3:31:26are and first let's interact with this
- 3:31:28one there you go it's spawn now if I
- 3:31:29press the testing key and if there you
- 3:31:30go it does move visually okay great so
- 3:31:32far so good however the counter still
- 3:31:34have the wrong data by the way here's a
- 3:31:37quick in tip on the inspector you
- 3:31:40already know that you can only see the
- 3:31:41public and the serialized Fields however
- 3:31:44there is actually a way to look at
- 3:31:45private fields on the inspector on the
- 3:31:48top right there's these three dots and
- 3:31:49if you click on it over here you can
- 3:31:51modify it into a debug inspector and
- 3:31:54when you go into this one Yep this one
- 3:31:55does show all the private Fields so you
- 3:31:58can see for example on the clear counter
- 3:31:59so that's the right one this one over
- 3:32:01here the kitchen object is indeed
- 3:32:02assigned and we can go into the other
- 3:32:04one and we can see this one has it as
- 3:32:06null so debug inspector is really useful
- 3:32:08in these kinds of cases if you want to
- 3:32:10inspect any kind of private Fields you
- 3:32:11can go to this and see it now let's swap
- 3:32:14back into the regular inspector
- 3:32:16and let's fix that issue by notifying
- 3:32:18the counters that the object is changed
- 3:32:20so over here basically we have two
- 3:32:22options over here on the clear counter
- 3:32:25when we modify the parent when we tell
- 3:32:26the kitchen object to go to a new parent
- 3:32:29when we do that we can make the new
- 3:32:30parent responsible to updating itself or
- 3:32:33we can just make the kitchen object
- 3:32:34itself be the one responsible for
- 3:32:36notifying the new parent both approaches
- 3:32:39can work personally I think it makes
- 3:32:41more sense for the kitchen object to
- 3:32:42handle itself so we just call this
- 3:32:45function to set set the new parent and
- 3:32:47what this happens basically this kitchen
- 3:32:48object needs to tell the old parent that
- 3:32:51it is no longer there and needs to tell
- 3:32:53the new parent that it is on there so on
- 3:32:55the counter let's make some function to
- 3:32:56set and get a kitchen object so over
- 3:32:59here on the clear counter script let's
- 3:33:01go down let's make first one to set so
- 3:33:04polling void set kitchen object and
- 3:33:07receive a kitchen
- 3:33:09object and just do this. kitchen object
- 3:33:12equals this kitchen object okay great
- 3:33:15then let's make a getter so P return a
- 3:33:17kitchen object get the kitchen object
- 3:33:20and just return this kitchen object okay
- 3:33:23then let's also make one just to clear
- 3:33:25it so public void clear kitchen
- 3:33:29object and this one just sets a kitchen
- 3:33:32object into
- 3:33:33null and finally just a nice simple
- 3:33:35function to test if this counter has
- 3:33:37anything on top so just a public bow has
- 3:33:40kitchen
- 3:33:41object and over here we just return if
- 3:33:43the kitchen object is not n
- 3:33:46okay so some four very simple functions
- 3:33:49now if we go into our kitchen object
- 3:33:51script over here when we tell it to
- 3:33:53change the parent let's first go into
- 3:33:55the current parent and clear
- 3:33:57it so let's first of all do a quick test
- 3:34:00for null so if this not clear counter
- 3:34:02which is the current parent so if this
- 3:34:04one is not null then we go into the
- 3:34:06current parent so the clear counter and
- 3:34:09we tell it to clear the kitchen object
- 3:34:12and then we go into the new parent and
- 3:34:14we tell new parent to set the kitchen
- 3:34:16object and the kitchen object is this
- 3:34:18one now here be very very important
- 3:34:21don't make the mistake of clearing the
- 3:34:22wrong counter keep in mind that over
- 3:34:25here this not clear counter this refers
- 3:34:27to the previous clear counter whereas
- 3:34:29the one in the parameter this is the one
- 3:34:31this is the new one so make sure you
- 3:34:33clear the kitchen object from the
- 3:34:35previous clear counter before you assign
- 3:34:37it and then you set it on the new clear
- 3:34:39counter so be very very careful here
- 3:34:42make sure you don't make mistakes
- 3:34:43between the quote unquote old clear
- 3:34:45counter and the new clear counter okay
- 3:34:48so that's it basically we have this
- 3:34:49function to set the new clear counter so
- 3:34:51set the new parent we clear the kitchen
- 3:34:53object from the old clear counter we add
- 3:34:55it to the new one and we update the
- 3:34:57visual now we can also add some nice
- 3:34:59safety checks here just to make sure we
- 3:35:00never make a mistake the kitchen object
- 3:35:03should never be set to a parent that is
- 3:35:05already holding something so before we
- 3:35:07set the kitchen object before we do that
- 3:35:09let's make sure that one is empty so
- 3:35:12over here just do an if if the clear
- 3:35:14counter so that's a new one if this one
- 3:35:16has a kitchen object then it already has
- 3:35:18something on there this should never
- 3:35:20ever happen so let's do a debug.log
- 3:35:23error and say counter already has a
- 3:35:26kitchen
- 3:35:27object we're going to eventually ADD
- 3:35:29test to make sure that this never ever
- 3:35:31happens but having the error here will
- 3:35:33be helpful just in case we miss
- 3:35:35something so if it has a kitchen object
- 3:35:37we're going to fire an error but this
- 3:35:38should never happen so we just set the
- 3:35:40error update Visual and so on okay so
- 3:35:43finally let's just go over here into the
- 3:35:45clear counter script and down here we
- 3:35:47have the interact action so we insen the
- 3:35:50kitchen object we're currently
- 3:35:52repositioning it and then we're setting
- 3:35:54this field assigning it to this one now
- 3:35:56we made the kitchen object responsible
- 3:35:58for doing all that for modifying the
- 3:36:00position and for setting the field so we
- 3:36:01don't need to do this instead we really
- 3:36:04just need to go and get the component of
- 3:36:06that and just pass in set player counter
- 3:36:09and pass in as this one so we no longer
- 3:36:13need all of this now our code is much
- 3:36:14more simple also importantly up here we
- 3:36:17were previously setting the clear
- 3:36:18counter and then doing a debug on log
- 3:36:20but when we set it to the new one that
- 3:36:22is actually going to clear this field so
- 3:36:23if we leave this then this is going to
- 3:36:25throw a null reference exception so
- 3:36:27let's just get rid of this log here we
- 3:36:28no longer need it okay so let's test and
- 3:36:31see if all of our logic is working all
- 3:36:33right so here we are let's go to this
- 3:36:35one interact spond it okay great and
- 3:36:38once again we can look in the debug
- 3:36:40inspector so let's put it on debug look
- 3:36:42at this clear counter so that's the
- 3:36:43right one and yep there you go it does
- 3:36:44have the kitchen object and if we look
- 3:36:46in the other one Yep this one has null
- 3:36:48okay great now if I press the testing
- 3:36:50key yep visually it did change and if we
- 3:36:53look at the counter so if we look at the
- 3:36:54old one so that's the right one this one
- 3:36:56is at null okay that's great correct and
- 3:36:58if we look at the new one Yep this one
- 3:37:00does have the reference all right
- 3:37:02awesome so now that we are correctly
- 3:37:04changing the kitchen object parent for
- 3:37:06example we can now interact again with
- 3:37:08this one and yep it does spawn a brand
- 3:37:09new one and of course if we try moving
- 3:37:11it to the other one then we should have
- 3:37:13our error as intended this one is
- 3:37:16currently already occupied with catchen
- 3:37:17object so we should not be able to drop
- 3:37:19something on there but if I press the
- 3:37:21testing key yep there you go nice ER
- 3:37:22okay so that's great we're basically
- 3:37:24going to fix this era later on when we
- 3:37:26had checks to make sure the object can
- 3:37:28only be spawned when it can be spawned
- 3:37:30but for now all of our basic logic is
- 3:37:31working we can spawn an object and
- 3:37:33change the parent all right so with that
- 3:37:35here we have added a really important
- 3:37:37feature to our game that is the ability
- 3:37:39to know where a kitchen object is now
- 3:37:41the next step is to enable the player to
- 3:37:43be able to pick it up and drop it
- 3:37:45somewhere so let's do that in the next
- 3:37:48lecture hello and welcome I'm your Cod
- 3:37:50monkey in this lecture we're going to
- 3:37:52enable the player to pick up a kitchen
- 3:37:54object and in doing so we're going to
- 3:37:56learn about another awesome C feature
- 3:37:58called
- 3:37:59interfaces okay so right now with our
- 3:38:01game I can already move the player I can
- 3:38:02approach a counter interact with it to
- 3:38:04spawn an object and with a testing key I
- 3:38:06can move it to a different parent so all
- 3:38:09that logic is working now let's make it
- 3:38:10work actually with the player let's say
- 3:38:13when we interact once we want to spawn
- 3:38:15it and if there's an object already on
- 3:38:17top of it and I interact again then I
- 3:38:18want to give it to the player okay so
- 3:38:21here on the clear counter script we've
- 3:38:23got our interact function and in order
- 3:38:24to make that work we need to have a
- 3:38:26reference to the player so I just pass
- 3:38:28it in over here as an argument for our
- 3:38:30interaction so just pass in the player
- 3:38:32reference now over here let's do the
- 3:38:34logic that I said so if the kitchen
- 3:38:36object is null so if there's nothing
- 3:38:38here then let's spawn it okay great but
- 3:38:40if there is
- 3:38:41something then let's give the object to
- 3:38:44the player
- 3:38:46so how we change the object parent is
- 3:38:47just like what we did up here so let's
- 3:38:50go into that one set the clear counter
- 3:38:51and pass in the player reference except
- 3:38:53of course this obviously does not work
- 3:38:56the parameter on this function is
- 3:38:58supposed to be of clear counter it does
- 3:38:59not work with the type of player
- 3:39:02basically on the logic that we built for
- 3:39:03setting the parent and change the parent
- 3:39:05this whole thing only works with a
- 3:39:07counter so it does not work with any
- 3:39:09other type so we cannot set the player
- 3:39:10as a parent now to solve this problem is
- 3:39:13exactly where C interfaces come in
- 3:39:16again I have a video going through them
- 3:39:17in detail definitely watch it to learn
- 3:39:19everything about interfaces basically
- 3:39:21what it is is a contract you define some
- 3:39:24functions in the interface and then any
- 3:39:26type can Implement that interface and
- 3:39:28you can write some code that works with
- 3:39:30the interface which in turn means that
- 3:39:31the code won't work with any type as
- 3:39:33long as it implements that interface so
- 3:39:36in this specific example we're going to
- 3:39:37make an interface to represent a kitchen
- 3:39:40object parent then we're going to
- 3:39:41implement that interface on both the
- 3:39:43counter and the player and that way both
- 3:39:45of them won't be able to be parents of a
- 3:39:47kitchen object so let's do exactly that
- 3:39:49now the first thing we do to Define an
- 3:39:51interface is Let's Make A C script so
- 3:39:53let's right click create new C script
- 3:39:56and now the standard is to start
- 3:39:57interface names with the capital I and
- 3:39:59then the name so in this case let's name
- 3:40:01it I kitchen object
- 3:40:04parent and let's open it okay so now to
- 3:40:08make an interface first of all this does
- 3:40:10not extend mon Behavior nope and
- 3:40:13secondly this is not a class instead
- 3:40:15this is an interface now like I said an
- 3:40:18interface is essentially a contract
- 3:40:19where each class that implements that
- 3:40:21interface must follow that contract what
- 3:40:24that really means that you can define a
- 3:40:25bunch of functions here by the way quick
- 3:40:28note you can also define properties but
- 3:40:29not Fields I cover all of that in the
- 3:40:31dedicated interface video but for now
- 3:40:34here we just want some functions like
- 3:40:36for example let's just put all of the
- 3:40:37parent functions that we made previously
- 3:40:39on the counter so over here on the clear
- 3:40:41counter a while ago we made all these
- 3:40:43functions that we needed to make it work
- 3:40:45as a kitchen object parent so we got the
- 3:40:48transform set kitchen object get it
- 3:40:49clear it and has it so let's just copy
- 3:40:51all of this and paste it over here on
- 3:40:53the interface however one important note
- 3:40:55is on the interfaces you don't actually
- 3:40:57include any function
- 3:40:59implementation the implementation is up
- 3:41:01to the class that implements this
- 3:41:02interface although again I should also
- 3:41:04point out another quick note as of c 7
- 3:41:06you can include a default implementation
- 3:41:08but that's for more advanced use cases
- 3:41:11so for here let's just use the basic and
- 3:41:12not apply any default implementation
- 3:41:15right here here so we just Define the
- 3:41:17function and put a semicolon so just
- 3:41:19like this just a function definition
- 3:41:22with the exact signature so just like
- 3:41:24this okay so now that we have defined
- 3:41:26our interface and all the functions that
- 3:41:28we want to have with this now let's go
- 3:41:31onto the counter script so over here on
- 3:41:33the clear counter script over here let's
- 3:41:35implement the interface and the way we
- 3:41:37do that is pretty much exactly the same
- 3:41:38as by extending class so over here we
- 3:41:41are already extending mod Behavior then
- 3:41:43let's set a common and let's say we are
- 3:41:45also implementing the IIT object parent
- 3:41:48interface so right now you might be
- 3:41:50wondering so this is pretty much the
- 3:41:51same thing as extending a base class and
- 3:41:54kind of except for one huge difference
- 3:41:57when extending a base class you can only
- 3:41:59have a single Base Class like for
- 3:42:02example over here we have monob Behavior
- 3:42:04you cannot extend multiple base classes
- 3:42:06there can only be one however when it
- 3:42:08comes to interfaces you can Implement as
- 3:42:10many interfaces as you want so over here
- 3:42:13we have defined our interface and right
- 3:42:15now we don't even have any errors that's
- 3:42:17because we already implemented pretty
- 3:42:19much all the exact functions also Visual
- 3:42:21Studio has a really nice Sile icon over
- 3:42:23here on the left side it is basically
- 3:42:25saying that this function this
- 3:42:26implementation is based on the interface
- 3:42:29but let's see what happens if I decide
- 3:42:30to comment out these functions so if I
- 3:42:33comment out all of this and if there we
- 3:42:35go over here we have an error it is
- 3:42:37telling us that this class does not
- 3:42:39implement the members for the interface
- 3:42:42like I said an interface is like a
- 3:42:43contract so you must write all of the
- 3:42:46functions included in the interface so
- 3:42:48we must Implement these so let's get rid
- 3:42:50of the commments okay with this our
- 3:42:53interface is perfectly working over here
- 3:42:54on the clear
- 3:42:55counter now let's just go into the
- 3:42:58kitchen object over here on this script
- 3:43:00for now we're still working with the
- 3:43:02type clear counter so let's just
- 3:43:04refactor this to instead of working with
- 3:43:06a clear counter let's make it work with
- 3:43:07a kitchen object parent so let's just
- 3:43:10change this from type that to Kitchen
- 3:43:12object parent let's also rename this so
- 3:43:14let's let's Us control RR for the
- 3:43:16kitchen object
- 3:43:18parent then we got a function to return
- 3:43:20the kitchen object okay that's good for
- 3:43:22this one instead of set clear counter
- 3:43:23let's once again rename this to set
- 3:43:26kitchen object parent and inside again
- 3:43:29we receive of type I kitchen object
- 3:43:33parent then let's also rename the
- 3:43:35parameter to Kitchen object parent okay
- 3:43:39so all the names here I have changed
- 3:43:40okay they're all correct we set it we
- 3:43:42assign it over here instead of counter
- 3:43:44let let's say kitchen object parent
- 3:43:46already has that so just like this and
- 3:43:49finally down here let's return I kitchen
- 3:43:52object parent and rename this to get
- 3:43:55kitchen object parent and we return that
- 3:43:59all right so we have changed everything
- 3:44:00I can even do control F to search for
- 3:44:02counter and nope there's no instance of
- 3:44:04any counter so all of this code has now
- 3:44:06been Rewritten to work with a kitchen
- 3:44:08object parent so like this everything
- 3:44:10should be working exactly the same as
- 3:44:12previously we have no errors here and
- 3:44:14over here on the clear counter we just
- 3:44:16have this error on the player let's fix
- 3:44:17this in a little bit for now let's just
- 3:44:19comment it let's just test it out to see
- 3:44:21if everything still works exactly the
- 3:44:22same as previously also one final thing
- 3:44:25since we modify the interact function
- 3:44:27over here on the player class when we
- 3:44:28have the interact we just need to pass
- 3:44:30in this reference okay so let's test all
- 3:44:33right so here we are let's approach this
- 3:44:35one interact yep there it is now let me
- 3:44:38press the testing key and Y there you go
- 3:44:39it does move okay so everything is still
- 3:44:41working exactly the same as previously
- 3:44:43once again another successful ref
- 3:44:45factoring now here comes the magical
- 3:44:47moment so right now again everything is
- 3:44:49still working exactly the same as
- 3:44:50previously so we can only have counters
- 3:44:52as parents but now let's go over here
- 3:44:54onto the player script and over here
- 3:44:56let's also implement the same interface
- 3:44:58so let's implement the i kitchen object
- 3:45:00parent and again as usual we have our
- 3:45:02error so we need to implement this also
- 3:45:05again Visual Studio is very helpful so
- 3:45:06we can click on the light bulb icon and
- 3:45:09let's say implement the interface and if
- 3:45:12we scroll down here it will
- 3:45:13automatically create all these functions
- 3:45:15so let's just actually Implement them so
- 3:45:18for implementing this interface the code
- 3:45:20is really going to be exactly the same
- 3:45:22so let's go up here into the clear
- 3:45:24counter let's go down find all of these
- 3:45:26functions let's copy them and on the
- 3:45:28player let's paste them down here at the
- 3:45:30bottom so we just need to also pick up
- 3:45:32the kitchen object as well as a
- 3:45:34reference to the top point so over here
- 3:45:36on the clear counter let's just grab
- 3:45:38both those so let's just grab the
- 3:45:41kitchen object so go into the player and
- 3:45:42over here let's add a field for the
- 3:45:44kitchen object and finally let's add
- 3:45:46another one for the counter top point so
- 3:45:48over here a serialized field for the
- 3:45:50counter top Point except obviously the
- 3:45:52player is not a counter so this name
- 3:45:54makes no sense on the player so let's
- 3:45:56just quickly rename this and set call it
- 3:45:58kitchen object hold
- 3:46:00Point okay here we have our new name
- 3:46:03we've got the kitchen object and down
- 3:46:05here all of our functions they're all
- 3:46:06working no errors all right now let's
- 3:46:08just assign this in the
- 3:46:10editor so over here let's just go into
- 3:46:12our player there's the player script and
- 3:46:14requires a reference to the kitchen
- 3:46:16object hold point so for that let's do
- 3:46:19it just like we did for the Counterpoint
- 3:46:20so inside the player let's create an
- 3:46:21empty game object call it the kitchen
- 3:46:24object hold point and now Bas let's just
- 3:46:28position it just slightly in front of
- 3:46:30the player so let's put it on a x of
- 3:46:32zero on a y of 1.3 and on a z of one so
- 3:46:36there you go just ahead that's where the
- 3:46:38player is going to be holding the
- 3:46:39objects finally over here on the player
- 3:46:41let's just rag that
- 3:46:43reference okay so far so good
- 3:46:45also one note here like I mentioned
- 3:46:47previously in order to implement the
- 3:46:48interface it requires you to write the
- 3:46:50function code basically what this means
- 3:46:53is that different objects can implement
- 3:46:54the exact same interface whilst having
- 3:46:56different implementations so for example
- 3:46:59over here on the player when setting the
- 3:47:01kitchen object perhaps over here you
- 3:47:03could play some kind of item grab
- 3:47:05animation or maybe when clearing a
- 3:47:07kitchen object you could do some kind of
- 3:47:09logging the only thing that needs to
- 3:47:11match perfectly is just the function
- 3:47:12signature and the function signature
- 3:47:15that means the return type as well as
- 3:47:16the name and any parameters the
- 3:47:18implementation itself that is up to the
- 3:47:20class that wants to implement that
- 3:47:21interface but in this case we wanted to
- 3:47:24behave pretty much exactly the same way
- 3:47:25so like this it should be working so we
- 3:47:28can now go back here onto the clear
- 3:47:30counter script and okay we have our
- 3:47:32interaction all right great so if
- 3:47:34there's nothing we're going to spawn it
- 3:47:35and if there is something on top of it
- 3:47:37we want to give it to the player so now
- 3:47:39let's go into the kitchen object and
- 3:47:40call the function set kitchen object
- 3:47:42parent and pass in the player reference
- 3:47:44and that's it no errors because again
- 3:47:46this takes a parameter of type kitchen
- 3:47:48object parent and the player does
- 3:47:50implement that interface so that's all
- 3:47:52valid now with this let's test and see
- 3:47:54if our code is working all right so here
- 3:47:56we are and let's interact with this
- 3:47:58counter and there you go the object has
- 3:47:59been spawned and now if I interact again
- 3:48:02yep there you go look that the player
- 3:48:03picked up the object and since our logic
- 3:48:06is using a transform hold Point as the
- 3:48:08parent the player is automatically
- 3:48:10carrying this tomato all right awesome
- 3:48:13so this is really great now over here on
- 3:48:15the counter we no longer need all of
- 3:48:17this testing code we now have the
- 3:48:19ability to actually pick up objects from
- 3:48:21the player so let's get rid of all this
- 3:48:23so we don't need this testing code don't
- 3:48:25need a reference to the second clear
- 3:48:26counter or the testing okay great so
- 3:48:29here you can see the power of interfaces
- 3:48:32by just implementing the interface we
- 3:48:34can now place an item anywhere we want
- 3:48:36and importantly on any type we want so
- 3:48:39the counter can hold a kitchen object
- 3:48:41the player can also hold it we could
- 3:48:43make a dog character and make it hold a
- 3:48:45kitchen object we could make a vehicle
- 3:48:47hold it or anything again interfaces are
- 3:48:50really really awesome one of the best C
- 3:48:52features definitely go ahead pause this
- 3:48:54course for now and watch a dedicated
- 3:48:56video on them you should be very very
- 3:48:58familiar with interfaces they will help
- 3:49:00you in making all kinds of systems and
- 3:49:02games if you want to see a clear example
- 3:49:04of the power of interface you can go
- 3:49:06watch my how to interact with NPC's
- 3:49:08video that video takes advantage of
- 3:49:10interface to make sure that the player
- 3:49:11can interact with any kind of object all
- 3:49:13right so thanks to interface we can now
- 3:49:15change the parent of the kitchen object
- 3:49:17and put it on either a counter or the
- 3:49:19player now in the next lecture let's
- 3:49:21make a proper different counter type
- 3:49:24hello and welcome I'm your Cod Maki in
- 3:49:26this lecture we're going to create a
- 3:49:28different counter type from where we can
- 3:49:30grab some
- 3:49:31ingredients okay so far here we have our
- 3:49:33character working and we have an empty
- 3:49:35counter and by interacting with it we
- 3:49:37can spawn an object but obviously that's
- 3:49:39not the behavior we want in the finnal
- 3:49:41game we want different counter types
- 3:49:43that do different things the clear
- 3:49:44counter should only be used as a place
- 3:49:46for putting down and grabbing objects it
- 3:49:48should not spawn anything so let's build
- 3:49:50a new counter type and for that one
- 3:49:53option is to make a brand new prefab and
- 3:49:55build it on from scratch another option
- 3:49:58is we can duplicate this counter and
- 3:49:59change a bunch of things or there's a
- 3:50:01third option that was added in recent
- 3:50:03Unity versions you can now have what is
- 3:50:06called prefab variance meaning that we
- 3:50:08can have a base counter and then we can
- 3:50:11make variance for all the types so let's
- 3:50:13do exactly that to learn about prefab
- 3:50:15variant now first let's duplicate this
- 3:50:17one just so we don't lose any changes
- 3:50:20let's rename this prefab toore base
- 3:50:23counter now I like to add an underscore
- 3:50:25just so that the base prefab is on top
- 3:50:27since this window is sorted
- 3:50:29alphabetically now let's go inside the
- 3:50:31base counter let's go into the scene
- 3:50:32view so here it is and basically over
- 3:50:35here we only want to have all the things
- 3:50:37that all of the counters will have so
- 3:50:40all the counters will have a boxer all
- 3:50:42with the same shape so that's good they
- 3:50:44will also all have a counter top
- 3:50:47point however for the visual different
- 3:50:49counters will have different visuals so
- 3:50:50let's get rid of this same thing for the
- 3:50:52selected let's get rid of this and on
- 3:50:55the actual object different counters
- 3:50:56will have different scripts so let's
- 3:50:59also get rid of this okay so that's it
- 3:51:01this is the base counter it only has all
- 3:51:04the things that every single counter
- 3:51:06will have so let's go ahead save this
- 3:51:08prefab go back outside and now let's
- 3:51:10right click on the base counter and go
- 3:51:13into create and over here let's scroll
- 3:51:16down and find the prefab variant now
- 3:51:18let's name this the clear counter except
- 3:51:20obviously we can't have two different
- 3:51:22names so let's put this one into backup
- 3:51:25we're going to get rid of this one in a
- 3:51:26little bit so on the variant let's name
- 3:51:28it clear
- 3:51:30counter let's open up this variant and
- 3:51:33now here let's add everything just like
- 3:51:34we had on the old clear counter so since
- 3:51:37it's going to be exact let's actually go
- 3:51:39inside the backup one so here let's just
- 3:51:41copy the visual and the selected so
- 3:51:43let's copy this
- 3:51:45go back inside the clear counter variant
- 3:51:47and over here let's space it so contrl +
- 3:51:49V save there it is the selected and the
- 3:51:52visual finally just script so over here
- 3:51:54let's have the clear counter
- 3:51:56script and now let's just drag the
- 3:51:59references so the kitchen object we're
- 3:52:00actually going to remove this in a
- 3:52:01little bit but for now let's assign it
- 3:52:03the counter top Point Let's drag it and
- 3:52:05on the selected we also need to drag the
- 3:52:07kitchen counter reference okay so here
- 3:52:10is our clear counter as a variant of the
- 3:52:13base counter so let's go ahead save this
- 3:52:15and go back
- 3:52:16outside and now we can finally delete
- 3:52:19the old prefab of the clear counter so
- 3:52:21let's go ahead and delete this and of
- 3:52:23course over here on the scene we've got
- 3:52:25some broken prefabs so let's get rid of
- 3:52:27both these and let's drop the clear
- 3:52:29counter variance so let's drop it place
- 3:52:30it over here so let's put it on X of 0 y
- 3:52:34of 0 and Z of
- 3:52:373.5 okay so that's see clear counter
- 3:52:39let's just put another one to the side
- 3:52:40and perfectly on the side so on an X of
- 3:52:42minus 1.5 okay now we can begin making
- 3:52:45our container counter so for that once
- 3:52:48again let's make a variance so right
- 3:52:50click on the base counter go into create
- 3:52:52and let's create a prefab variant call
- 3:52:55this the container counter and let's go
- 3:52:58inside of it now here first thing we
- 3:53:00need is the visuals so let's go inside
- 3:53:01our assets we've got the prefab visuals
- 3:53:04inside we have the counters visuals and
- 3:53:07let's find the container counters so
- 3:53:08let's drag it inside again for the loc
- 3:53:10comp position make sure it's all in 0 0
- 3:53:120 okay great then we need to make the
- 3:53:15selected so let's duplicate this visual
- 3:53:17let's rename this to
- 3:53:19selected let's go inside on all of these
- 3:53:23then let's modify the material for the
- 3:53:25selected material so let's click on the
- 3:53:26circle icon and select the counter
- 3:53:28select material okay we've got our nice
- 3:53:30little ghost icon and just like we did
- 3:53:33previously let's start with these
- 3:53:34disabled so all these game objects
- 3:53:36disabled so they are hidden and on the
- 3:53:38selected let's make sure the scale is 1%
- 3:53:40bigger so
- 3:53:411.01 also selected this one does not
- 3:53:44need animator so let's get rid of this
- 3:53:46now let's add the selected counter
- 3:53:49Visual and obviously for this one we're
- 3:53:51eventually going to need to refactor it
- 3:53:53to support multiple visual objects as
- 3:53:55you can see this selected has multiple
- 3:53:57but for now just make sure that it works
- 3:53:59let's just drag just the first one okay
- 3:54:01great so our container counter has been
- 3:54:04built the only thing that we need is the
- 3:54:05main logic script so let's do that let's
- 3:54:08go into our script folder let's create a
- 3:54:11brand new C script name it the container
- 3:54:14counter and let's select the main game
- 3:54:17object attach a script and let's open it
- 3:54:20all right so now here let's first think
- 3:54:22what we want for this counter we want
- 3:54:24the player to interact with it and when
- 3:54:26it does we want to spawn an ingredient
- 3:54:28and give it to the player so that means
- 3:54:30that we're going to want pretty much the
- 3:54:31exact same behavior that we made over
- 3:54:33here on the clear counter so when the
- 3:54:35player interacts we spawn and we give it
- 3:54:37to the player so let's actually copy all
- 3:54:39of this code let's go into the Container
- 3:54:41counter and over here let's paste this
- 3:54:44we just need to grab the references to
- 3:54:46the kitchen object and the kitchen
- 3:54:47object so so again just like we did on
- 3:54:49the container counter let's copy all
- 3:54:51these references and over here let's
- 3:54:54paste all of them and of course here we
- 3:54:56have an error in order for this to work
- 3:54:58this needs to implement our interface so
- 3:55:00let's do exactly that so let's implement
- 3:55:01the I catchen object parent and back in
- 3:55:04the clear counter let's just copy the
- 3:55:06exact same code so all of these
- 3:55:07functions let's just copy them and on
- 3:55:09the container counter just paste them
- 3:55:11okay great so we don't have any more
- 3:55:13errors here so everything should work we
- 3:55:16should be able to interact with the
- 3:55:17container counter and we should be able
- 3:55:19to see an object being spawned on top of
- 3:55:21it over here in the editor let's just
- 3:55:23make sure to assign it so let's assign a
- 3:55:25default kitchen object so let's say
- 3:55:27tomato and the counter top Point Let's
- 3:55:29drag the reference and okay everything
- 3:55:31else should be working so over here on
- 3:55:33the selected we've got the visual game
- 3:55:35object on the container counter we've
- 3:55:36got this okay great so let's go outside
- 3:55:38into scene View and over here let's just
- 3:55:41Place some container counters so let's
- 3:55:43drag one up there
- 3:55:45let's place it on an X of 1.5 on a y of
- 3:55:47zero and Zed of 3.5 and let's also Place
- 3:55:50another one down here so let's rotate it
- 3:55:53to face it
- 3:55:54upwards okay so on position 0 0 - 5 okay
- 3:55:58great and let's make them spawn
- 3:56:00different things so on this one up here
- 3:56:03let's actually spawn a cheese block and
- 3:56:05on this one down here let's spawn a
- 3:56:06tomato so let's also modify the icon
- 3:56:08here so from cheese block and let's put
- 3:56:11a tomato icon so here it is
- 3:56:14okay we've got two counters and two
- 3:56:16clear counters so let's test so here we
- 3:56:18are and if I approach a container
- 3:56:20counter and I press the interact button
- 3:56:22and nope nothing happened we cannot
- 3:56:24interact with it at all even the
- 3:56:26selection visual even that one is broken
- 3:56:28so as I approach nope the visual is not
- 3:56:30showing up now the reason for this is
- 3:56:33actually pretty obvious if we go over
- 3:56:35here on the player script down here when
- 3:56:38we're handling our interactions so let's
- 3:56:40go into the handle interactions function
- 3:56:42over here we are doing a rate recast and
- 3:56:44we are trying to get component of type
- 3:56:46clear counter so basically we're not
- 3:56:48doing anything if that object has a
- 3:56:50container counter instead of a clear
- 3:56:52counter so again we have a similar issue
- 3:56:55to the one that we had in the object
- 3:56:56parent logic basically we have two types
- 3:56:59a clear counter and a container counter
- 3:57:01and we want the player to be able to
- 3:57:03interact with both them so as a solution
- 3:57:05for this exact same problem we could
- 3:57:07also Implement an interface just like we
- 3:57:09did that would work that would enable
- 3:57:11the player to interact with multiple
- 3:57:13counters but in this case since the
- 3:57:15counters are all very similar very
- 3:57:16related objects they're all going to be
- 3:57:19kitchen counters as opposed to object
- 3:57:20parents where the player and ENC counter
- 3:57:22are completely different in this case
- 3:57:24since they are all very similar a better
- 3:57:26approach is actually to use inheritance
- 3:57:28now here I should point out that
- 3:57:30inheritance is one of those things that
- 3:57:31is simultaneously very powerful but also
- 3:57:33very dangerous usually beginners get
- 3:57:36really excited when they first hear
- 3:57:37about inheritance but after gaining some
- 3:57:39experience they start to see the massive
- 3:57:41downsides one funny joke about it is
- 3:57:43let's say you want to write some code
- 3:57:45that all it needs is a Banana class but
- 3:57:47because of messy inheritance you end up
- 3:57:49with a monkey and the entire jungle
- 3:57:50behind it basically the banana extends a
- 3:57:53monkey which extends a tree which
- 3:57:54extends a jungle and so on so you just
- 3:57:56want a small thing but because of a
- 3:57:58complex inheritance you end up picking
- 3:58:00up a huge object so all that to say
- 3:58:02inheritance is something you must use
- 3:58:03very very carefully it's a powerful tool
- 3:58:06definitely but you need to make sure to
- 3:58:08absolutely use it in the right approach
- 3:58:10for the problem you're trying to solve
- 3:58:12now in this case like I said since all
- 3:58:13of the counters are going to be very
- 3:58:15closely related in this case it does
- 3:58:17make sense and of course in the future
- 3:58:19if that does change we can always
- 3:58:21refactor if you're a beginner definitely
- 3:58:23go ahead and research a bit more on C
- 3:58:26inheritance the pros and cons I don't
- 3:58:28have any dedicated video on that topic
- 3:58:30myself but if you search I'm sure you'll
- 3:58:32find tons of content again it's a very
- 3:58:34powerful but also very dangerous tool so
- 3:58:36definitely use it wisely over here let's
- 3:58:39make sure we're wise so let's use it
- 3:58:42first thing we need to do is Define the
- 3:58:43base counter class so let's create a new
- 3:58:45C script let's call it the base
- 3:58:49counter so over here on the script let's
- 3:58:51get rid of the functions we don't want
- 3:58:52any default functions and let's also
- 3:58:54make sure that we do extend mono
- 3:58:57Behavior we do want that we still want
- 3:58:58to use this as a component so let's
- 3:59:01leave the script just like this let's
- 3:59:02save it then let's go over here into the
- 3:59:05clear counter script and on this one
- 3:59:08instead of extending mon behavior let's
- 3:59:09extend the base counter okay that's it
- 3:59:12that's the only change and now let's go
- 3:59:14into the Container counter and over here
- 3:59:15same thing let's extend the base counter
- 3:59:17instead of mon Behavior so now both
- 3:59:19these counters extend the exact same
- 3:59:21base counter script so now if we go into
- 3:59:24the player script so here we are on the
- 3:59:25player script and on the handle
- 3:59:27interactions function over here instead
- 3:59:29of trying to get a component of type
- 3:59:31clear counter let's try to get the
- 3:59:33component of type base counter so let's
- 3:59:35also rename this so control RR to rename
- 3:59:38rename this to base counter and of
- 3:59:41course we need to rename all these
- 3:59:42references that expect a clear counter
- 3:59:44instead of a base counter so over here
- 3:59:46for the selected counter let's modify
- 3:59:47the type to base counter then also up
- 3:59:51here when we've got the event ARS let's
- 3:59:53modify the type okay so over here we
- 3:59:56have the interactor let's leave this for
- 3:59:58a bit let's go down and let's fix this
- 4:00:00issue so let's go down into that
- 4:00:01function to set the selected counter
- 4:00:03instead of this type let's receive a
- 4:00:05base counter okay so all of these errors
- 4:00:08have been solved there's only one left
- 4:00:09and it's this one the interact we see
- 4:00:12this error because obviously the base
- 4:00:13class does not have any kind of interact
- 4:00:15method so let's add
- 4:00:17that now for adding methods to a base
- 4:00:19class actually very simple it's really
- 4:00:21just like any other method so first the
- 4:00:23accessor for the interact we want the
- 4:00:25player to be able to access it so let's
- 4:00:27make it public and also since we're
- 4:00:29talking about inheritance I should
- 4:00:30probably mention the other accessor now
- 4:00:33you already know about public and you
- 4:00:34also already know about private but
- 4:00:36there's another one you might not know
- 4:00:38which is called
- 4:00:39protected basically this one means that
- 4:00:41whatever function we Define with this
- 4:00:43accessor it is going to be accessible to
- 4:00:45this class and any class that extends it
- 4:00:48so for example if we had a function that
- 4:00:50was protected the clear counter could
- 4:00:52call this function because does extend
- 4:00:54this Base Class however the player would
- 4:00:56not be able to call this because it is
- 4:00:58protected now in our case for the
- 4:01:00interact action we do want a player to
- 4:01:02call it so let's make it public just
- 4:01:03like we had previously then another
- 4:01:05keyword for every function that we want
- 4:01:08the child classes to be able to
- 4:01:09implement in their own way we can Define
- 4:01:11it as virtual and finally the functions
- 4:01:14signature as normal so for the interact
- 4:01:16we made a return void call it interact
- 4:01:19and we received a player
- 4:01:23argument okay so that's it that's our
- 4:01:25basic signature for the implementation
- 4:01:28let's leave it empty over here on the
- 4:01:29base counter so by default it's not
- 4:01:31going to do anything in the game design
- 4:01:33that we're building we're never actually
- 4:01:35going to end up with anything like this
- 4:01:37so if we want for safety we can just add
- 4:01:39a debug.log
- 4:01:40error to say just base counter. interact
- 4:01:44because this should never be triggered
- 4:01:46also I should point out for a more
- 4:01:47advanced method instead of making it
- 4:01:50virtual you could make it abstract and
- 4:01:52basically what that does is that forces
- 4:01:54of the classes to implement their own
- 4:01:57implementation so you would make this
- 4:01:59abstract and just put it just like this
- 4:02:01as if this were an interface but in
- 4:02:04doing so you would also need to define
- 4:02:05the base counter as abstract and so on
- 4:02:07so obiously this is a more advanced
- 4:02:09method so don't worry about it for now
- 4:02:10let's keep it a bit more simple so let's
- 4:02:13make it just virtual void interact okay
- 4:02:16great so we have this let's save this
- 4:02:18and now if we go on the clear
- 4:02:20counter over here on the interact notice
- 4:02:23how we have a green squiggle line
- 4:02:26basically this is a warning it's telling
- 4:02:28us that we are hiding the base function
- 4:02:30now in reality we don't want to hide it
- 4:02:32instead we want to override it so before
- 4:02:35the void before the return type we just
- 4:02:37add the keyword
- 4:02:38override and Yep this will now override
- 4:02:41the base function so when the player in
- 4:02:43interacts with an object of type based
- 4:02:45counter and that object is actually a
- 4:02:46clear counter when the player calls the
- 4:02:48interact function instead of running
- 4:02:50this code it's actually going to run
- 4:02:52this code now let's do the same thing on
- 4:02:54the container counter so over here let's
- 4:02:56also add the keyword override to
- 4:03:00override the base function okay great so
- 4:03:02we have no errors here and on the player
- 4:03:04we also don't have any more errors since
- 4:03:06that one does now implement the interact
- 4:03:08function so with this let's test and
- 4:03:10everything should still be working so
- 4:03:12over here let's approach the counter and
- 4:03:14let's interact with it and yep it does
- 4:03:16work it spawned some cheese and down
- 4:03:17here yep it spawned the tomato and then
- 4:03:20if we go onto the empty counter and
- 4:03:21interact and yep it still works okay so
- 4:03:24here we added the ability to interact
- 4:03:26with two different counter types all
- 4:03:28right great now know how the selected
- 4:03:30logic isn't really working well you can
- 4:03:32see the container counters they are both
- 4:03:34selected even though the player is not
- 4:03:36looking at them and actually if I
- 4:03:39approach it then it actually becomes
- 4:03:40deselected basically the reason for that
- 4:03:42is because these selected script that
- 4:03:44one is still referencing the clear
- 4:03:46counter inside of the base counter so
- 4:03:48right now it's only being selected when
- 4:03:49the selected counter is null so that is
- 4:03:51why as I approach it actually hides
- 4:03:53itself so let's fix this let's go inside
- 4:03:56the container counter prefab and inside
- 4:03:58we've got the selected and yep over
- 4:04:00there we have a reference to that so
- 4:04:01let's open up this script and over here
- 4:04:03all we need to do is just modify this
- 4:04:05type so let's make it of type base
- 4:04:07counter and let's rename this to base
- 4:04:11counter okay that's the only change we
- 4:04:13need
- 4:04:14and by the way since we're here let's
- 4:04:15also fix the other issue the issue we
- 4:04:18had where we need to support more than
- 4:04:20one visual game object so instead of
- 4:04:22having a field of type just game object
- 4:04:24let's receive a game object array so
- 4:04:27let's modify this to game object array
- 4:04:30and then down here on the show hide is
- 4:04:31actually very simple so let's just do a
- 4:04:334 in game object for the visual game
- 4:04:39object in the visual game object array
- 4:04:42we go inside set it to true and on this
- 4:04:45one we set it to
- 4:04:48false okay that's it super simple now
- 4:04:51let's just update the prefabs so first
- 4:04:53over here on the container counter let's
- 4:04:55rag the container counter reference as
- 4:04:57the base counter okay great and for the
- 4:05:00visuals let's just drag all of them so
- 4:05:02let's drag the counter solid drag it on
- 4:05:04top then the counter hole drag it on top
- 4:05:07then the single door drag it and the
- 4:05:09black drag it and also by the way over
- 4:05:11here on this counter this one actually
- 4:05:13has a object Sprite this is the actual
- 4:05:16Sprite in there but for the selected we
- 4:05:18really don't want that so if I enable
- 4:05:20this game object here we've got the
- 4:05:21object Sprite let's actually delete this
- 4:05:24we don't need the actual icon Sprite to
- 4:05:26be highlighted so let's leave it just
- 4:05:27like this so we only have these four
- 4:05:29objects and all four of them are on the
- 4:05:31list okay that's great so all the
- 4:05:33references in here they're all working
- 4:05:35perfectly so let's go back outside let's
- 4:05:37save the prefab let's go inside the
- 4:05:39empty clear counter and on this one same
- 4:05:42thing on the selected let's Drag The
- 4:05:44Insider reference and for the base
- 4:05:46counter let's also drag that
- 4:05:48reference okay so let's go outside save
- 4:05:51it and let's test and now let's see if
- 4:05:53the selected works so as I approach this
- 4:05:55one yep it works yep it works and on
- 4:05:57this one yep it works and down here yep
- 4:05:59it works all right awesome so we can
- 4:06:01interact and we can highlight our
- 4:06:03selection okay everything is working
- 4:06:05great so now that all the code is
- 4:06:07working we can inspect the code to see
- 4:06:09if we can refactor
- 4:06:11anything we can see for example if
- 4:06:13there's any kind of common logic that
- 4:06:14all of the counters share that we should
- 4:06:16probably write in the base counter and
- 4:06:19you can see right away that both the
- 4:06:20clear counter and the container counter
- 4:06:22both of them implement the kitchen
- 4:06:24object parent interface that behavior is
- 4:06:26something that all of the counters won't
- 4:06:28share so instead of defining it on each
- 4:06:30counter itself let's actually do it on
- 4:06:32the base class instead so let's get rid
- 4:06:35of the interface implementation here and
- 4:06:37also on the container counter let's get
- 4:06:39rid of that and said on base counter
- 4:06:41let's Implement that one so I kitchen
- 4:06:43object parent and for the functions
- 4:06:46let's do the same thing so let's cut
- 4:06:48this one from here and let's bace it on
- 4:06:50the base counter it's okay now we need
- 4:06:53these two points so let's go ahead copy
- 4:06:55all of this let's go into the base
- 4:06:57counter paste it except for the base one
- 4:07:00doesn't need a kitchen object as so so
- 4:07:01just the counter top point and the
- 4:07:03kitchen object okay so there are no
- 4:07:05errors on this one let's go into the
- 4:07:07Container let's get rid of the kitchen
- 4:07:09object and the counter top Point okay
- 4:07:11great now we see an error but before we
- 4:07:13worry about that let's actually go into
- 4:07:15the clear counter and let's do the same
- 4:07:16thing so let's get rid of this get rid
- 4:07:18of this and down here get rid of all
- 4:07:20these
- 4:07:21functions okay so now the counter
- 4:07:23scripts are much much more simple all of
- 4:07:26the common code is now written directly
- 4:07:27on the base counter now for solving this
- 4:07:31the container counter needs to know if
- 4:07:32there's a kitchen object on top of it so
- 4:07:35now here we have an interesting question
- 4:07:37with two possible
- 4:07:38approaches basically we need access to
- 4:07:40this object so one approach would be to
- 4:07:43make this protected like I said
- 4:07:45protected means that any classes that
- 4:07:47extend this base counter class any of
- 4:07:50those classes can then modify that field
- 4:07:52so like this yep there is no more errors
- 4:07:54that's one approach and the other
- 4:07:56approach is to instead keep this one as
- 4:07:58private and whenever we want to interact
- 4:08:01with it we simply interact through these
- 4:08:02functions both approaches can work and
- 4:08:05when in doubt as usual you should
- 4:08:07probably go with the more limited option
- 4:08:09so let's leave it as private and work
- 4:08:11with these functions instead over here
- 4:08:13here on the container counter instead of
- 4:08:14testing if the kitchen object is null
- 4:08:16let's just test has kitchen object so if
- 4:08:19it does not have a kitchen object then
- 4:08:21we're going to spawn it and for spawning
- 4:08:23over here we could grab the actual
- 4:08:25transform follow so this one up here we
- 4:08:28could call this function to get it or
- 4:08:30since that is actually going to be
- 4:08:31handled automatically when we call this
- 4:08:33function to set the parent then let's
- 4:08:34actually not use this at
- 4:08:36all so we just spawn it and set the
- 4:08:39kitchen object parent okay great so now
- 4:08:41let's just look at the clear counter for
- 4:08:44this one like I said it's not really
- 4:08:45meant to spawn anything so let's
- 4:08:47actually remove all of this
- 4:08:49code this one is only going to serve to
- 4:08:51pick up and drop items we're going to
- 4:08:53handle that in the next lecture but for
- 4:08:55now let's just go back into the
- 4:08:56Container counter and let's do the
- 4:08:59proper logic that I mentioned in the
- 4:09:00beginning basically on this one we want
- 4:09:02to spawn the object and we want to
- 4:09:04immediately give it to the player so
- 4:09:06when we call set kitchen object parent
- 4:09:07instead of passing in this let's pass in
- 4:09:09the player reference and that's really
- 4:09:11it for the container counter this is all
- 4:09:13we're going to do so the player
- 4:09:14interacts and it spawns an object and
- 4:09:16gives it to the player okay so that's it
- 4:09:19with this as you can see the code for
- 4:09:21all of our counters is much much more
- 4:09:23simplified so basically it only handles
- 4:09:25the logic related to that specific
- 4:09:27counter everything else is on the base
- 4:09:28counter so let's test this so here we
- 4:09:32are and if I approach the counter
- 4:09:33interact and yep there you go spawn some
- 4:09:35cheese and gave it to the player okay
- 4:09:37great now just for fun when I made these
- 4:09:40assets I actually included a nice
- 4:09:41animation so if you go inside the
- 4:09:44container counter over here on the
- 4:09:45visual note how this already has an
- 4:09:47animator with an animator control
- 4:09:49attached to it you can double click to
- 4:09:51open it up and over here you can see
- 4:09:53it's very simple basically just has two
- 4:09:55animations one is the container close
- 4:09:57and one is the container opening and
- 4:09:58closing these transitions are basically
- 4:10:01triggered by this parameter this is a
- 4:10:02trigger parameter so when triggers goes
- 4:10:05into the open close and when this one
- 4:10:06ends goes back into close so let's just
- 4:10:09quickly add these nice animations
- 4:10:11however again as usual let's make sure
- 4:10:12to write some good clean code so let's
- 4:10:15not add the visual over here on the
- 4:10:16logic script instead let's make a proper
- 4:10:19new script over here let's create a new
- 4:10:21C
- 4:10:22script call this the container counter
- 4:10:26visual okay now we want to attach this
- 4:10:29only to the visual game object so only
- 4:10:31this one let's attach okay and over here
- 4:10:34the first thing we need is to get the
- 4:10:36animator so let's sort a field for the
- 4:10:38animator and since it's on the exact
- 4:10:40same object we can just make an awake
- 4:10:42and get component of type
- 4:10:45animator and we just assign this field
- 4:10:50okay so with this we have the animator
- 4:10:53now we just need to know when we should
- 4:10:54play the animation so let's go over here
- 4:10:56on the container counter script and
- 4:10:58basically let's make an event that we're
- 4:10:59going to fire when the player grabs an
- 4:11:01object so let's make a public event of
- 4:11:05type let's stick with the standard so
- 4:11:06let's use event handler inside using
- 4:11:08system okay let's name this on player
- 4:11:11grab object
- 4:11:14and then down here when the player
- 4:11:15interacts and gets an object let's fire
- 4:11:17off this event so invoke let's invoke
- 4:11:20with this an event rx.
- 4:11:23empty okay so we are firing off this
- 4:11:26event and over here on the visual first
- 4:11:28we need the field for the container
- 4:11:29counter so let's add it up here let's
- 4:11:31add a serialized field of tripe
- 4:11:33container
- 4:11:36counter okay we have this field now
- 4:11:38let's listen to the event but again
- 4:11:40we're accessing an external reference so
- 4:11:43let's let's make sure to do it on start
- 4:11:44and not on awake so let's go into this
- 4:11:47one and listen to the on player grabed
- 4:11:48object event okay so here we have the
- 4:11:50event and it's over here that we want to
- 4:11:52access the animator and call set trigger
- 4:11:55in order to play the animation again
- 4:11:57when working with animator parameters
- 4:11:58suddenly we do need to use strings
- 4:12:00there's no way around that but at least
- 4:12:02we can make it a bit more clean by
- 4:12:03defining a constant so up here a private
- 4:12:06con string call it open close and let's
- 4:12:09make sure to use the exact same
- 4:12:11parameter name so open close
- 4:12:15and then down here on the set trigger
- 4:12:17let's call this
- 4:12:18trigger okay so that's it some very
- 4:12:20simple Vision logic and now over here
- 4:12:23inside the prefab all we need is to drag
- 4:12:25the container counter reference so let's
- 4:12:27drag it also make sure that it has the
- 4:12:29animator and the animator controller so
- 4:12:31with that everything should already be
- 4:12:32set up so let's go back into the scenes
- 4:12:34save the changes and let's set on play
- 4:12:37so here we are and if I go towards the
- 4:12:39tomato and interact and there you go it
- 4:12:40plays a nice little animation all right
- 4:12:43right awesome okay so here we created a
- 4:12:45brand new counter type and we refactored
- 4:12:48our interact code to be able to interact
- 4:12:50with any counter type the player can
- 4:12:52interact with the container counter to
- 4:12:53pick up an object now the next obvious
- 4:12:56thing that we need is to enable the
- 4:12:57player to drop an object on the clear
- 4:12:59counter so let's do that in the next
- 4:13:02lecture hello and welcome I'm your Cod
- 4:13:04monkey in this lecture we're going to
- 4:13:06enable the player to pick up and drop
- 4:13:08objects okay so we already have the
- 4:13:11player working I can approach this
- 4:13:12container counter interact with it and
- 4:13:14yep the player picks up something now
- 4:13:16that's left is being able to put a clear
- 4:13:18counter and being able to drop this
- 4:13:19object so let's do that let's go over
- 4:13:22here on the clear counter script and
- 4:13:24when we interact with it we're going to
- 4:13:26do a bit of logic first let's just check
- 4:13:28if this counter is empty meaning if
- 4:13:30there's no kitchen object on it so let's
- 4:13:32test if has kitchen object or if not so
- 4:13:36let's say if we don't have a kitchen
- 4:13:38object then there is no kitchen object
- 4:13:42here
- 4:13:43and if not then there is a kitchen
- 4:13:46object
- 4:13:49here okay these are the two valid
- 4:13:52options so if there is nothing here then
- 4:13:55let's check the player itself so we go
- 4:13:57into the player and we can ask the same
- 4:13:59question so has kitchen object so if the
- 4:14:01player is carrying
- 4:14:04something so over here the player is
- 4:14:07carrying
- 4:14:08something if so then basically we just
- 4:14:11want to drop that object from the player
- 4:14:13and drop it in here so that's very
- 4:14:15simple we just go into the player we get
- 4:14:17the kitchen object that the player is
- 4:14:18holding and we just modify the kitchen
- 4:14:21object parent onto this
- 4:14:23object all right so that's it just with
- 4:14:25this it should already be working let's
- 4:14:27do a quick test before we handle the
- 4:14:29rest of the
- 4:14:30interactions okay so here moving the
- 4:14:32player and if I just interact with the
- 4:14:33clear counter and nope nothing happens
- 4:14:35okay great since the player is not
- 4:14:36carrying anything nope nothing happens
- 4:14:38all right great now let's pick up
- 4:14:40something from the container counter
- 4:14:41okay so now the player is carrying a
- 4:14:43tomato approach a clear counter press
- 4:14:45the button and yep there you go there it
- 4:14:46is all right Awesome everything worked
- 4:14:50now this is an excellent point to know
- 4:14:51just how easy this was to implement and
- 4:14:53the reason why it was so easy was
- 4:14:55because we focus hard on writing some
- 4:14:57good clean code for how the object and
- 4:14:59the parent system works because we took
- 4:15:01some time to think about that it was now
- 4:15:03very easy to implement this brand new
- 4:15:05action so this is a very very clear
- 4:15:07example of the power of writing good
- 4:15:09clean code okay so with that now let's
- 4:15:11implement the rest so over here there's
- 4:15:14no kitchen object here and the player's
- 4:15:15carrying something but if not we've got
- 4:15:17the else so player has nothing so if the
- 4:15:22player doesn't have anything so let's
- 4:15:23not do anything so player not carrying
- 4:15:27anything so those are all the possible
- 4:15:29States up there then down here if there
- 4:15:31is a kitchen object on this clear
- 4:15:32counter if so then let's check if the
- 4:15:35player has a kitchen
- 4:15:37object so in this the player is carrying
- 4:15:41something and and if
- 4:15:44not then the player is not carrying
- 4:15:48anything so basically if there is a
- 4:15:50kitchen object here and the player is
- 4:15:51carrying something if so then we don't
- 4:15:53want to do anything since we can't give
- 4:15:54the player two items however if there is
- 4:15:57a kitchen object here and the player is
- 4:15:59not carrying anything then we want to
- 4:16:00give it to the player so let's just get
- 4:16:02the kitchen object the one that is on
- 4:16:04this clear counter and let's do the
- 4:16:07exact same thing so set the parent and
- 4:16:09set the parent off to the player okay so
- 4:16:11that's it as you can see some very
- 4:16:12simple logic so let's test okay here we
- 4:16:15are and if we interact nope nothing
- 4:16:17happens okay great now pick up a tomato
- 4:16:19go there drop it yep there it is now if
- 4:16:21I interact again yep there you go I
- 4:16:22picked it up again so I can go somewhere
- 4:16:24pick it up drop it and everything works
- 4:16:26perfectly all right awesome now the last
- 4:16:30thing that we need to fix is the
- 4:16:31container counter right now it's giving
- 4:16:33out an object every time even if the
- 4:16:35player has something so if I pick up yep
- 4:16:37it works now if I pick up again there
- 4:16:39you go we've got our nice helpful error
- 4:16:41this should never happen so let's set
- 4:16:43some nice checks so over here on the
- 4:16:46container counter okay we have our
- 4:16:47interaction and before we spawn anything
- 4:16:50let's just see if the player can pick up
- 4:16:51something so once again very simple
- 4:16:54let's just go into the player and we
- 4:16:55check does the player have a kitchen
- 4:16:56object if so we're not going to give it
- 4:16:58anything but if the player does not have
- 4:17:00a kitchen object then yep the player
- 4:17:02picks it up and we give it the
- 4:17:10object okay so that's it it's this
- 4:17:12simple Let's test so here we are let's
- 4:17:14pick up some cheese okay great now pick
- 4:17:16up another one and nope nothing happens
- 4:17:18okay great we're already carrying
- 4:17:19something so we cannot drop anything now
- 4:17:21drop it in there now pick up a tomato
- 4:17:23and yep it works I can pick it up drop
- 4:17:25it and yep everything works okay great
- 4:17:28let's just see one more thing over here
- 4:17:30the container counter is spawning the
- 4:17:32object and the object is the one that we
- 4:17:34assigned so over here in scene view
- 4:17:36we've got the container counter this one
- 4:17:39is placed on the scene and we' made an
- 4:17:41override to spawn a cheese block
- 4:17:43technically we could keep doing this
- 4:17:45pretty much just duplicate objects
- 4:17:47modify the Sprite modify over here the
- 4:17:49kitchen object that would work but
- 4:17:51another better approach would be to
- 4:17:53Simply make some prefab variants and yep
- 4:17:55that does work you can make a variant of
- 4:17:57a variant so let's do examply that over
- 4:17:59here on the container counter let's
- 4:18:02right click go into create let's create
- 4:18:03another prefab variant and let's say
- 4:18:06container counter this one will be the
- 4:18:08Tomato now let's go inside the prefab
- 4:18:11and over here make sure it has the an
- 4:18:13object for tomato okay great and over
- 4:18:14there on the Sprite so let's find the
- 4:18:17object Sprite and choose the Tomato
- 4:18:19Sprite so there you go this one okay
- 4:18:22let's exit and save all right now once
- 4:18:25again let's right click on the container
- 4:18:26and let's make it another one this is
- 4:18:29going to be the one for the cheese block
- 4:18:32so let's go inside of it and over here
- 4:18:34modify it for the cheese block and
- 4:18:36inside the actual visual let's modify
- 4:18:38the Sprite and it's actually that one so
- 4:18:40the cheese block okay great let's go
- 4:18:42back outside
- 4:18:43and since we're here doing this let's
- 4:18:45make all of the other grabbable objects
- 4:18:46from the containers so let's first make
- 4:18:49the kitchen object as so so let's go
- 4:18:51over here we can right click go into
- 4:18:53create create a new kitchen object as so
- 4:18:55let's make one for the
- 4:18:57bread then let's duplicate this one
- 4:18:59we're going to have a cabbage and
- 4:19:01finally we're going to have the meat
- 4:19:03Patty
- 4:19:04uncooked all right so now let's make
- 4:19:06sure to assign all the data for all
- 4:19:08these scriptable objects first we need
- 4:19:10to make the actual kitchen object so
- 4:19:12let's duplicate get tomato name this one
- 4:19:14bread let's go inside of it and first
- 4:19:16for the kitchen object as so let's make
- 4:19:18sure to drag the correct one okay
- 4:19:19there's the bread and for the visual
- 4:19:21this one is not a tomato so let's go
- 4:19:24inside our visual assets inside the
- 4:19:26prefab visuals let's pick up the bread
- 4:19:28visual okay there it is that's all we
- 4:19:30need so let's go outside save the
- 4:19:32changes and then select the bread script
- 4:19:34object drag the prefab reference okay
- 4:19:37for the Sprite this is the bread and
- 4:19:39finally just call it bread okay let's do
- 4:19:41the same thing for the other one so next
- 4:19:43up for the Cabbage let's do the Cabbage
- 4:19:45drag the Cabbage script object let's go
- 4:19:48inside and modify the visual so the
- 4:19:50Cabbage
- 4:19:51visual okay that's it then on the
- 4:19:55Cabbage script object drag the reference
- 4:19:57for the prefab let's assign the Sprite
- 4:19:59and finally give it a name
- 4:20:01cabbage and finally the meat Pion cooked
- 4:20:04so let's do that one so let's duplicate
- 4:20:05it name it meat Patty
- 4:20:10uncooked let's go inside modify the
- 4:20:13kitchen objecto for this one and for the
- 4:20:16visual let's select here it is the meat
- 4:20:18Patty
- 4:20:19uncooked okay let's go back outside and
- 4:20:23on the script M object let's just drag
- 4:20:26the prefab assign the Sprites so this
- 4:20:29one is the uncooked so it's this one and
- 4:20:31finally meet Patty uncooked okay great
- 4:20:34so we added all of these script M
- 4:20:36objects we also have the prefabs with
- 4:20:39the visuals and the logic script now
- 4:20:41let's just make the container counter so
- 4:20:42once again let's create another variant
- 4:20:44so prefab variant this one is for let's
- 4:20:47say for the bread then let's make all
- 4:20:50the other ones already so let's go make
- 4:20:52another prefab variant this one is going
- 4:20:55to be for the meat Patty
- 4:20:57uncooked and finally another variant
- 4:21:00also here make sure you're creating a
- 4:21:01variant of the container counter don't
- 4:21:03make an accident of creating a variant
- 4:21:05of something else let's make another
- 4:21:07variant one final one and this one is
- 4:21:09going to be for the cabbage
- 4:21:13okay we have all the variants now let's
- 4:21:14just assign them so let's go inside the
- 4:21:16bread and over there modify the
- 4:21:18scriptable object for the bread and for
- 4:21:20the icon modify for the bread icon okay
- 4:21:23let's go to the Cabbage save the changes
- 4:21:26modify that one for the Cabbage go into
- 4:21:29the icon and modify the icon and finally
- 4:21:32the meat Patty uncooked let's go ahead
- 4:21:34modify this one for that one and the
- 4:21:37icon put it on that one all right
- 4:21:39everything is working now let's just
- 4:21:42place some over here in our scene so
- 4:21:44let's get rid of the ones that we made
- 4:21:45some overrides so let's get rid of that
- 4:21:48container counter and said for that one
- 4:21:50let's drag the cheese block put it right
- 4:21:52in there let's put it on X 1.5 y of z z
- 4:21:56of 3.5 okay then down here for this one
- 4:22:00let's put the Cabbage next to it let's
- 4:22:03rotate it to face upwards so like that
- 4:22:07let's put it on X of - 1.5 y of 0 and- 5
- 4:22:10on the Zed then for tomato let's get rid
- 4:22:13of this one and use the proper tomato
- 4:22:15one so let's rotate it put it on an X of
- 4:22:180 y 0 and - 5 okay next we want some
- 4:22:22bread so let's put the bread up here on
- 4:22:24the left side let's put it on X of minus
- 4:22:273 0o on the Y and 3.5 on the
- 4:22:30Zed and finally the meat Pat and cook
- 4:22:33let's put it over here a bit more on the
- 4:22:34side let's put it over here on X of 7.5
- 4:22:370 and 3.5 all right so we have
- 4:22:40positioned all of them let's just make
- 4:22:42more clear counters so we can actually
- 4:22:44place the objects so let's put this one
- 4:22:46over here on minus 4.5 this one over
- 4:22:48there let's also put some counters let's
- 4:22:51say one on the right side and a bunch
- 4:22:53more down here let's rotate them
- 4:22:57upwards let put this one on 1.5 minus
- 4:23:025 and one more over here on the
- 4:23:05side okay great so we have all of our
- 4:23:07container counters as well as a bunch of
- 4:23:09clear counters so let's test make sure
- 4:23:11that everything works okay so here we
- 4:23:13are let's go down pick up a tomato yep
- 4:23:14there's a tomato now a cabbage yep
- 4:23:16there's a cabbage now some bread there's
- 4:23:18some bread and some cheese there's some
- 4:23:20cheese and some meat and yep there's
- 4:23:22some meat all right Awesome everything
- 4:23:24works so with this over here we added
- 4:23:27the ability to pick up and drop objects
- 4:23:29on an empty container and spawn them
- 4:23:30from all kinds of container counters now
- 4:23:33in the next lecture let's build a
- 4:23:34counter we can interact with in a very
- 4:23:36interesting way hello and welcome I'm
- 4:23:39your Cod Maki in this lecture we're
- 4:23:41going to create a cutting counter so
- 4:23:43this is going to be a counter where we
- 4:23:44can place an object like for example a
- 4:23:46tomato and after doing a secondary
- 4:23:48interaction we can slice it however
- 4:23:50before we do that let's just fix one
- 4:23:52slightly annoying issue so right now the
- 4:23:55player is walking around okay that's
- 4:23:56great I can approach a counter and
- 4:23:57interact with it that's great however if
- 4:23:59I approach a counter from the side look
- 4:24:01how the player is pointing towards the
- 4:24:03right and if I press the double key I
- 4:24:05can indeed select it but the player does
- 4:24:07not rotate to face the counter so that's
- 4:24:09just a minor visual issue but still I'd
- 4:24:11like to fix it so let's do that very
- 4:24:12quickly basically the issue is over here
- 4:24:14on our player script so we scroll down
- 4:24:16and find our handle movement function
- 4:24:18okay so here we were doing a bunch of
- 4:24:21capsule cast in order to fix the problem
- 4:24:23with the diagonal movement so you try to
- 4:24:25move in One Direction if not try to move
- 4:24:27in just one of those and if we can move
- 4:24:30then we assign the move Direction and
- 4:24:31then move it basically the problem that
- 4:24:33we have here is that if I press dou to
- 4:24:36face towards the counter then over here
- 4:24:38when we do this logic so it's going to
- 4:24:40first attempt the X movement only and
- 4:24:42the x is going to be zero so the move
- 4:24:44the x is going to be 0 0 0 so it won't
- 4:24:47actually move anywhere which means it
- 4:24:48won't be able to move so this one
- 4:24:50becomes true which then sets a move
- 4:24:52direction to 0000 0 which then down here
- 4:24:55when we have our rotation it's not
- 4:24:56actually going to rotate to anything so
- 4:24:58we want the player to still not go
- 4:25:00through any objects but we only want to
- 4:25:02modify the move Deer over here if we
- 4:25:04actually move in any of these directions
- 4:25:06so the solution is actually super simple
- 4:25:08so over here for the can move we can
- 4:25:10move if there's nothing on there and and
- 4:25:12if the move direction dox is not
- 4:25:16zero so that's really it if we are
- 4:25:19attempting to move in the X at all and
- 4:25:21if there's nothing on there then we can
- 4:25:23move which means we then assign the move
- 4:25:24direction if not then we don't touch
- 4:25:26this and same thing down here so we can
- 4:25:29move if there's nothing on it and if the
- 4:25:32move deer. Z is not
- 4:25:34zero so that's it just this one simple
- 4:25:37change and now the player should be able
- 4:25:39to rotate so here we are and if I over
- 4:25:42there and the player is currently
- 4:25:43looking to the left and if I press W to
- 4:25:46point towards the container counter and
- 4:25:47you there you go the player does rotate
- 4:25:49a little bit so that feels a bit more
- 4:25:51natural all right so that's just a tiny
- 4:25:53visual thing that I wanted to fix okay
- 4:25:55so let's keep going now let's handle the
- 4:25:58actual cutting counter so first of all
- 4:26:01as usual let's make a counter variant so
- 4:26:03let's right click on the base counter
- 4:26:05create a new prefab variant call it the
- 4:26:07cutting counter let's go inside of it
- 4:26:11and over here for thing we need is the
- 4:26:12visual so let's pick up from the assets
- 4:26:15The Cutting counter visual so here it is
- 4:26:18then we need the selected so let's
- 4:26:20duplicate this one let's rename this one
- 4:26:21to selected and on the animator let's
- 4:26:24get rid of it and instead at the
- 4:26:26component the selected counter visual
- 4:26:28okay great now let's wrag the visuals
- 4:26:31for the visual game object array and by
- 4:26:33the way here's a quick tip on the right
- 4:26:35side on the inspector you can see this
- 4:26:37nice little lock icon so if you click on
- 4:26:40it then that means this inspector will
- 4:26:42not change as you select other objects
- 4:26:45so I can click on and select something
- 4:26:47different and this one does not change
- 4:26:48it is still showing the selected object
- 4:26:50now this is useful when you want for
- 4:26:51example to drag multiple things so you
- 4:26:53can lock the inspector then the Hier key
- 4:26:55you can use shift click to select
- 4:26:57multiple objects and then just drag them
- 4:26:59all directly inside the array that's it
- 4:27:01just a nice quick tip so everything is
- 4:27:03done let's unlock it there it is okay so
- 4:27:06that said let's just assign the selected
- 4:27:09material so the counter select material
- 4:27:11let's make it just 1% bigger so let's
- 4:27:14lock them all 1.01 okay and let's start
- 4:27:18with all of them disable Okay so the
- 4:27:20basic setup is done now let's make our
- 4:27:23script to run this so let's go down
- 4:27:24let's create a brand new C script for
- 4:27:27The Cutting
- 4:27:28counter let's select the parent game
- 4:27:30object and attach a cutting counter and
- 4:27:32let's
- 4:27:34open now here as usual in set of all
- 4:27:36this let's start off by extending the
- 4:27:38base counter
- 4:27:40okay once again thanks to how we set
- 4:27:42things up using such clean code this is
- 4:27:44pretty much all we need to make a
- 4:27:45counter with this the counter already
- 4:27:48works as a counter then next thing we
- 4:27:49need is to customize any logic specific
- 4:27:51to this counter by just overwriting the
- 4:27:54interact function so that's it now over
- 4:27:56here we can put whatever logic we want
- 4:27:58just for the cutting counter and for
- 4:28:00this one for star is actually going to
- 4:28:01be just like the empty counter meaning
- 4:28:03we're going to be able to drop objects
- 4:28:05on this so let's just go directly into
- 4:28:07the clear counter so here it is and
- 4:28:09let's just copy all of this code going
- 4:28:11into the cutting counter and and past it
- 4:28:13okay so the exact same logic so checks
- 4:28:14if there is a catch an object or not
- 4:28:16checks if the player is carrying
- 4:28:17something or not and picks up or drops
- 4:28:19it with this let's do a quick test just
- 4:28:21to make sure this one is working exactly
- 4:28:22like the clear
- 4:28:24counter so over here let's just make
- 4:28:26sure to drag the last references so on
- 4:28:27The Cutting counter let's make sure to
- 4:28:29drag the counter top point so drag that
- 4:28:31reference and then on the selected Drag
- 4:28:33The Cutting counter reference okay
- 4:28:35everything is good let's exit this
- 4:28:36prefab make sure to save all the changes
- 4:28:39and over here in the scene view let's
- 4:28:41Place one of our cutting en counter so
- 4:28:42let's paste them right in there let's
- 4:28:44put it on X of 4.5 0 and
- 4:28:473.5 okay so let's test all right so here
- 4:28:51we are now if I approach and I interact
- 4:28:52nope nothing happens okay great pick up
- 4:28:54some cheese and drop it on there and yep
- 4:28:56there it is I can pick it up I can pick
- 4:28:58up some bread drop it and yep everything
- 4:29:00works okay so far so good now the next
- 4:29:04goal is to use the knife and actually
- 4:29:05slice the object that is on there and
- 4:29:08for that the first thing that we need is
- 4:29:09we're going to need a different input
- 4:29:11right now we only have the movement and
- 4:29:13the interaction so let's add another alt
- 4:29:15interaction for that let's go into our
- 4:29:18input action so let's open it up and
- 4:29:21over here let's make another action so
- 4:29:23create a new action call it interact
- 4:29:27alternate and for The Binding let's put
- 4:29:29it on another key so let's listen and I
- 4:29:31think on F makes sense so let's go ahead
- 4:29:34select this one then as usual let's make
- 4:29:36sure to save the asset which in turn is
- 4:29:38going to generate C class and compound
- 4:29:40the code okay great now we can go here
- 4:29:42into our game input class and let's do
- 4:29:44the exact same thing we did for the
- 4:29:45interact action so first of all let's
- 4:29:48listen to it so let's go inside the
- 4:29:49player input actions inside the player
- 4:29:51action map so this one is the interact
- 4:29:53alternate and let's listen to the
- 4:29:55performed event okay and when we have
- 4:29:57that let's fire off an event pretty much
- 4:29:59the same thing so interact alternate
- 4:30:04action and down here and let's just fire
- 4:30:06off this event so let's invoke using
- 4:30:10this and event arsmt
- 4:30:14okay so we have the input for the
- 4:30:15interact alternate now let's go on the
- 4:30:17player to listen the same way we were
- 4:30:19listening to the regular interact
- 4:30:21action so over here on the player script
- 4:30:24let's see how we're doing things so we
- 4:30:26go into game input and listen that so
- 4:30:28let's do the same thing game input and
- 4:30:30on interact alternate action let's
- 4:30:32listen to this one and when this one
- 4:30:34happens let's do pretty much exactly the
- 4:30:35same thing except we're just going to
- 4:30:37call a different
- 4:30:38function so instead of interact let's
- 4:30:40call interact alternate
- 4:30:42which in turn obviously means we need to
- 4:30:44Define this function so let's go into
- 4:30:46our base
- 4:30:47counter so here we are on the base
- 4:30:49counter we've got the interact and let's
- 4:30:51make another one exactly the same just
- 4:30:53different name interact
- 4:30:56alternate okay that's it and now we are
- 4:30:59only going to implement this in the ones
- 4:31:01that need
- 4:31:02implementation so for example on The
- 4:31:04Cutting counter over here let's override
- 4:31:06that one so public override and let's
- 4:31:09override the interact alternate
- 4:31:12and now here let's check check if
- 4:31:14there's something placed on here so if
- 4:31:16there's a kitchen object placed on this
- 4:31:18counter if so then let's basically cut
- 4:31:28it and for cutting it the simplest way
- 4:31:31is really to destroy whatever object is
- 4:31:33on there and just spawn the sliced
- 4:31:34object so let's handle destroying a
- 4:31:37kitchen object for handling that let's
- 4:31:39go over here on the kitchen object
- 4:31:41script and let's make a simple function
- 4:31:43for this object to destroy itself so
- 4:31:45let's go up here make it public return
- 4:31:47void and for the name I like to use the
- 4:31:49name destroy self to make it destroy
- 4:31:51this
- 4:31:52object and really all we need to do is
- 4:31:55just destroy and call destroy on this
- 4:31:56game object however before we do let's
- 4:31:59make sure to clear the parent so let's
- 4:32:01go into the kitchen object parent clear
- 4:32:02it and then destroy the game object okay
- 4:32:05that's great it's really this simple and
- 4:32:07then on the cutting counter let's get
- 4:32:09the kitchen object that is on here and
- 4:32:11tell it to destroy itself okay so that
- 4:32:13destroys the object and after we do
- 4:32:15let's just spawn the slices object so
- 4:32:17for now just keep things simple let's
- 4:32:19make a direct reference up here so let's
- 4:32:21make a serialized
- 4:32:23field let's make it of type kitchen
- 4:32:25object so and for the cut kitchen object
- 4:32:29so okay so we have this then here in the
- 4:32:32editor let's make sure drag reference so
- 4:32:34let's go inside the cut en counter let's
- 4:32:36open up the prefab and inside let's
- 4:32:38assign this one that means we need to
- 4:32:40create the object so let's actually do
- 4:32:42that
- 4:32:43first so let's create a brand new
- 4:32:45kitchen object so let's call it for the
- 4:32:47tomato
- 4:32:49slices then if we do this we need to
- 4:32:51create the prefab so let's once again do
- 4:32:53the same thing tomato slices make the
- 4:32:55prefab let's go inside this prefab let's
- 4:32:58modify the visual so use the tomato
- 4:33:00slices visual okay and drag the
- 4:33:02reference for the other kitchen object
- 4:33:04for the tomato slices okay so the visual
- 4:33:07prefab is good and let's just go into
- 4:33:10the kitchen object let's just just make
- 4:33:12sure to drag the prefab reference then
- 4:33:14let's assign the tomato slices icon and
- 4:33:17just call it tomato
- 4:33:19slices okay so we have the kitchen
- 4:33:21objecto now we can go into the kitchen
- 4:33:24cun encounter and over here let's open
- 4:33:26up and set this one to the tomato slices
- 4:33:29okay so we have all the references let's
- 4:33:31go back outside save it and back over
- 4:33:34here in our code so we have this now we
- 4:33:36just need to spawn this object so we're
- 4:33:38really just going to spawn it pretty
- 4:33:39much EXA like we did over here on the
- 4:33:41container so we just go into the scripal
- 4:33:43object spawn the prefab and set the
- 4:33:45parent so let's do exactly that over
- 4:33:47here we destroy the object then we ineni
- 4:33:50the cut kitchen object and instead of
- 4:33:53getting into the player let's put it on
- 4:33:55this okay so that's it we should be able
- 4:33:58to place a tomato directly on top of the
- 4:34:00cutting counter and it should be able to
- 4:34:02transform from a tomato into a tomato
- 4:34:05slices okay so here we are let me pick
- 4:34:07up a tomato go up there drop it and okay
- 4:34:09that works now if I press the alt trct
- 4:34:12key press it and Y there you go it did
- 4:34:13work the Tomato was destroyed and the
- 4:34:16tomato slices were spawned and now I can
- 4:34:18pick them up place them anywhere and yep
- 4:34:19everything works all right awesome so
- 4:34:22with this the basics are fully working
- 4:34:24let's just briefly clean up this code we
- 4:34:27already saw a little bit of code
- 4:34:28duplication so the cutting counter is
- 4:34:31going to spawn an object and the
- 4:34:32container counter is also spawning an
- 4:34:34object so we're copy-pasting these two
- 4:34:36lines of code in multiple places so
- 4:34:38instead of doing that let's put it in
- 4:34:39just one place and actually a good place
- 4:34:42to put this is on the kitchen object L
- 4:34:44itself so it makes sense that this one
- 4:34:45is responsible for spawning more objects
- 4:34:48so let's put it over here however let us
- 4:34:51not make it a regular function instead
- 4:34:53let us make it a static function again
- 4:34:55just like we saw for the Singleton by
- 4:34:57making it static it means that the
- 4:34:59function is going to belong to the class
- 4:35:00itself as opposed to any instance so
- 4:35:03let's go all the way down to the bottom
- 4:35:04of the file person I like to put Statics
- 4:35:06at the end and over here let's make
- 4:35:08public make it static we're going to
- 4:35:10return a kitchen object and let's call
- 4:35:13it just spawn kitchen
- 4:35:15object and for our parameters let's
- 4:35:18receive the kitchen object as
- 4:35:20so and let's also receive the kitchen
- 4:35:22object
- 4:35:24parent okay so that's it and we're going
- 4:35:26to do the exact same thing so let's go
- 4:35:27into the cutting counter and copy the
- 4:35:29code that we were using and over here
- 4:35:31just paste it in there so we go inside
- 4:35:33here spawn the prefab and set it on this
- 4:35:35parent and finally let's return
- 4:35:39it so let's return the kitchen object
- 4:35:41over here let's pick it up so the
- 4:35:43kitchen
- 4:35:45object we get it and then we do kitchen
- 4:35:48object set the parent and finally we
- 4:35:51return the kitchen
- 4:35:53object all right so that's it here we
- 4:35:55have a super simple function that we can
- 4:35:57call very easily it will automatically
- 4:36:00spawn an object and set to parent so now
- 4:36:02let's just call this from somewhere so
- 4:36:03over here on the cutting counter instead
- 4:36:05of doing all this let's just go into the
- 4:36:06kitchen object again remember let's go
- 4:36:09through the class name itself and not
- 4:36:10any instance
- 4:36:12and over here let's call the function
- 4:36:14pass in the cut kitchen objecto and for
- 4:36:16the parent it's going to be this all
- 4:36:18right so that is now much much simpler
- 4:36:20and let's do the same thing over here on
- 4:36:22the container counter so if the player
- 4:36:24is not carrying
- 4:36:25anything let's give the player this
- 4:36:28object and give it to the player just
- 4:36:31like this as usual when we do some kind
- 4:36:33of refactoring let's do a quick test to
- 4:36:35make sure everything still works exactly
- 4:36:37the same okay so here we are and if I go
- 4:36:39to the counter and pick it up yep it
- 4:36:40does work does on the object now I can
- 4:36:42drop it in there I can cut it and yep
- 4:36:44there you go everything does work all
- 4:36:45right so far so good so with all this
- 4:36:48basically we have created a brand new
- 4:36:50counter where we can cut objects however
- 4:36:53right now there's obviously one huge
- 4:36:54laying fall if I now pick up a cabbage
- 4:36:57and I drop it on the cutting counter and
- 4:36:58I interact with it that cabbage has
- 4:37:00suddenly magically turned into tomato
- 4:37:02slices now that is obviously not
- 4:37:04intended so for that let's define a
- 4:37:07proper cutting recipe and let's do that
- 4:37:08in the next
- 4:37:10lecture hello welcome I'm your Cod
- 4:37:12monkey in this lecture we're going to
- 4:37:14create another scriptable object type
- 4:37:16this one is going to be for handling our
- 4:37:18cutting recipes so here's our game I can
- 4:37:21pick up a tomato drop it on the cutting
- 4:37:23counter cut it there you go slic
- 4:37:24Tomatoes however if I could pick up a
- 4:37:27cabbage go there cut it and there you go
- 4:37:28cabbage turns into tomatoes so we have
- 4:37:31an obvious issue The Cutting object is
- 4:37:33currently hardcoded instead of being
- 4:37:34based on the object we put on top of it
- 4:37:37so to solve that let's make another
- 4:37:38script ball object type like I mentioned
- 4:37:40script B object objects are excellent
- 4:37:42for storing and organizing data so it's
- 4:37:44perfect for this use case basically we
- 4:37:46want a scriptable object to hold a
- 4:37:48reference to the regular object and the
- 4:37:50cut object so we can then identify the
- 4:37:52input in order to spawn the output okay
- 4:37:55so let's build that let's create a brand
- 4:37:57new C script call it the cutting recipe
- 4:38:00so and let's open it okay so now here
- 4:38:04let's do exactly that so something
- 4:38:05extremely simple so instead of mono
- 4:38:07Behavior this one is a scriptable object
- 4:38:09let's add the create asset menu
- 4:38:11and finally for the fields let do just
- 4:38:13an input and output so we've got of type
- 4:38:16kitchen object so let's go for the input
- 4:38:18and another one for the
- 4:38:20output okay so that's really it super
- 4:38:22simple now here in the editor before we
- 4:38:25create let's keep things organized so
- 4:38:26let's make another folder let's make it
- 4:38:29for the cutting recipe so and inside
- 4:38:32let's right click create a new cutting
- 4:38:34recipe let's call it tomato to tomato
- 4:38:39slices and over here let's select the
- 4:38:41reference so the input is going to be
- 4:38:43our tomato and the output the tomato
- 4:38:45slices okay so this is how we're going
- 4:38:48to handle things so let's go ahead and
- 4:38:50make actually the final kitchen object
- 4:38:52Asos so let's make yet another one a
- 4:38:55kitchen
- 4:38:56objecto let's make it for the Cabbage
- 4:38:59slices and then let's have another one
- 4:39:01for the cheese
- 4:39:03slices okay so now let's make these so
- 4:39:05as usual let's duplicate tomato make the
- 4:39:07cheese slices and another one for the
- 4:39:10Cabbage slices
- 4:39:12let's go inside of it and first of all
- 4:39:14drag the kitchen objecto so this one is
- 4:39:16the Cabbage
- 4:39:17slices and let's go modify the visual so
- 4:39:21instead of this one the Cabbage slices
- 4:39:23okay so we have this let's save the
- 4:39:26prefab go outside then the other one we
- 4:39:28made the cheese slices so let's swap
- 4:39:30this out let's find the cheese
- 4:39:33slices and modify the kitchen object
- 4:39:36asell
- 4:39:38okay so finally just assign the
- 4:39:40references
- 4:39:41so on the cheese slices drag the cheese
- 4:39:44slices prefab let's assign the icon and
- 4:39:48call it cheese
- 4:39:50slices okay so finally on the Cabbage
- 4:39:52slices so these are the Cabbage
- 4:39:55slices let's pick up the icon and let's
- 4:39:59drag the prefab reference okay so far so
- 4:40:02good we have created our new icons and
- 4:40:04over here let's just make all the other
- 4:40:06cutting recipes so we've got two more so
- 4:40:09one is going to be the cheese block on
- 4:40:11onto cheese slices and the other one is
- 4:40:14going to be cabbage onto cabbage slices
- 4:40:17so all we need is just to drag drop the
- 4:40:19scriptable objects so for this one
- 4:40:21cabbage let's drop the cabbage on the
- 4:40:23input cabbage slices on the output for
- 4:40:26cheese block that's the cheese block on
- 4:40:28the input and the cheese slices on the
- 4:40:30output okay great all of our data is now
- 4:40:33stored in some really nice scripal
- 4:40:35objects so now let's go here into our
- 4:40:37cutting counter and instead of having a
- 4:40:40hardcoded kitchen object
- 4:40:42let's receive a field of type cutting
- 4:40:44REO except we're going to have multiple
- 4:40:46so let's actually make an array of this
- 4:40:49call it the cutting recipe so
- 4:40:52array now for the interaction this is
- 4:40:54picking up and dropping things so let's
- 4:40:56leave that the same for now and over
- 4:40:57here on the alternate basically we need
- 4:40:59to find out which recipe we should apply
- 4:41:02to this so how I identify that is pretty
- 4:41:04simple so we've got the kitchen object
- 4:41:06that is placed on this object and we've
- 4:41:08got a list of cutting recipes which in
- 4:41:10turn has the input so we just need to
- 4:41:12cycle through all the recipes in order
- 4:41:13to find the one where the input matches
- 4:41:16okay so let's go down here make a
- 4:41:17function to do just that let's make it
- 4:41:19private we're going to return a kitchen
- 4:41:20object so so let's call it get output
- 4:41:23for input so we give it a certain input
- 4:41:25and Returns the one that matches that
- 4:41:27one so it turnes a kitchen object so for
- 4:41:30the input kitchen
- 4:41:33objecto and now here let's cycle so do a
- 4:41:36for each cutting recipe so in the
- 4:41:38cutting recipe so right so let's cycle
- 4:41:40through all these and just check if the
- 4:41:43cutting recipe so if this one do input
- 4:41:46matches the input that we received if so
- 4:41:49then this is the one we want so let's
- 4:41:51return the cutting recipes so. output
- 4:41:54and to make sure that the function Works
- 4:41:56down here let's return
- 4:41:58no okay so that's it we give it an input
- 4:42:01and we get back the output so now here
- 4:42:04we just need to make sure to do it
- 4:42:05before we destroy the current kitchen
- 4:42:08object so let's store a kitchen object
- 4:42:10as so for the output kitchen object so
- 4:42:13so and we just get the output from the
- 4:42:15input and for the input pass in the get
- 4:42:17kitchen object so that's the one inside
- 4:42:19of this cutting counter and let's get
- 4:42:22the kitchen object so so that gives us
- 4:42:24the output and then we just spawn that
- 4:42:26output okay so that's it let's test
- 4:42:30finally back in the scene let's just go
- 4:42:32inside the prefab and over here on
- 4:42:33cutting counter we need to make sure to
- 4:42:35add all the recipes so let's add so the
- 4:42:38Cabbage then a second one for cheese B
- 4:42:41and finally for the Tomato okay so there
- 4:42:43are all of our recipes let's go outside
- 4:42:45save the changes and let's test okay so
- 4:42:48over here let's pick up a tomato go up
- 4:42:50there slice it there you go got some
- 4:42:51tomato slices now pick up some cheese go
- 4:42:53here slice it and there you go got some
- 4:42:55cheese slices and finally the Cabbage go
- 4:42:57up there slice it and there you go some
- 4:42:59cabbage slices all right awesome so
- 4:43:02everything is working perfectly however
- 4:43:05now let's say that I want to pick up
- 4:43:06some bread and bread should not really
- 4:43:08be able to be cut so if I go ahead and I
- 4:43:11cut it and there you go there's our
- 4:43:13error we have no recipe that takes bread
- 4:43:15as an input So that obviously leads to a
- 4:43:17non reference exception now here we have
- 4:43:20two options for solving this problem one
- 4:43:23option is simply over here when we do
- 4:43:25the interact alternate we get the output
- 4:43:28for the input and if this one returns
- 4:43:29null then we just don't cut it so we
- 4:43:32don't destroy it and we don't spawn it
- 4:43:34or alternatively we can actually add
- 4:43:36some validation over here when dropping
- 4:43:37objects so we can make sure that we only
- 4:43:40drop valid cutable objects now both
- 4:43:42approaches are valid and actually we do
- 4:43:44need to implement both of them we'll see
- 4:43:45why in a bit so let's do both starting
- 4:43:48off with the validating the drop so
- 4:43:50first we check if there's no kitchen
- 4:43:52object on this cutting counter then we
- 4:43:54check if the player is carrying
- 4:43:55something and then we drop it from the
- 4:43:57player on this so over here let's just
- 4:43:59check if there's any recipe that has
- 4:44:01whatever the player has as an input so
- 4:44:04let's go down here make a function to do
- 4:44:06that private let's return a bow and call
- 4:44:08it has recipe with input
- 4:44:12and we're going to receive a kitchen
- 4:44:14object so for the input kitchen object
- 4:44:17so so and over here let's do pretty much
- 4:44:20literally the same logic so we have this
- 4:44:22and if we find a match then let's return
- 4:44:24true so there's a recipe with that input
- 4:44:27if not return false so now up here when
- 4:44:30the player is carrying something let's
- 4:44:32check if has recipe with input and give
- 4:44:36it the player get the kitchen object the
- 4:44:38player is holding and get the kitchen
- 4:44:40object so so if there's any recipe that
- 4:44:43takes whatever the player is carrying as
- 4:44:45an
- 4:44:46input if so then we drop
- 4:44:54it okay so like this let's sayest and
- 4:44:57see if we can drop the
- 4:44:58bread okay so let's pick up some bread
- 4:45:01go ahead drop it and nope does not work
- 4:45:03pick up some cheese and yep that one
- 4:45:04does
- 4:45:05work however now we actually also need
- 4:45:07the other validation that I mentioned
- 4:45:10the reason is because if we place Val
- 4:45:11object like for example the cheese there
- 4:45:13so that works and I can cut it and yep
- 4:45:15that does work however Now the recipe
- 4:45:18the cheese block became cheese slices
- 4:45:20and now cheese slice is no longer an
- 4:45:22input to any cutting recipe so now if I
- 4:45:24try cutting again y there you go I've
- 4:45:26got another non reference exception so
- 4:45:28we need to validate putting objects on
- 4:45:30top of it and also actually cutting them
- 4:45:32that logic is also pretty simple so
- 4:45:34let's go down to the interact alternate
- 4:45:36so we just check if there's a kitchen
- 4:45:38object on The Cutting counter and
- 4:45:41has recipe input and let's get this
- 4:45:44kitchen object get kitchen object so
- 4:45:47just like this so we're only going to
- 4:45:49cut if there is a kitchen object here
- 4:45:52and it can be
- 4:45:54cut okay so let's test so first of all
- 4:45:58the other one let's pick up bread and
- 4:45:59nope Cannot drop okay great now pick up
- 4:46:01some cheese and I can drop now interact
- 4:46:03cut now cut again and yep there you go
- 4:46:06no more errors all right awesome okay so
- 4:46:09here we have everything working perfect
- 4:46:10perfectly I can pick up a cabbage go up
- 4:46:13there cut it into slices I can slice
- 4:46:15some cheese and I can even slice some
- 4:46:17Tomatoes everything works perfectly now
- 4:46:19the one thing missing from our design is
- 4:46:21we don't actually want this action to be
- 4:46:23instant we don't want to just press a
- 4:46:24button everything slices instantly
- 4:46:26instead we want to have the player press
- 4:46:28the button a few times in order to
- 4:46:29actually cut so let's do all that in the
- 4:46:32next
- 4:46:33lecture hello and welcome I'm your Cod
- 4:46:35monkey in this lecture we're going to
- 4:46:37add the mechanic for the player to be
- 4:46:39able to cut multiple times in order to
- 4:46:41actually cut an object okay so we have
- 4:46:44our cutting counter I can drop a tomato
- 4:46:46and press a button there you go it cuts
- 4:46:47it straight away now we want the exact
- 4:46:49same logic but we want it to take a few
- 4:46:51Cuts before the cut object is spawned so
- 4:46:54let's start off by going here onto the
- 4:46:55cutting counter and basically let's keep
- 4:46:58track of some kind of progress basically
- 4:47:00the way we do that is pretty arbitrary
- 4:47:02it's up to you to decide for example you
- 4:47:04could use a normalized float however for
- 4:47:06cutting since this is going to be a
- 4:47:08discrete action let's actually count the
- 4:47:09numbers with an INT so let's store a
- 4:47:12private end just call it cutting
- 4:47:14progress okay so now let's begin by
- 4:47:17actually initializing this progress so
- 4:47:19when the player drops something on there
- 4:47:20let's set this one to
- 4:47:22zero and then down here when we have the
- 4:47:24interact alternate we do our logic and
- 4:47:27when we do let's just increase this by
- 4:47:29one and now we need to know if the
- 4:47:32object has been cut so we need somewhere
- 4:47:33to Define some kind of Maximum and for
- 4:47:36that we can actually do it directly on
- 4:47:38the recipe so so inside the The Cutting
- 4:47:41re so over here we've got the input
- 4:47:43we've got the output and let's also
- 4:47:45Define an INT for The Cutting progress
- 4:47:49Max okay that's it and back here in the
- 4:47:52editor let's go into the Tomato to
- 4:47:54tomato slices let's say this one takes
- 4:47:56just three Cuts then for the cheese
- 4:47:59let's also take three cuts and for the
- 4:48:00Cabbage let's say it's a bit thicker so
- 4:48:02let's say it takes five cuts okay so
- 4:48:05back in the cutting counter here down
- 4:48:07here we are adding to our cutting
- 4:48:09progress so we just need the recipe so
- 4:48:12in order to grab the maximum so let's
- 4:48:14actually go down here and actually make
- 4:48:16a different function so this one just
- 4:48:17returns a bullion this one a kitchen
- 4:48:19objecto let's make another one this one
- 4:48:22is going to return a cutting recipe so
- 4:48:25so get the cutting recipe so with
- 4:48:30input and we're going to receive as
- 4:48:32usual the kitchen object so for the
- 4:48:36input and really going to do the exact
- 4:48:39same thing that we did up here next time
- 4:48:41instead of returning the output let's
- 4:48:42return the recipe itself okay so now
- 4:48:45that we have this more logical one we
- 4:48:47can actually get rid of all this copy
- 4:48:48paste code so over here we just get the
- 4:48:51cutting recipe
- 4:48:54so and we just get it and pass in the
- 4:48:58input so we have this one over here if
- 4:49:01this one is not null then we're going to
- 4:49:04return this one. output and if not we're
- 4:49:07just going to return null okay so we're
- 4:49:09doing the exact same one logic just a
- 4:49:11bit simpler okay and up here pretty much
- 4:49:13the same thing so has recipe with input
- 4:49:17let's get the cutting recipe as so and
- 4:49:20basally just return if this one is not
- 4:49:23null okay so we have our three nice
- 4:49:26helper functions so let's just use this
- 4:49:28one to get the cutting REO so let's
- 4:49:30actually copy this and go up here so we
- 4:49:32do the cutting progress then let's pick
- 4:49:35it up the one for this input so the
- 4:49:37input is going to be this one the object
- 4:49:39currently on the cutting counter
- 4:49:41and over here we already know that
- 4:49:42there's going to be a recipe with this
- 4:49:43input since we've gone through this F so
- 4:49:46then we can just check if the cutting
- 4:49:48progress is bigger or equal to The
- 4:49:51Cutting recipe so and let's grab the
- 4:49:56maximum if so then yep we do spawn it
- 4:50:00okay so that's it some very simple logic
- 4:50:02Let's test so here we are let's pick up
- 4:50:05a tomato go up there and okay now I'm
- 4:50:06going to press the AL toct okay press
- 4:50:08once and yep okay so far good nothing
- 4:50:11now two times and if I press a third
- 4:50:14time boom and yep there you go got the
- 4:50:16nice slices now for cheese same thing
- 4:50:18one 2 three yep it works and finally for
- 4:50:21the Cabbage this one should be five so 1
- 4:50:23two 3 four and five and yep there you go
- 4:50:26everything does work perfectly all right
- 4:50:29awesome so with this we now have
- 4:50:31progress in our cutting logic although
- 4:50:33of course just like this it's not very
- 4:50:35good for the player the player has no
- 4:50:37way of knowing what exactly is going on
- 4:50:39so we need some kind of visual feedback
- 4:50:41so for that let's set a really nice
- 4:50:42visual progress bar and for doing this
- 4:50:44we're also going to learn about a really
- 4:50:46awesome Unity feature these are World
- 4:50:48canvases so before we make the world
- 4:50:50canvas on The Cutting counter let's
- 4:50:52actually set something up over here on
- 4:50:53the scene itself let's first create a
- 4:50:56regular canvas we're only going to use
- 4:50:58this in a couple of lectures but let's
- 4:50:59first do that one just for
- 4:51:01now so let's go on the plus button go
- 4:51:04into UI and let's create a brand new
- 4:51:07canvas okay so there you go that creates
- 4:51:09a canvas and event system
- 4:51:11now like I said we're only going to
- 4:51:12worry about this in a little bit but for
- 4:51:14now let's just leave those as is and
- 4:51:16also since we're here creating some
- 4:51:17objects let's also take some time to
- 4:51:19organize our hierarchy Unity Sly doesn't
- 4:51:22really have any folder objects so you
- 4:51:24can't organize the hierarchy in any
- 4:51:26folders however you can use empty game
- 4:51:28objects essentially as folders so let's
- 4:51:31make a brand new empty game object let's
- 4:51:33call it
- 4:51:34counters and now very importantly for
- 4:51:36empty fer objects make sure you put them
- 4:51:38on 0000 so nothing breaks
- 4:51:41so make sure you put it on there before
- 4:51:43you drag the counters and now let's just
- 4:51:45drag all the counters inside so all the
- 4:51:47clear counters put them all inside this
- 4:51:49one also drag it inside and all of these
- 4:51:51counters put them all inside so there
- 4:51:53you go now our hierarchy is quite a bit
- 4:51:55more clean okay so now let's make the
- 4:51:57cutting progress so let's click on the
- 4:51:59cutting
- 4:52:00counter and let's go inside our prefab
- 4:52:03so let's go inside of it now over here
- 4:52:06let's right click on the Hier key and
- 4:52:08we're going to create a UI let's create
- 4:52:09another canvas
- 4:52:11now for this one let's give it a name
- 4:52:12let's name it the progress bar UI and
- 4:52:15for this one over here on the inspector
- 4:52:16for the settings instead of being screen
- 4:52:18space overlay let's make this one a
- 4:52:20world space canvas basically screen
- 4:52:23space means that it would occupy the
- 4:52:24entire screen whereas World space means
- 4:52:26that this exists in the world in
- 4:52:27whatever position it is so let's make it
- 4:52:30World space and over here the fields
- 4:52:32actually unlock so let's put the
- 4:52:34positions all on zero and for the width
- 4:52:36and height let's also put it on
- 4:52:38zero so basically the canvas is going to
- 4:52:41be exactly over here by the way the
- 4:52:43shortcut that I just used was the F in
- 4:52:45order to focus on the object so this
- 4:52:47useful if you're zoomed out or zoomed in
- 4:52:49way too much okay so we have this and we
- 4:52:52want the bar to be a little bit above so
- 4:52:54let's actually lift it up on the Y by a
- 4:52:55little bit so over here let's put it on
- 4:52:57a y of 2.5 okay now like I said the goal
- 4:53:00with this is to make a progress bar so
- 4:53:02inside the progress bar UI let's create
- 4:53:04a new UI image let's name this one our
- 4:53:08bar let's put it with the width of one
- 4:53:11and the height maybe
- 4:53:13of2 so there you go just a really thin
- 4:53:16bar and for the color you can play
- 4:53:17around tinted with any color you want
- 4:53:20now for progress I think maybe a blue or
- 4:53:22a yellow something like that makes sense
- 4:53:24so let's go with a yellow kind of like
- 4:53:26this okay so there's our really nice
- 4:53:28progress bar and for this let's actually
- 4:53:31use one really nice trick for making a
- 4:53:33super easy progress bar the image
- 4:53:35component has a really easy way of
- 4:53:37making a sler image however it only
- 4:53:40actually works if you assign an image
- 4:53:41over here so let's assign one in order
- 4:53:44to be able to see those options and for
- 4:53:46that in the included project files
- 4:53:47there's a texture white 1ex one this is
- 4:53:50literally just a 1 by one white pixel so
- 4:53:53here it is just a 1ex one image fully
- 4:53:56white and as soon as we assign it we do
- 4:53:58see over here the image type so we see a
- 4:54:00bunch more options and the one that we
- 4:54:02want is to set the Sprite as filmed this
- 4:54:04one lets you do some really cool really
- 4:54:06easy effects for example you can make it
- 4:54:08radial and look at what happens in there
- 4:54:10as I modify over here on the fill amount
- 4:54:12so as I go down look that it's radiantly
- 4:54:14filling so for some kind of circular
- 4:54:16progress bar this would be excellent but
- 4:54:18in our case what we really want is just
- 4:54:20a horizontal bar so over here for the
- 4:54:22film method instead of radial let's go
- 4:54:24with horizontal and if there you go now
- 4:54:26by playing around this we have a really
- 4:54:28nice progress bar then if you want you
- 4:54:31can modify left to right right to left
- 4:54:32but yep like this it looks great now in
- 4:54:35order to modify this visual really all
- 4:54:36we're going to need is modify over here
- 4:54:38the fil Mount this one is a normaliz
- 4:54:40value so between 0 and one so Z is
- 4:54:42completely empty one is completely full
- 4:54:44however one issue with this is when the
- 4:54:46bar is empty then we can pretty much not
- 4:54:48see so we can't see the actual size of
- 4:54:50the bar we can't see what size it should
- 4:54:52be so with this it's pretty difficult to
- 4:54:54see how far along we are but solving
- 4:54:57that is pretty simple we can really just
- 4:54:58add some kind of background so let's
- 4:55:01duplicate the bar let's name this one
- 4:55:03the
- 4:55:03background for this one for the image
- 4:55:05type we don't want anything so let's
- 4:55:07leave it on SIMPLE and for the color
- 4:55:09let's put it on kind of a dark dark gray
- 4:55:11okay great and now here's one very very
- 4:55:13important thing is over here on the Hier
- 4:55:15key let's click and drag and place it
- 4:55:17above the bar the reason why that is
- 4:55:20super important is because the Sorting
- 4:55:21order and how it works in unity
- 4:55:23basically when it comes to UI elements
- 4:55:25inside a canvas the Sorting order is
- 4:55:27based on the hoard in the Hier basically
- 4:55:30it renders from top to bottom so the bar
- 4:55:33on top the background this is going to
- 4:55:34render first and then the one below it
- 4:55:36the bar is going to render afterwards
- 4:55:38which means it's going to render on top
- 4:55:40so for the background we want it to be
- 4:55:42behind so place it above on the Hier and
- 4:55:44that way it renders the background and
- 4:55:46then renders the bar also by the way for
- 4:55:482D Sprites Unity has another different
- 4:55:50sorting method it's all based on sorting
- 4:55:52layers and sorting orders I have video
- 4:55:55on that topic if you're interested in to
- 4:55:56the games okay so with this we have the
- 4:55:59background and then we have our film bar
- 4:56:01this way we can see if the progress is
- 4:56:02being fillmed or not also one more tiny
- 4:56:05thing that I like to add is Unity has
- 4:56:06some really nice really easy to add
- 4:56:08effects so you can go going to add
- 4:56:10component and let's search for a
- 4:56:13shadow this one does exactly what you
- 4:56:15expect it adds a nice drop shadow over
- 4:56:16here on the effect distance let's put it
- 4:56:18on 0.1.1 in order to see and actually
- 4:56:21let's not do it on this one but do it on
- 4:56:23the background so let's get rid of this
- 4:56:25instead going to the background over
- 4:56:26here let's add the same Shadow so if you
- 4:56:29put it on 0.1 and minus .1 y there go a
- 4:56:31nice simple drop shadow or the other one
- 4:56:34that I prefer so inside of the Shadow
- 4:56:36let's add a really nice outline once
- 4:56:38again for the effect distance point
- 4:56:400.1.1 or maybe actually 05 just to be
- 4:56:44just a tiny bit and let's raise it on
- 4:56:46the alpha so there you go nice little
- 4:56:47outline to our bar this is just a visual
- 4:56:50thing so you don't have to add this but
- 4:56:51personally I find that looks pretty good
- 4:56:54so with all of this we have our visual
- 4:56:55perfectly set up we've got our nice bar
- 4:56:57all we need to do is play around the
- 4:56:59fill mount in order to fill it so now
- 4:57:01all we need to do is to connect this to
- 4:57:03the logic but as usual let's make sure
- 4:57:05to write some good clean code so we do
- 4:57:07not want the cutting counter to directly
- 4:57:09touch on this image
- 4:57:11instead let's make a script to handle
- 4:57:12that so let's right click create a new C
- 4:57:14script call it the progress bar
- 4:57:17UI and just personally as a rule I like
- 4:57:20to append UI to any UI script you don't
- 4:57:24have to do that it's just a rule that I
- 4:57:25personally find helpful to follow that
- 4:57:27way just by looking at the scripts I can
- 4:57:29immediately see this one is a UI this
- 4:57:31one is script logic and so on so on the
- 4:57:34progress bar UI on the main game object
- 4:57:36let's attach the script and let's open
- 4:57:38it okay so now here we're going to need
- 4:57:41a reference to our
- 4:57:43image so let's add a serialized field
- 4:57:46private and we're going to need the
- 4:57:47image type and importantly this is
- 4:57:50inside using unityengine.ui so let's go
- 4:57:52up here using
- 4:57:54unityengine.ui so we have our image
- 4:57:56component okay great let's call it the
- 4:57:59bar
- 4:58:00image so we have our reference and now
- 4:58:03with this obviously we need to have some
- 4:58:05kind of reference to the counter so we
- 4:58:06know when the progress changes so it's
- 4:58:08really the same thing that we've already
- 4:58:10done so many times throughout this
- 4:58:11course so let's set a field up here
- 4:58:13serialized field private cutting counter
- 4:58:17for our cutting
- 4:58:18counter then over here in the editor
- 4:58:20let's rag the references so drag the
- 4:58:22reference to The Cutting counter and
- 4:58:24another one to the bar image okay great
- 4:58:27now we just need some kind of event to
- 4:58:28update the bar image so let's go over
- 4:58:31here into our cutting cter script let's
- 4:58:33make an event to spawn that so public
- 4:58:35event let's use the event handler the
- 4:58:38default standard let's call it on
- 4:58:41progress
- 4:58:42changed and let's also make a nice event
- 4:58:45AR to be able to send the current
- 4:58:46progress amount so let's make a public
- 4:58:49class on progress changed event arcs and
- 4:58:53let's extend event
- 4:58:54arcs and then inside let's put the
- 4:58:57current progress however let's also pass
- 4:59:00in the progress as normalized since
- 4:59:01that's the what the bar one will use so
- 4:59:04public float progress
- 4:59:07normalized and we're going to make this
- 4:59:09event of this
- 4:59:10type okay great so we have our event now
- 4:59:14whenever we modify the progress we just
- 4:59:15need to fire this event so over here
- 4:59:17when resetting the progress let's fire
- 4:59:19it so let's invoke pass in this intiate
- 4:59:22our event ARs and pass in the progress
- 4:59:25normalized and to get the normalized
- 4:59:27progress actually very simple basically
- 4:59:29we just need to divide the current
- 4:59:30progress by the maximum so cutting
- 4:59:32progress divided by cutting progress Max
- 4:59:35which is actually inside the recipo so
- 4:59:37we need to pick that one up so so let's
- 4:59:40go down there to pick up the cutting
- 4:59:42progress
- 4:59:43recipe so we pick this one up and we go
- 4:59:46in there and get the
- 4:59:48maximum however over here we also need
- 4:59:50to be very careful because there's one
- 4:59:52sneaky issue here this has to do with
- 4:59:54how C works and how ins are divided with
- 4:59:57other ins for example if we had a
- 5:00:00cutting progress of one and cutting
- 5:00:01progress Max of five you would think one
- 5:00:03divid by 5 would equal 0.2 however if we
- 5:00:06actually did that over here we would
- 5:00:08actually get a zero and the reason for
- 5:00:10that is because we are dividing two inss
- 5:00:12cutting progress is an INT cutting
- 5:00:14progress Max is also an INT and if you
- 5:00:16divide an INT by an INT then the end
- 5:00:18result will also be an INT since you
- 5:00:20cannot Define 0.2 in an INT the decimal
- 5:00:23gets cut down and you end up with just
- 5:00:25zero so that would not be correct in
- 5:00:28order to get the right value from this
- 5:00:29calulation we need to make sure to
- 5:00:30convert one of these values onto a float
- 5:00:33so that's really simple we just cast one
- 5:00:35of them so just cast this one to the
- 5:00:36float just like that basically now this
- 5:00:39one will first we cast to a float and
- 5:00:41then we're going to have a float divided
- 5:00:42by an INT and the end result will be a
- 5:00:44float so if you ever do some math and
- 5:00:47you get some weird results always make
- 5:00:48sure to check the type of your numbers
- 5:00:51okay so here we are correctly firing the
- 5:00:53event and then down here when adding our
- 5:00:55progress let's do the same thing let's
- 5:00:57also fire on the
- 5:00:59event so now we can go back into our
- 5:01:01progress bar UI and over here let's
- 5:01:04listen to the event and again remember
- 5:01:06that if we're accessing an external
- 5:01:08reference let's do that on start and not
- 5:01:10an awake so cutting counter listen to
- 5:01:13the on progress changed
- 5:01:16event when that happens let's just go
- 5:01:18bar image and set the fill amount to
- 5:01:20what we receive from the event so the
- 5:01:21progress normalized okay so that's
- 5:01:24really it and also up here on start
- 5:01:26let's initialize it as ZF so the bar is
- 5:01:29nice and empty okay so let's test back
- 5:01:32in the editor let's just go back into
- 5:01:34the scenes make sure the prefab has been
- 5:01:35saved and let's set on play and right
- 5:01:38away yep we do see the bar yep it is
- 5:01:40empty now pick up some cheese drop it
- 5:01:42and if I cut and Y there you go add a
- 5:01:44little bit of progress now a bit more
- 5:01:45and there you go there's our cheese okay
- 5:01:48great everything does work now let's add
- 5:01:51just one more tiny bonus thing we can
- 5:01:53add some extra logic in order to hide
- 5:01:55this visual if the bar is either
- 5:01:56completely empty or completely full that
- 5:01:58is actually pretty simple over here on
- 5:02:01the progress bar UI script let's just
- 5:02:03make some basic show and height
- 5:02:04functions so private void show and then
- 5:02:08we're going to have
- 5:02:12a private void
- 5:02:13hide on these one just game object set
- 5:02:16active this one set it to true and this
- 5:02:18one set it to false now on start we
- 5:02:21subscribe to the event and then let's
- 5:02:23hide it
- 5:02:25okay also here it's very important make
- 5:02:27sure you hide it after you listen to the
- 5:02:29event if for example you called hide on
- 5:02:31awake that would disable the game object
- 5:02:33and the start would never run so it
- 5:02:34would never listen to the event so if
- 5:02:36you have set the game object as inactive
- 5:02:39make sure you do it only after you're
- 5:02:41listening to whatever events you want so
- 5:02:43we have this that's great and then when
- 5:02:45the progress changes let's just do a
- 5:02:47basic test so if e. progress normalized
- 5:02:50equals 0f or if the progress normalized
- 5:02:54equals 1f so if the bar is empty or
- 5:02:56completely full if so then let's hide it
- 5:02:59and if not then let's show
- 5:03:03it okay that's it let's test okay and
- 5:03:07yep by default starts off hidden let's
- 5:03:09pick up a tomat go up there and yep
- 5:03:11still hidden now I cut and there you go
- 5:03:12there it is cut again and yep there you
- 5:03:14go it hides itself okay great so we've
- 5:03:16got a nice little visual let's do just
- 5:03:19one more final thing let's add a really
- 5:03:21nice
- 5:03:22animation if we go inside the cutting
- 5:03:24counter and we'll look at the cutting
- 5:03:26counter visual over here note how it
- 5:03:27already has an animator just like we did
- 5:03:30for the container counter it's all very
- 5:03:32simple so basically just has a cut
- 5:03:34parameter when that happens it just cuts
- 5:03:36the counter so it just plays a simple
- 5:03:38animation since it's going to be pretty
- 5:03:40much EXA like the container counter
- 5:03:42let's actually duplicate that script so
- 5:03:44let's go down find that script so the
- 5:03:46container counter visual let's duplicate
- 5:03:48this so contrl D let's rename this to
- 5:03:51The Cutting counter visual okay let's
- 5:03:55open and over here let's rename the
- 5:03:57script so the cutting counter visual
- 5:03:59okay great then for the parameter let's
- 5:04:01rename this instead of open close is
- 5:04:03going to be called cut and for the
- 5:04:05string it's cut again make sure you
- 5:04:08write it case sensitive make sure sure
- 5:04:09it's all correct then instead of having
- 5:04:12a container counter we've got a cutting
- 5:04:14counter and a cutting
- 5:04:16counter and finally we just need to
- 5:04:18listen to the correct event so
- 5:04:20technically we could listen to the
- 5:04:21onprogress changed however that one also
- 5:04:23gets fired over here when the cutting
- 5:04:25progress is zero we don't want the cut
- 5:04:27anation to play when this happens so
- 5:04:29let's just make another simple event so
- 5:04:31a public event event handler let's call
- 5:04:34this just on
- 5:04:36Cut okay and then down here when we have
- 5:04:38our cutting progress so we cut and let's
- 5:04:41just invoke this
- 5:04:43event okay that's it super simple so now
- 5:04:47on The Cutting counter visual let's go
- 5:04:49into the cutting counter and into the
- 5:04:50uncut event let's listen to this and
- 5:04:53we're going to set the trigger exactly
- 5:04:55like this so get rid of the container
- 5:04:57counter like
- 5:04:59this okay there you go a very simple
- 5:05:01script so now here back in the scene
- 5:05:04view inside the container counter prefab
- 5:05:07let's just go inside the visual let's
- 5:05:08attach a cutting counter visual just
- 5:05:10need to drag The Cutting counter
- 5:05:11reference and that's it let's exit the
- 5:05:14prefab save it and let's play okay so
- 5:05:16now let's pick up a cabbage go up there
- 5:05:18drop it and out interact and if there
- 5:05:20you go we've got a nice little animation
- 5:05:23all right awesome so I can drop things I
- 5:05:25can cut them and everything works
- 5:05:28perfectly all right so here we added a
- 5:05:31cutting progress to our cutting counter
- 5:05:34and we also learned about yet another
- 5:05:35very useful Unity feature called World
- 5:05:38canvases and at the at the same time you
- 5:05:40might have also noticed that the canvas
- 5:05:41is looking at the camera in kind of a
- 5:05:43weird way basically just pointing
- 5:05:45straight forward this can sometimes make
- 5:05:47it difficult to see so let's work on
- 5:05:49that in the next
- 5:05:50lecture hello and welcome I'm your Cod
- 5:05:53monkey in this lecture we're going to
- 5:05:55build a very simple but very useful
- 5:05:57script to make an object look straight
- 5:05:58at the camera with various options okay
- 5:06:01so we previously made the cutting
- 5:06:03counter and when I play something yep
- 5:06:04there's a nice progress bar so now that
- 5:06:07this is working let's do one more thing
- 5:06:10right now look at how the bar is
- 5:06:11oriented it's looking quite a bit
- 5:06:13slanted that's because we have a
- 5:06:15perspective camera and it's looking from
- 5:06:16top down now this is one of those things
- 5:06:19that is kind of personal preference so
- 5:06:20maybe you'll like it just like this but
- 5:06:22a lot of the times you want these World
- 5:06:24UI elements to face the camera just like
- 5:06:26a regular UI one example of this problem
- 5:06:29is for example let me pick up the
- 5:06:30cutting counter duplicate it and let's
- 5:06:32put one down here so rotate it
- 5:06:36upwards okay let's put it on 4.5 0 and
- 5:06:40minus 5 now if I place something on
- 5:06:43there and I cut it yep look at that the
- 5:06:44bar is Now inverted so let's make a
- 5:06:47simple script to solve this
- 5:06:48problem let's go into our scripts create
- 5:06:51a new C script call it look at
- 5:06:54camera let's go onto the cutting counter
- 5:06:57prefab let's open it up go inside on the
- 5:06:59progress bar let's attach this script so
- 5:07:01the look at camera okay now let's open
- 5:07:04so from here let's use an interesting
- 5:07:06function so let's use a private void
- 5:07:08late up update so not update we have
- 5:07:11theate update so if this is the first
- 5:07:13time you're hearing about this like name
- 5:07:15implies this one is going to run after
- 5:07:17the regular update so every single
- 5:07:19update and all the objects is going to
- 5:07:21run and then all the late updates so
- 5:07:23kind of like you've got awake and start
- 5:07:25you have update and late update why this
- 5:07:27is useful specifically for this script
- 5:07:30is because for this element you really
- 5:07:31want this to run the orienting logic you
- 5:07:33want that to be done after whatever that
- 5:07:35object does in the update in this case
- 5:07:38this object will never move so it's not
- 5:07:39really an issue but for example if you
- 5:07:41had some kind of moving vehicle with a
- 5:07:43world canvas on top if you had that you
- 5:07:45would want to set the world canvas
- 5:07:47location to look at the camera after the
- 5:07:49vericle had moved otherwise the canvas
- 5:07:51would not look perfect so anyways
- 5:07:53because that here we're doing on late
- 5:07:55update and now we can just look straight
- 5:07:57at the camera so we can just do
- 5:07:59transform. look
- 5:08:02at and for Target pass in the camera.
- 5:08:05main.
- 5:08:06transform this function makes this
- 5:08:08transform look at another transform or
- 5:08:10another point so this will make it look
- 5:08:11straight at the camera also by the way
- 5:08:14one quick note here in some older
- 5:08:15tutorials you might see people telling
- 5:08:17you not to use camera. main the reason
- 5:08:20for that is because this field did not
- 5:08:22used to be cached so every time you use
- 5:08:24this it would cycle through every single
- 5:08:26game object in the scene until it found
- 5:08:27the main camera so that was obviously
- 5:08:30really bad for performance but nowadays
- 5:08:32this field is now cached by default on
- 5:08:33the unity back end so you no longer need
- 5:08:35to cat it yourself accessing it directly
- 5:08:37just like this is now fine okay so with
- 5:08:40this let's test just make sure to save
- 5:08:43the prefab and let's set on play Let's
- 5:08:46go ahead pick up a cabbage put it up
- 5:08:47there and yep there you go look at that
- 5:08:49how it's looking straight at the camera
- 5:08:51and for this one down here same thing
- 5:08:53cut it and yep there you go both of them
- 5:08:54are looking straight at the camera okay
- 5:08:57so that's great you can also see exactly
- 5:09:00what it's doing if we try to move the
- 5:09:01camera again we're using cinem machine
- 5:09:03so let's move the virtual camera so over
- 5:09:05here if I just play around with the
- 5:09:07positionx look at that look how as I
- 5:09:09move the camera yep the objects are
- 5:09:11perfectly looking straight at the camera
- 5:09:13so that's great that's what we want but
- 5:09:15also you might notice one thing notice
- 5:09:17how the bars are actually inverted
- 5:09:20instead of going left to right they're
- 5:09:21actually going right and left basically
- 5:09:23this has to do with how the canvas by
- 5:09:25default assumes you are essentially
- 5:09:26going to look at it from behind instead
- 5:09:28of looking forward so that is why when
- 5:09:30this game object is pointing straight at
- 5:09:32the camera it's essentially inverted so
- 5:09:34to solve this actually quite simple we
- 5:09:36basically just need to look in the exact
- 5:09:38opposite direction but at the same time
- 5:09:40sometimes we might want this exact
- 5:09:42Behavior having something look straight
- 5:09:43at the camera maybe we do want it to be
- 5:09:45inverted sometimes so for that let's
- 5:09:47make a nice complete script with all of
- 5:09:49our possible options and for the finding
- 5:09:52options this also an excellent way to
- 5:09:53learn about one more thing which are C
- 5:09:55enums enums are an enumeration meaning a
- 5:09:59fixed set of options that you can have
- 5:10:00of something so these are really useful
- 5:10:03when you have a fixed set of something
- 5:10:05like for example maybe a fixed number of
- 5:10:07options so for example up here let's
- 5:10:09let's make it private make it an inum
- 5:10:11and let's call it mode and then inside
- 5:10:14we can Define all of our options so
- 5:10:16let's say we have the regular look at
- 5:10:18and then look at
- 5:10:19inverted okay so we have these two
- 5:10:22options in our enum now let's do a field
- 5:10:24of this type and exposed in the editor
- 5:10:26so let's make a serialized field private
- 5:10:29of type mode and call it
- 5:10:31mode okay let's save this and look what
- 5:10:33this looks like in the editor and if we
- 5:10:36go inside the cutting counter and we
- 5:10:38look at the progress bar
- 5:10:39you a look at that the mode shows up and
- 5:10:41it shows up as a really nice drop- down
- 5:10:43menu so since we have a limited number
- 5:10:45of options we've got a really nice menu
- 5:10:47where we can choose each one you want so
- 5:10:50that's really awesome that's one of the
- 5:10:51benefits of enums they are really easy
- 5:10:53to use over here in the
- 5:10:55editor now back in the code here let's
- 5:10:57decide which one to use so on The Late
- 5:11:00update let's just do a switch on our
- 5:11:01mode in case we are on the regular look
- 5:11:04at mode then let's do exactly this let's
- 5:11:06simply look at it in case we are on the
- 5:11:09look at
- 5:11:10inverted for this we just want to look
- 5:11:12at the inverse position so that's
- 5:11:13actually pretty easy we just calculate
- 5:11:16the direction Vector from the camera to
- 5:11:18this object so a vector 3 call it deer
- 5:11:21from
- 5:11:22camera and to get direction from the
- 5:11:24camera we start from this object so this
- 5:11:26transform. position subtract the camera.
- 5:11:29main transform
- 5:11:30position so this gives us the direction
- 5:11:33pointing from the camera and then we
- 5:11:35just do transform.
- 5:11:37Lookout and instead of looking at the
- 5:11:39camera let's look at the opposite
- 5:11:40position so let's look at transform.
- 5:11:42position so our current position plus
- 5:11:44the direction from the camera so we're
- 5:11:45going to be looking at the exact
- 5:11:47opposite Point okay so that's it let's
- 5:11:50test and right now by default we have
- 5:11:52the regular look at so let's just see it
- 5:11:55let's just Place some objects okay so
- 5:11:57right now it's still
- 5:11:58inverting and something really nice is
- 5:12:00you can play around the inom even as the
- 5:12:02game is running so let's go inside the
- 5:12:04cutting counter on the progress bar UI
- 5:12:06for this one let's SW from look at to
- 5:12:07look at inverton any look at that that
- 5:12:09one is now looking perfectly so this one
- 5:12:12is using look at and this one using look
- 5:12:14at
- 5:12:14inverted okay great it's all working
- 5:12:17however yet another thing that is all
- 5:12:19about personal preference note how the
- 5:12:21visual has a slight slant this is due to
- 5:12:24how the visual is actually looking
- 5:12:26directly at the center of the camera so
- 5:12:29you can really see it if I move the
- 5:12:30camera left and right how it Ls going
- 5:12:33left or going right again this is all
- 5:12:35personal preference it's just a visual
- 5:12:37so maybe you do want this look but but
- 5:12:39let's see another method so over here in
- 5:12:41our modes let's add two more let's add
- 5:12:43camera forward and Camera forward
- 5:12:46inverted and then down here on our late
- 5:12:48update let's add those so the camera
- 5:12:50forward and then we have the camera
- 5:12:53forward
- 5:12:53inverton so for this one for the camera
- 5:12:56forward super simple let's just say this
- 5:12:57transform use the forward which again
- 5:12:59you can get or you can set it and let's
- 5:13:01set it to the exact same one as the
- 5:13:03camera. main. transform. forward and for
- 5:13:07the inverting exactly the same thing
- 5:13:09except in setad of forward we do minus
- 5:13:11forward okay so let's see what this
- 5:13:13looks like okay so here's the game with
- 5:13:15both counters they're both currently
- 5:13:17using the look at mode now if I put a
- 5:13:19look at inverting yep that one goes left
- 5:13:21to right okay great now if I put camera
- 5:13:22forward yep look at that now that one is
- 5:13:25perfectly straight so even as I move the
- 5:13:27virtual camera left and right look how
- 5:13:29that is always perfectly facing the
- 5:13:31camera as if it was a regular UI
- 5:13:33element and for the inverton does the
- 5:13:36exact same thing but invert so just like
- 5:13:37that so that's it these are the four
- 5:13:40modes again these are all just visual
- 5:13:42elements so pick whatever you prefer for
- 5:13:44me I'm going to be using this one the
- 5:13:45camera. for so that everything is
- 5:13:47perfectly horizontal so I'm just going
- 5:13:49to make sure to go inside the prefab and
- 5:13:51on the prefab itself modified and set it
- 5:13:53as camera. for and now if I add a cheese
- 5:13:56there yep looks great and if I add a
- 5:13:58cabbage here and yep it also looks right
- 5:14:01all right so here we created a really
- 5:14:03nice useful generic script to make an
- 5:14:05object look straight at the camera in
- 5:14:07various ways note how this this one has
- 5:14:09nothing to do with canvas or a progress
- 5:14:11bar or anything it's really a generic
- 5:14:13script to look at the camera so you can
- 5:14:15apply this to anything where you want it
- 5:14:16to look at the camera okay so with that
- 5:14:19the cutting counter is fully done now
- 5:14:21let's handle the trash counter in the
- 5:14:23next
- 5:14:24lecture hello and welcome I'm your code
- 5:14:27monkey in this lecture let's create the
- 5:14:29trash counter this one is actually
- 5:14:31pretty simple it's how we're going to
- 5:14:32drop something and just destroy it okay
- 5:14:35so making the trash counter is going to
- 5:14:36be super super easy once again going to
- 5:14:39be another great practical example of
- 5:14:41the power of writing good clean code and
- 5:14:42having good organization in your project
- 5:14:45so let's do the same thing that we've
- 5:14:46already done a bunch of times so first
- 5:14:48of all let's make the prefab variant so
- 5:14:50let's right click on the base counter
- 5:14:52and create a brand new prefab variant
- 5:14:55call it the trash
- 5:14:57counter okay let's go inside and first
- 5:15:00of all let's drag the visual so find the
- 5:15:02visual prefab on the trash counter okay
- 5:15:05then let's duplicate it to make the
- 5:15:07selecton so let's rename this to
- 5:15:10selected let's add the selected counter
- 5:15:13visual let's add the visual inside of it
- 5:15:17and on the visual let's select the other
- 5:15:20material so the counter selected and
- 5:15:22finally on the selected put it 1% bigger
- 5:15:271.01 and start off with visual disabled
- 5:15:30okay so that's the basics just like
- 5:15:33we've already done so many times now
- 5:15:35let's make the script to run this so
- 5:15:37let's right click create new C script
- 5:15:39script call it the trash
- 5:15:41counter and by the way here we're
- 5:15:43already starting to have quite a bunch
- 5:15:44of scripts so we should probably
- 5:15:45organize the scripts folder so let's
- 5:15:48make a new folder let's call it
- 5:15:51counters and let's make another one and
- 5:15:54call it scriptable
- 5:15:56objects so on the counters let's drag
- 5:15:59the base counter clear counter the
- 5:16:01container the container visual The
- 5:16:02Cutting The Cutting visual then down
- 5:16:04here the trash counter okay let's drag
- 5:16:07them all onto the counters folder and on
- 5:16:09the scriptable objects let's put the
- 5:16:11cutting recipe and the kitchen object
- 5:16:12ASO okay now our folder is a bit more
- 5:16:15organized so let's open up the trash
- 5:16:17counter and over here as usual let's
- 5:16:19begin by extending the base counter okay
- 5:16:23great then let's implement the regular
- 5:16:25interaction so override the
- 5:16:28interact and on this one again it's
- 5:16:30going to be super simple we just check
- 5:16:32if the player is holding something and
- 5:16:34if so we destroy it so just check if
- 5:16:36player that has kitchen object so if the
- 5:16:39player is holding something go into the
- 5:16:40player get the kitchen object the player
- 5:16:42is holding and simply call destroy
- 5:16:46self and that's it it's this simple back
- 5:16:49in the editor let's just attach a script
- 5:16:51let's make sure to drag the counter top
- 5:16:53Point reference and on the selected drag
- 5:16:55the base counter reference okay with
- 5:16:57this it should be working so let's exit
- 5:16:59the scene let's save the prefab and
- 5:17:01let's drag it over here onto our scene
- 5:17:03so let's drag the trash counter and put
- 5:17:06it maybe somewhere over here on the
- 5:17:07corner so let's put it here on an X of
- 5:17:10seven y0 and minus
- 5:17:133.5 then let's also fill up these spots
- 5:17:16down here so let's duplicate a clear
- 5:17:18counter put one in there put another one
- 5:17:21in there let's put another one on the
- 5:17:24side and for the trash counter and let's
- 5:17:25align it so let's put it a bit more to
- 5:17:27the side so on 7.5 okay great and let's
- 5:17:30put it inside the counters and now we
- 5:17:32can test okay so let's see if we can
- 5:17:35interact with it and yep as I approach
- 5:17:36yep I do see it highlighted okay great
- 5:17:38and if I if I interact obviously nothing
- 5:17:40happens since the player isn't holding
- 5:17:41anything now if I pick something up
- 5:17:43let's say a tomato and I don't want this
- 5:17:45tomato so I want to trash it and if
- 5:17:47there you go it does get trashed all
- 5:17:49right awesome so this is literally it
- 5:17:51like I said this is once again another
- 5:17:53excellent example of the power of
- 5:17:54writing good clean code this was super
- 5:17:56simple to implement because we have a
- 5:17:58really nice structure for how all of our
- 5:18:00Counters work also because our
- 5:18:02interaction system is very well built
- 5:18:04also because the kitchen object system
- 5:18:06is very well made it's because of all of
- 5:18:08the that great very clean code that we
- 5:18:10were able to implement a brand new
- 5:18:12counter in literally about 60 seconds so
- 5:18:15once again I hope that by following this
- 5:18:16course you know understand why I'm
- 5:18:18always talking about the importance of
- 5:18:19writing good clean code it's exactly
- 5:18:21because of this if you write your code
- 5:18:23correctly it makes developing the game
- 5:18:25so much easier at first it might seem
- 5:18:27like the quick and dirty approach is
- 5:18:28faster and usually in the beginning it
- 5:18:30is faster but as soon as you add some
- 5:18:32complexity the quick and dirty approach
- 5:18:34suddenly won't scale whereas the
- 5:18:36well-built clean Cod approach this one
- 5:18:38won't continue scaling very well so here
- 5:18:40we have a fully functional trash bin so
- 5:18:42we can dispose of unwanted objects next
- 5:18:45let's build a much much more complex
- 5:18:47counter let's build a stove counter
- 5:18:49which also requires building a really
- 5:18:51nice State machine so let's do that in
- 5:18:53the next lecture hey again another quick
- 5:18:56intermission you're past the halfway
- 5:18:58point so congrats again by now I really
- 5:19:00hope you've already learned a ton from
- 5:19:02the course we've already covered lots of
- 5:19:04topics and built a ton of systems I hope
- 5:19:06you've been following the website as you
- 5:19:07go through the lectures and I I hope
- 5:19:08reading the frequently asked questions
- 5:19:10has helped you in some way let me know
- 5:19:12in the comments how you've used the
- 5:19:13course website did you just read the FAQ
- 5:19:16or did you also download some project
- 5:19:18files let me know I'm curious to know if
- 5:19:20you enjoy my teaching style also look at
- 5:19:22my other courses after finishing this
- 5:19:23one especially the turn-based strategy
- 5:19:25course that one is an excellent followup
- 5:19:27for this one okay there's still quite a
- 5:19:29bit more for us to build and learn so
- 5:19:31let's continue in the next
- 5:19:33lecture hello and welcome I'm your Cod
- 5:19:35monkey in this lecture we're going to
- 5:19:37build the stove counter so we want to
- 5:19:39place some uncooked meat then we wait
- 5:19:41for a bit for it to be cooked however if
- 5:19:43we wait too much it's going to get
- 5:19:45burned so let's Implement that all right
- 5:19:47so as usual let's first begin by making
- 5:19:48our counter so let's go inside the
- 5:19:50prefabs the counters let's right click
- 5:19:52on the base counter and create new
- 5:19:53prefab variant call this the stove
- 5:19:56counter and as usual let's go inside of
- 5:19:58it let's find the visual so inside the
- 5:20:01prefab visuals the counters visuals here
- 5:20:03is the stove counter so let's drag it
- 5:20:05then let's duplicate this rename this
- 5:20:07one the selecton
- 5:20:09let's set the component the selected
- 5:20:11counter visual then let's go inside on
- 5:20:14all of these and by the way this visual
- 5:20:16actually has some nice visuals that
- 5:20:17we're going to implement in a little bit
- 5:20:19but for the selected we really just want
- 5:20:20the static objects so let's pick up all
- 5:20:22of these and let's select the counter
- 5:20:24select visual okay nice and white then
- 5:20:27let's lock over here the parents so I
- 5:20:28can select all of these and drag all of
- 5:20:30them okay great and start off with all
- 5:20:32of them disable Okay so that's the basic
- 5:20:34setup as usual just for the counter
- 5:20:37point since this one has a nice little
- 5:20:39sub on top let's lift it up by a little
- 5:20:41bit so put it on a y of 1.
- 5:20:441456 okay that looks pretty good just
- 5:20:47move it a little bit to the center okay
- 5:20:49great so now let's make our script so
- 5:20:52let's go inside our script folder we've
- 5:20:54got our counter so in here let's create
- 5:20:56a brand new C script for the stove
- 5:20:58counter let's wait for it to compile
- 5:21:01let's attach the script and open okay so
- 5:21:04here as usual let's extend the base
- 5:21:06counter now like I said the go for this
- 5:21:09one is to be able to cook our meat and
- 5:21:10for that it's going to be based on a
- 5:21:12timer and to actually cook the meat
- 5:21:14we're going to need to know which one is
- 5:21:16the uncooked meat type and which one is
- 5:21:18the cooked meat type so for that we
- 5:21:20really want the exact same logic that we
- 5:21:22did for the cutting action we want some
- 5:21:24kind of place where we can sore an input
- 5:21:26and output as well as a cook timer so
- 5:21:28for that let's actually just duplicate
- 5:21:30so let's go inside our scriptable
- 5:21:31objects for The Cutting recipe and let's
- 5:21:33duplicate this one so contrl D and let's
- 5:21:35name this one the frying recipe so okay
- 5:21:39let's go inside and over here let's
- 5:21:41rename the object then we have an input
- 5:21:43we have an output and then set of
- 5:21:45progress let's have the frying timer Max
- 5:21:48and since this one is a timer instead of
- 5:21:50an in let's make it a float okay so
- 5:21:52that's it pretty simple then back here
- 5:21:54in the editor let's create our script
- 5:21:56object so let's go inside let's make a
- 5:21:58nice folder so a folder for the frying
- 5:22:01recipe
- 5:22:05so and inside let's create one so let's
- 5:22:08create a brand new frying recipe so for
- 5:22:10this one let's call it meat Patty
- 5:22:12uncooked into meat Patty
- 5:22:15cooked then for the inputs let's choose
- 5:22:18the meat Patty uncooked now we have to
- 5:22:20make the other one so let's go ahead and
- 5:22:22make that one let's duplicate this one
- 5:22:24rename it to the meat Patty
- 5:22:26cooked and the object name meat Patty
- 5:22:29cooked let's select the different Sprite
- 5:22:32so this one is going to be the meat
- 5:22:34Patty cooked okay and finally for the
- 5:22:36prefab let's also make it so for the
- 5:22:39meat Patty cooked let's go inside of it
- 5:22:42and also make sure to save the changes
- 5:22:44on our stove counter so okay now in here
- 5:22:46let's get rid of this Visual and use the
- 5:22:48other visual so we want the meat Patty
- 5:22:50cooked and let's make sure to drag the
- 5:22:52script ball object okay so it's all good
- 5:22:55here let's go back outside save it and
- 5:22:57finally over here on the meat Patty
- 5:22:59cooked let's just grab the prefab
- 5:23:01reference so there you go that one okay
- 5:23:03so this one is working and since we're
- 5:23:04here let's actually make the other one
- 5:23:06right away so let's make the meat pack
- 5:23:08Patty burned so the prefab and let's
- 5:23:11also duplicate this to make the meat
- 5:23:13Patty burned then on the text let's
- 5:23:17rename this to burned let's choose the
- 5:23:19burned icon and for the prefab let's go
- 5:23:23into our meat Patty burned and swap it
- 5:23:25out for the burned one so there you go
- 5:23:27nice and Char and over here swap it for
- 5:23:30the meat Patty burned okay let's save it
- 5:23:33and finally down here just make sure
- 5:23:35everything is correct so me Patty burn
- 5:23:37just drag the SC script M object the
- 5:23:39transform prefab just like that okay so
- 5:23:42all of our burn references over here all
- 5:23:44of our cooked and over here all of are
- 5:23:46uncooked and again when going through
- 5:23:48this process always make sure that you
- 5:23:49match all the references on the script
- 5:23:51objects and also over here on the
- 5:23:53kitchen objects so meat Patty burn yep
- 5:23:55meat Patty burn for the uncooked the
- 5:23:57uncooked and for the cooked there it is
- 5:23:59okay everything is good great so now we
- 5:24:01can go back over here into our frame
- 5:24:03recipe so and for the output let's
- 5:24:05output the meat Patty cooked and for the
- 5:24:07fry timer let's put it on 3 seconds okay
- 5:24:10so that's it great now back in the code
- 5:24:12here on the stove counter let's set an
- 5:24:14array of our Frank recipes so a
- 5:24:16serialized field private it's going to
- 5:24:19be an array of frying recipe so so
- 5:24:20frying recipe so array and call it
- 5:24:22frying recipe so array okay great then
- 5:24:26back here in the editor let's go inside
- 5:24:28the stove counter let's make sure to
- 5:24:30drag that so let's drag the meat Patty
- 5:24:33from uncooked into cooked okay let's
- 5:24:35also drag the counter top point and
- 5:24:37finally since we have already made the
- 5:24:38script over here on the selected we can
- 5:24:40also drag the selected okay so our stove
- 5:24:42prefab should be working okay let's go
- 5:24:45outside make sure to save the prefab
- 5:24:47okay now let's continue with the rest of
- 5:24:48the script so let's make our override so
- 5:24:52override the interact action and when we
- 5:24:55interact with it let's validate dropping
- 5:24:58the object just like we did on the
- 5:24:59cutting
- 5:25:01counter so let's go over here into our
- 5:25:03cutting count script and let's just copy
- 5:25:05pretty much the exact same thing so
- 5:25:07let's copy all of this into Dr code
- 5:25:09let's go over here in the stove counter
- 5:25:10and just paste it now we also need to
- 5:25:13copy in our recipe so over here on the
- 5:25:16cutting counter let's copy paste those
- 5:25:18functions so these functions go into the
- 5:25:20self counter and over here let's paste
- 5:25:22them they're going to work pretty much
- 5:25:23the same thing so we got an input except
- 5:25:26instead of being a cutting recipe so
- 5:25:28we're going to have a frying recipe so
- 5:25:30so let's replace all the cutting recipe
- 5:25:32references with frying recipe reference
- 5:25:35then for the array this one is a frying
- 5:25:37recipe array and let's rename these so
- 5:25:40control RR to rename all of them into
- 5:25:42frying recipe so let's also rename the
- 5:25:45function instead of get cutting recipe
- 5:25:47so it's the frying recipe so okay so
- 5:25:49there's no more mentions of cutting over
- 5:25:51here so let's use this function up here
- 5:25:53and up here and just make sure to rename
- 5:25:55these the frying recipe
- 5:25:59so and down here all same thing so the
- 5:26:02frying recipe so okay so down here we
- 5:26:05have no more mentions of any cutting
- 5:26:07let's just go here and solve all these
- 5:26:09problems so first we check if there's no
- 5:26:11kitchen object here and if the player is
- 5:26:13carrying something then we see if what
- 5:26:15the player is carrying matches any kind
- 5:26:16of frying recipe if so then the player
- 5:26:19is carrying something that can be fried
- 5:26:22then we set the parent and for now let's
- 5:26:24not worry about the progress so let's
- 5:26:26just get rid of all of this just like
- 5:26:28this okay so with this we should be able
- 5:26:30to drop but only an uncooked meat so
- 5:26:32back in the other turn let's just set up
- 5:26:34our scene so let's drag a stove counter
- 5:26:36onto our scene let's put over there
- 5:26:38there on X of 6 y of 0 and 3.5 all right
- 5:26:42so let's test okay so now if I pick up
- 5:26:45some cheese I go up there and I drop it
- 5:26:47and nope doesn't work okay great but if
- 5:26:49I pick up some uncooked meat and I go
- 5:26:51and I drop it and yep that does work
- 5:26:53okay great so it works and I can only
- 5:26:55drop the actual objects that match the
- 5:26:57recipe now unlike the cutting counter
- 5:26:59this one will not be based on a player
- 5:27:01alt interaction and actually over here
- 5:27:04let's fix this minor issue basically we
- 5:27:07added this debug. log error to the base
- 5:27:09interact because pretty much every
- 5:27:11single counter is going to implement
- 5:27:12this interact function but not all
- 5:27:14counters are going to have the interact
- 5:27:16alternate action so this one let's just
- 5:27:18do nothing let's not spawn an error okay
- 5:27:20just a quick fix so like I said the
- 5:27:23stove counter this one is going to be
- 5:27:24based on a simple timer and for making
- 5:27:27some time based logic basically we have
- 5:27:29two approaches one approach is to use a
- 5:27:31simple flow timer or you can also use a
- 5:27:34Cod routine now a lot of tutorials will
- 5:27:36teach you how to use a code routine
- 5:27:38and that's not necessarily a bad
- 5:27:40practice it does work it does achieve
- 5:27:42desired result so to do that you would
- 5:27:44just make a function like fry
- 5:27:46timer so you'd make a private you have
- 5:27:49to return I in
- 5:27:51numerator then call it something like
- 5:27:53handle fry
- 5:27:56timer then inside you can do a yield
- 5:27:59return and return a new weight for
- 5:28:05seconds and to start this C routine you
- 5:28:08would do maybe on start you would call
- 5:28:10start Co
- 5:28:13routine and start the handle fry
- 5:28:16timer so this is one approach this is
- 5:28:18definitely perfectly valid timer code
- 5:28:21however personally I am not a fan of Co
- 5:28:23routines it's not because of performance
- 5:28:25or anything it's simply because I don't
- 5:28:27like the pattern that they force you to
- 5:28:29use I don't like being forced to make a
- 5:28:31function that returns I numerator I
- 5:28:33don't like using Guild return I don't
- 5:28:36like having to use the start co- routine
- 5:28:38function I don't like being forced to
- 5:28:40use this on a monob behavior object
- 5:28:42those are all requirements for making a
- 5:28:44co- routine work and personally I find
- 5:28:46those are way too many requirements that
- 5:28:48create a very strange pattern that I
- 5:28:50really don't like so that's really the
- 5:28:52only reason I don't like co- routines
- 5:28:54because I find this pattern to be quite
- 5:28:56a lot convoluted so instead of Co
- 5:28:58routines what I like to use are simple
- 5:29:00basic flow timers so just make a simple
- 5:29:03private void update then we just need to
- 5:29:05keep track of a certain timer so for
- 5:29:08examply simple private float frying
- 5:29:10timer then on the update let's first
- 5:29:13check that we have an object so has a
- 5:29:15kitchen object if we have a kitchen
- 5:29:16object then let's increase the timer by
- 5:29:19time. off time by the way here when
- 5:29:21working with a timer you can increase or
- 5:29:23decrease it's pretty arbitrary both ways
- 5:29:25work the obvious difference is only if
- 5:29:27you test if it's above the max or if
- 5:29:29it's under zero in here for frying it
- 5:29:31does make sense to start at zero and
- 5:29:32then the frying timer Max so you do that
- 5:29:35and if the frying timer if it is bigger
- 5:29:38than the maximum so let's get the frying
- 5:29:41re so frying recip so let's get the
- 5:29:44frying re so with input so let's get
- 5:29:46this kitchen object and get the kitchen
- 5:29:48object so okay so we go into the fry
- 5:29:51recipo and we get the fry timer Max okay
- 5:29:54so if it's above the max then this one
- 5:29:56has been fried so here let's just see
- 5:29:58what we did on the cutting counter so
- 5:30:00let's get this kitchen object and tell
- 5:30:02it to destroy itself and then let's go
- 5:30:05into the kitchen object class in order
- 5:30:07to spawn another kitchen object let's go
- 5:30:08into the frying recipe and spawn the
- 5:30:11output and we're going to spawn it
- 5:30:13inside of this
- 5:30:15counter all right so that's it this
- 5:30:17should already be working we don't have
- 5:30:19a visual yet so let's add a debug log so
- 5:30:21up here just a debug.log on the frying
- 5:30:24timer and up here let's also just reset
- 5:30:28the timer so frying timer let's put it
- 5:30:29on zerf and let's also do a debug.log
- 5:30:32and sa Pride however like this you might
- 5:30:35already be guessing that we're going to
- 5:30:36have a bunch of bugs but still let's
- 5:30:38just test it just like this okay so over
- 5:30:41here I can move around I can pick up
- 5:30:42some uncooked meat I can drop it there
- 5:30:45and after a little bit there you go
- 5:30:46there's the timers and Y there you go it
- 5:30:49did work you can see the timer increase
- 5:30:50until 3 then it was fried then it was
- 5:30:53reset and then we've got a null
- 5:30:54reference exception basically this is
- 5:30:57the exact same problem that we had on
- 5:30:58the cutting counter where first we put
- 5:31:00an object like tomato and that is indeed
- 5:31:02an input for a recipe so we cut tomato
- 5:31:05into slices but then the slices are not
- 5:31:07an input for any any recipe so over here
- 5:31:09we put some uncooked meat so that's
- 5:31:10great we fry it which means we destroy
- 5:31:13the uncooked meat and we spawn the
- 5:31:14cooked meat but then next time the
- 5:31:16cooked meat is not an input for anything
- 5:31:17so obviously this one is going to return
- 5:31:19null one thing we can do to sort of
- 5:31:21solve this problem which is also going
- 5:31:24to be beneficial in terms of performance
- 5:31:25is simply caching this field so let's go
- 5:31:28up here Define a frying recipe ASO
- 5:31:31frying recipe ASO instead of constantly
- 5:31:33getting it on every single update which
- 5:31:35might be a bit costly in terms of
- 5:31:37performance instead of this let's just
- 5:31:39get it over here when the player drops
- 5:31:40something so the player drops something
- 5:31:42and we assign the Frank recipo so we
- 5:31:44assign it cach the value and then do
- 5:31:46this okay that should have fixed the non
- 5:31:48reference problem but we still have a
- 5:31:50bunch more problems but still Let's test
- 5:31:52it out okay so here let's pick up some
- 5:31:54meat put it there and let's look at the
- 5:31:56timer and yep there you go everything is
- 5:31:58cooking great and yep there you go it
- 5:31:59finished it cooked and the timer was
- 5:32:01reset and now it's finishing it's
- 5:32:02cooking and so on so this is obviously
- 5:32:05another Prett serious problem basically
- 5:32:07it's constantly frying the meat and
- 5:32:08spawning more and more objects instead
- 5:32:10of constantly spawning from the same
- 5:32:12recipe what we want is for the stove to
- 5:32:14First fry the object but then if the
- 5:32:17object is fried then we want to burn it
- 5:32:19so really that means that we want the
- 5:32:21stove to have multiple States meaning
- 5:32:23that we're going to need to make a
- 5:32:24simple State machine so let's do just
- 5:32:26that now if you're a beginner the
- 5:32:28concept of a state machine might seem
- 5:32:30daunting at first but it's actually
- 5:32:31extremely simple at least to make a very
- 5:32:33basic one all we need is really just a
- 5:32:36bunch of States so to define those
- 5:32:37States let's go up here and make a
- 5:32:39simple enum so let's make a private enum
- 5:32:42call it
- 5:32:43State and now let's put all the states
- 5:32:45for our state machine now for the S
- 5:32:47let's say we have idle when there's
- 5:32:49nothing on top then let's say we have a
- 5:32:51frying state for when the ingredients is
- 5:32:53actually being fried then we have fried
- 5:32:56for when the ingredient has already been
- 5:32:57cooked but it's still getting some heat
- 5:32:59and finally if we leave it too long in
- 5:33:01that state then everything ends up
- 5:33:02burned okay so these are all of our
- 5:33:05states for our state machine and now to
- 5:33:07make the State machine it's actually
- 5:33:08quite simple first of all we just need
- 5:33:10to store the current state so up here
- 5:33:12make a private of type State and store
- 5:33:14the current state and then on update
- 5:33:17let's just do a switch on the current
- 5:33:19state and now here basically we're going
- 5:33:21to do different logic depending on the
- 5:33:22state that we're at so let's say if
- 5:33:24we're idle we do something then if we
- 5:33:27are frying we're going to do something
- 5:33:29else then if we are on the fry also
- 5:33:32something else and finally if we are on
- 5:33:34Burn do something else so here are all
- 5:33:37of our States and the logic that we did
- 5:33:39down here this is the Frank logic so
- 5:33:42let's actually just copy all this and
- 5:33:45let's paste it inside the Frank logic
- 5:33:47and for the state machine we're only
- 5:33:49going to run any of these states if
- 5:33:51there's a kitchen object inside of it so
- 5:33:52let's actually put that switch in there
- 5:33:54just like this okay so that's it so when
- 5:33:57idle we're not doing anything and when
- 5:33:59frying we're going to run our frying
- 5:34:00timer we're going to fry the object
- 5:34:02let's also get rid of the log we no
- 5:34:03longer need this then we destroy the
- 5:34:05current object and we spawn a brand new
- 5:34:07object now what we need is to handle
- 5:34:09over here the State field we need to
- 5:34:11modify this when changing states so
- 5:34:13first of all let's handle the start so
- 5:34:14let's make a private void
- 5:34:16start and on start let's begin with the
- 5:34:19state on state. idle okay great then
- 5:34:22down here when we interact when the
- 5:34:24player drops something when the player
- 5:34:25drops something that can be fried over
- 5:34:28here let's set the state and put it on
- 5:34:30state. frying and over here we should
- 5:34:33also probably reset the timer so let's
- 5:34:34set the frying timer back into zerf okay
- 5:34:37we the timer and we reset the state
- 5:34:40finally up here let's not reset the
- 5:34:42timer since we're resetting the timer
- 5:34:43down there since it makes more sense
- 5:34:45down there so we do the frying the
- 5:34:47frying timer we end up frying and then
- 5:34:48obviously we need to modify the state so
- 5:34:50modify State and put it on state. Fry
- 5:34:53okay so that's the basics of our saate
- 5:34:55machine with this everything should be
- 5:34:57working just the same as previously
- 5:34:58except we're only going to fry once so
- 5:35:00let's actually just put a log here debug
- 5:35:02on log object
- 5:35:06fried and let's put one down here
- 5:35:08outside of the state machine just do a
- 5:35:10debug. log on the
- 5:35:14state okay like this let's test okay so
- 5:35:17here we are let's pick up some meat and
- 5:35:19drop it on there and there you go goes
- 5:35:21from idle directly into frying and then
- 5:35:23it's fried and yep there you go now it
- 5:35:25stays on fried so it no longer goes on
- 5:35:27frying and it's no longer spawning any
- 5:35:29more objects it went from frying into
- 5:35:31fried and yep everything worked all
- 5:35:33right awesome so we have the fry State
- 5:35:35working perfectly now let's handle the
- 5:35:37the burning in terms of logic it's
- 5:35:39really going to be the exact same thing
- 5:35:41we're going to have a frying timer so
- 5:35:43let's copy this code and paste it down
- 5:35:45here now technically we could reuse the
- 5:35:48exact same float timer but that would be
- 5:35:50a bit confusing so let's keep our code
- 5:35:52as clear as possible and really just
- 5:35:54make a different timer with a more
- 5:35:55descriptive name so here a private float
- 5:35:59call it the burning
- 5:36:01timer then let's initialize this timer
- 5:36:03so when we go into the Fright State
- 5:36:05let's set the timer the burning timer
- 5:36:07into to zero then down here let's use
- 5:36:09this Burning timer okay great when timer
- 5:36:12is left and the object is spawn let's go
- 5:36:14into the burn Sate and obviously we need
- 5:36:17another recipe so let's make another
- 5:36:19scriptable object back in the editor
- 5:36:21let's find the frying recipe so let's
- 5:36:23duplicate this call it the burning
- 5:36:26recipe so then over here let's modify
- 5:36:29the name instead of frying timer Max
- 5:36:30let's call it burning timer Max okay
- 5:36:33great so now over here on the stove
- 5:36:35let's use pretty much the exact same
- 5:36:36thing and let's make over here private
- 5:36:39of burning recipe so the burning recipe
- 5:36:42so then down here we just need a
- 5:36:45function to get the burning recipe so so
- 5:36:46let's copy this and paste it over here
- 5:36:49this one is going to return a burning
- 5:36:51recipe so so let's replace this and this
- 5:36:54rename this into burning recipe so we're
- 5:36:58going to need an array and over here
- 5:36:59let's just change the name instead of
- 5:37:01frying recip so the burning recipe
- 5:37:04so and finally let's just find a new
- 5:37:07array so let's go all the way up here
- 5:37:08make another array an array of burning
- 5:37:11recipe so and this is the burning recipe
- 5:37:14so array and finally if we go down here
- 5:37:16let's use this array okay that's it so
- 5:37:18now let's use this function to set our
- 5:37:20burning recipo so when we set it to find
- 5:37:24let's set the burning recipe so and
- 5:37:26let's get it with the input and the
- 5:37:28input is going to be the object that is
- 5:37:29on here so the kitchen object. get the
- 5:37:32kitchen object as
- 5:37:35so okay so we're initializing our fright
- 5:37:38State and setting up the burning rest PS
- 5:37:40so and over here we use that one Max and
- 5:37:44we go into that one and use the output
- 5:37:46so over there object fried and over here
- 5:37:48object burned all right so that's pretty
- 5:37:50much it we modified everything to say
- 5:37:52burning timer over here we are correctly
- 5:37:54initializing so we go through the
- 5:37:56burning timer through the burning rest
- 5:37:57PSO which we are grabing up here then we
- 5:38:00spawn the output on the burning rest PSO
- 5:38:02and we go into state. burn okay so all
- 5:38:04that's left is just filling in this
- 5:38:05array so back the editor over here let's
- 5:38:08make the object so let's make a brand
- 5:38:10new folder for the burning recipe so and
- 5:38:14now inside let's create a new Burning
- 5:38:16recipe so call this one the meat Patty
- 5:38:20cooked into meat Patty burned and over
- 5:38:23here let's set the input so the meat
- 5:38:25Patty cooked onto the meat Patty burned
- 5:38:28and for timer let's make it take a bit
- 5:38:30longer to burn so let's say 5 Seconds
- 5:38:32okay that's great let's just drag the
- 5:38:34reference so let's go into the stove
- 5:38:35counter and let's make sure to open up
- 5:38:37and get go inside the prefab and over
- 5:38:39here on the prefab just drag the burning
- 5:38:41recipe okay that's great let's go
- 5:38:43outside save the prefab and let's test
- 5:38:45all right so here we are let's pick up
- 5:38:47some meat drop it on there and look over
- 5:38:49there it's frying and after a bit yep
- 5:38:51it's fried there you go it's spawned
- 5:38:52that one and now if we wait for 5
- 5:38:54seconds it should go from frying into
- 5:38:56burn and yep there you go that one is
- 5:38:57charred everything is burned everything
- 5:38:59is great all right awesome so everything
- 5:39:01worked as intended with this all of our
- 5:39:03logic is working now let's handle
- 5:39:05picking up objects from the stove now
- 5:39:07technically it's already working so I
- 5:39:09can approach the so and pick it up the
- 5:39:11object and there you go drop it in there
- 5:39:12so that does work however if we look
- 5:39:15over here in log the state machine is
- 5:39:16now in the wrong state so over here
- 5:39:19let's do a quick fix let's go down into
- 5:39:22the interact action okay so here it is
- 5:39:24so if there's no kitchen object then the
- 5:39:25player places it okay that's good but if
- 5:39:28there is a kitchen object so if there's
- 5:39:29something on the stove counter when the
- 5:39:31player picks it up let's also manually
- 5:39:33set the state and put the state back
- 5:39:36into idle just like this okay that's it
- 5:39:39so let's test okay so over here let's
- 5:39:42pick up some meat put it in there it's
- 5:39:43cooking and let's wait until it gets
- 5:39:46finished yep there you go it's done pick
- 5:39:47it up and there you go out now if I want
- 5:39:49I can put another one and yep there you
- 5:39:50go the logic is reset and everything is
- 5:39:52back to normal okay great so all the
- 5:39:55logic is working perfectly now let's
- 5:39:57just get rid of our log so we don't need
- 5:39:58this so let's get rid of that debug log
- 5:40:01this one and this one okay great
- 5:40:03everything is nice and clean and now
- 5:40:05let's add some nice fun visuals so if we
- 5:40:07go inside the stove counter and over
- 5:40:10here is the visual and I include these
- 5:40:12two prefabs inside the visual so one of
- 5:40:15them this one the stove on visual this
- 5:40:17one is just a glowing red square now
- 5:40:19again there's a weird bug on this
- 5:40:21specific un version so post procing
- 5:40:23isn't showing over here on scene view
- 5:40:25but if I leave it enabled and I go back
- 5:40:27outside and now if we look in the game
- 5:40:29view yep there you go there's a nice
- 5:40:31glowing red square if you don't see
- 5:40:33glowing make sure you add the bloom post
- 5:40:35rossing effect so if you missed
- 5:40:37something you can go back into the
- 5:40:38postprocessing lecture and make sure
- 5:40:39everything is set up correctly so
- 5:40:41there's a nice glowing red square and
- 5:40:43there's also a bunch of particles so you
- 5:40:45can enable this one press on restart and
- 5:40:47there you go just some nice particles
- 5:40:48just jumping up this was made with the
- 5:40:50unity particle system so for example on
- 5:40:53the Hier key you can right click go up
- 5:40:55here into effects and you can create a
- 5:40:57particle system so that's what this is
- 5:40:59it has a particle system over here you
- 5:41:01can see all of the various settings for
- 5:41:03these particles they just jump up and
- 5:41:05fall down so for jumping up that is the
- 5:41:08emission you can actually see a visual
- 5:41:10over there of the cone that is the
- 5:41:11spawning cone which you can find over
- 5:41:13here on the shape so in the shape it has
- 5:41:16the shape of a cone then you can see the
- 5:41:18radius radius thickness and so on so
- 5:41:19that is from where the objects are being
- 5:41:21spawned then up here you can see the
- 5:41:23lifetime of each object so each particle
- 5:41:25is going to last for 7 Seconds you can
- 5:41:28also see the speed so that's speed at
- 5:41:30which they come from there the start
- 5:41:32size that's how big they are on start
- 5:41:34and note how the particles are spawning
- 5:41:36jumping up and and falling down so that
- 5:41:39Falling Down is over here the gravity
- 5:41:41modifier if you put it at zero then they
- 5:41:43just keep going up and if you put at two
- 5:41:45yep they go up and they fall down next
- 5:41:48down here on the emission this is how
- 5:41:49many are being spawned so if I put this
- 5:41:51on 200 there you go tons and tons of
- 5:41:53particles next is over here the size
- 5:41:55over lifetime so this one has just a
- 5:41:57basic curve so they start off on full
- 5:41:59size and over the x-axis this one is the
- 5:42:03lifetime so as the particle goes from
- 5:42:05the beginning until the end of their
- 5:42:06life they basically go down on size so
- 5:42:07that is why they become quite a bit
- 5:42:09smaller also by the way this window down
- 5:42:10here this one is called an animation
- 5:42:12curve this is another really useful
- 5:42:14Unity feature I have a dedicated video
- 5:42:16on animation curves and finally down
- 5:42:18here just have the renderer so we're
- 5:42:20just using some basic particles so we
- 5:42:22can inspect the material it's including
- 5:42:24the assets and there you go we're just
- 5:42:25using the default particle material just
- 5:42:28with the alpha on half and that's pretty
- 5:42:29much it so as you can see just a very
- 5:42:32basic very simple particle system now
- 5:42:34all we really want to do is just for
- 5:42:36both of these we want to enable or
- 5:42:38disable them depending on if the stove
- 5:42:40is on or not so let's make a script to
- 5:42:42handle the visuals so let's go down and
- 5:42:44create a brand new C script let's call
- 5:42:46it the stove counter visual then let's
- 5:42:49go into the stove counter Visual and
- 5:42:51let's attach the script so here it is
- 5:42:54attach it and open all right so now here
- 5:42:56we just need references to those two
- 5:42:58objects so as usual let's make a basic
- 5:43:00serialized field let's make it of type
- 5:43:02game object for the stove on game object
- 5:43:06and the other one is the particles game
- 5:43:09object okay let's save and back here in
- 5:43:12the editor let's rag the references so
- 5:43:14the stove on Visual and the sizzling
- 5:43:16particles okay great so now all you
- 5:43:18really need to know is know when to turn
- 5:43:20these on or off and for that is really
- 5:43:22going to be based on the state over here
- 5:43:24on the stove counter so if it is on the
- 5:43:26state frying or fry then we want to show
- 5:43:28them if it is on idle or burned we want
- 5:43:30to hide them but as usual we don't want
- 5:43:32to mix the logic and visuals directly so
- 5:43:34let's do that through a really nice
- 5:43:36event let's make a public event let's
- 5:43:39use a standard event handler let's call
- 5:43:42it on state
- 5:43:44changed and let's also include the state
- 5:43:46on the event arcs so let's make a public
- 5:43:48class call it on state change event arcs
- 5:43:52and let's expand event ARs and then in
- 5:43:55here let's just put a public state for
- 5:43:59our state however here we also have a
- 5:44:01really nice error so this one is telling
- 5:44:03you there's inconsistent accessibility
- 5:44:06basically that's because we made this
- 5:44:07one public so any class like for example
- 5:44:10our visual class can indeed see this
- 5:44:11class however from outside that class
- 5:44:14cannot see the private state so that is
- 5:44:17why we have inconsistent accessibility
- 5:44:19we cannot have something public which
- 5:44:21inside has something of a specific type
- 5:44:22which is private so in order to make
- 5:44:25this work we need to modify this state
- 5:44:26and make it public so that the other
- 5:44:28classes can see it okay so that's great
- 5:44:30now let's just fire this event whenever
- 5:44:32the state changes so over here when you
- 5:44:34go into the frying State let's go and
- 5:44:37and invoke and as usual just
- 5:44:39this and I actually forgot to add that
- 5:44:42so let's go up here let's use the one
- 5:44:44with generics so the on state change
- 5:44:46event arcs okay great so then down here
- 5:44:48when invoke the event let's create of
- 5:44:51this type and inside passing the state
- 5:44:53equals this state okay so this all we
- 5:44:56need so then down here going into the
- 5:44:58burn State let's fire the event and down
- 5:45:00here frying fired the event and on idle
- 5:45:02fr the event all right that's it so we
- 5:45:05have all our state logic and over here
- 5:45:07on the stove counter visual obviously we
- 5:45:09need a reference to the counter so let's
- 5:45:11add that so A serialized field private
- 5:45:15make it up type stove counter for the
- 5:45:17stove counter and then we can do and as
- 5:45:20usual for accessing external references
- 5:45:22let's do it on start go into the stove
- 5:45:24counter and let's listen to the on state
- 5:45:27changed
- 5:45:28event and over here it's going to be
- 5:45:30very simple we just want to show if it's
- 5:45:32on the state frying or fried and if not
- 5:45:35we don't want to show so let's define a
- 5:45:37B call it show Visual and this one is
- 5:45:39going to true if the e. State equals the
- 5:45:42state. fry or e. State equals D state.
- 5:45:48frde so if it's out of these and this
- 5:45:50going to be true if not it's going to be
- 5:45:52false so then let's just go into the
- 5:45:54stove on game object and call sent
- 5:45:57active and pass in this and same thing
- 5:46:00for the other for the particles game
- 5:46:02object okay that's it super simple let's
- 5:46:05just drag this reference so over here
- 5:46:07inside the prefab just drag the
- 5:46:08reference let's leave the prefab save
- 5:46:10the changes and let's set on play and
- 5:46:13all right so it starts off disable Okay
- 5:46:15so there's no visual now if I pick up
- 5:46:16and I drop it and there you go a nice
- 5:46:18visual so the glowing red hot and the
- 5:46:20particles and now it's frying and if I
- 5:46:22leave it until it burns when it burns
- 5:46:24then it's going to turn it off and there
- 5:46:25you go it turns off all right awesome so
- 5:46:27now if I pick it up wait until it gets
- 5:46:30cooked so it's cook pick it up and there
- 5:46:32you go turns it off all right awesome
- 5:46:35we've got a really nice visual all
- 5:46:37that's left is to have a proper visual
- 5:46:39progress bar and with this we actually
- 5:46:41have another interesting clean code
- 5:46:42question right now the progress bar that
- 5:46:45we made over here on the cutting counter
- 5:46:47that one is great so we would like to
- 5:46:49reuse that however if we look over here
- 5:46:51on the progress bar UI we can see this
- 5:46:53is only working with the specific type
- 5:46:55cutting counter so by default this will
- 5:46:58not work with a stove counter so as
- 5:47:00usual we have multiple approaches to
- 5:47:02solving this problem one option would be
- 5:47:04to Simply complely duplicate the script
- 5:47:07then we would make a completely
- 5:47:08different progress bar UI class that
- 5:47:10would work only with the Ste counter so
- 5:47:12that's one approach that would work and
- 5:47:14that approach might be good if you want
- 5:47:16the progress bar to behave very very
- 5:47:18differently but over here I want both
- 5:47:20them to behave exactly the same so
- 5:47:22instead of having some code duplication
- 5:47:24we can write some good clean code but
- 5:47:26doing exactly what we did with regards
- 5:47:28to the kitchen object parent meaning we
- 5:47:30can use a nice interface we can then
- 5:47:32Implement on anything that has some kind
- 5:47:34of progress so let's do exactly that
- 5:47:36first of all let's actually go inside
- 5:47:38the cutting counter so let's go inside
- 5:47:40the prefab and over here we've got the
- 5:47:42progress bar and this one is just a
- 5:47:43regular game object but since we're
- 5:47:45going to reuse this let's make this a
- 5:47:46proper prefab so let's find over here
- 5:47:49all of our prefabs and just drag the
- 5:47:51progress bar UI inside the prefabs
- 5:47:52folder okay great so this is now a
- 5:47:54proper prefab now let's define our
- 5:47:56interface so let's create a brand new C
- 5:47:59script as usual interface start with I
- 5:48:01so let's call it I and for this one we
- 5:48:03wanted to represent anything that has
- 5:48:05progress so let's just call it literally
- 5:48:07has progress personally I like to use
- 5:48:10the word has to indicate that a certain
- 5:48:12object has certain Behavior so in this
- 5:48:14case objects that implement this
- 5:48:15interface will have some kind of
- 5:48:17progress Behavior so now over here for
- 5:48:19the interface let's first make it so
- 5:48:20this one does not extend mod of behavior
- 5:48:22instead of a class this one is an
- 5:48:24interface okay great so now for the
- 5:48:27functions that we're going to need if
- 5:48:29we'll look in the progress bar and we'll
- 5:48:30look at the cutting counter references
- 5:48:31we can see the only one is literally
- 5:48:33just this so we just have to listen to
- 5:48:35the event and then the rest of progress
- 5:48:37bar Works inside of it so real the
- 5:48:39interface is the only thing we need to
- 5:48:41Define so let's actually go inside the
- 5:48:42cutting counter so here we have the on
- 5:48:45progress change event and then we have
- 5:48:46this so we can literally just copy this
- 5:48:48go into the I has progress and let's put
- 5:48:50exactly this okay that's it that is
- 5:48:53literally all we need now if we wanted
- 5:48:55we could also make a function to expose
- 5:48:57the progress amount but since we
- 5:48:58included over here on the event then we
- 5:49:00really don't need it just this is enough
- 5:49:02now let's go over here on the progress
- 5:49:04bar UI script and instead of working
- 5:49:06with the type cutting counter instead
- 5:49:07let's work with a type that has I has
- 5:49:09progress so let's rename this to has
- 5:49:13progress and it's going to have the
- 5:49:15exact same event the only difference is
- 5:49:16over here instead of the event RX being
- 5:49:19the one inside the cutting counter is
- 5:49:20the one inside the I has progress so
- 5:49:22let's make sure to change this I has
- 5:49:24progress okay so the signature matches
- 5:49:26let's just obviously rename this so
- 5:49:29let's rename instead of cutting counter
- 5:49:31let's rename has progress on progress
- 5:49:34changed and that's pretty much it we
- 5:49:35don't have any more errors so everything
- 5:49:37over here is now working nicely with our
- 5:49:40interface and back here in the editor
- 5:49:42once we're still inside the cutting
- 5:49:43counter suddenly interfaces do have one
- 5:49:46downside when it comes to Unity if we
- 5:49:48look in the progress bar UI down there
- 5:49:50we can see the progress bar UI and
- 5:49:52previously we had the counter field
- 5:49:54exposed in the editor however now by
- 5:49:56changing into an interface there we have
- 5:49:58the issue the field does not show up
- 5:50:00here interfaces do not show up in the
- 5:50:02editor because Unity basically has no
- 5:50:04way of knowing that the interface will
- 5:50:05be implemented by some kind of game
- 5:50:07object so sadly this is the one thing
- 5:50:09that doesn't work very well with unity
- 5:50:11the solution that I normally do is
- 5:50:13actually pretty simple instead of
- 5:50:14exposing the interface which does not
- 5:50:16work instead let's just make this a
- 5:50:18regular private field and then let's
- 5:50:20make a serialized field and for this one
- 5:50:22let's make it of type game object and
- 5:50:24let's call it has progress game
- 5:50:26object okay so like this we have a
- 5:50:29regular serialized field with a regular
- 5:50:30game object so if you look here yep we
- 5:50:32do have that field so now we can indeed
- 5:50:35Drag The Cutting counter reference and
- 5:50:37then over here in the code in order to
- 5:50:39get the has progress that is super
- 5:50:40simple has progress we just go into the
- 5:50:43has progress game object and get
- 5:50:44component of type I has progress okay so
- 5:50:48that's it now our code does work however
- 5:50:50of course one big potential issue with
- 5:50:52this is that over here we have a field
- 5:50:54of type game object meaning that we have
- 5:50:56no guarantee that this field does have a
- 5:50:59component that implements the interface
- 5:51:00so we cannot make sure that we drag the
- 5:51:02correct reference we can drag any
- 5:51:04reference doesn't have to have our
- 5:51:06progress interface so in order to keep
- 5:51:08ourselves safe let's add a nice safety
- 5:51:10warning so over here if has progress
- 5:51:12equals null so if this one is n that
- 5:51:14means that that game object does not
- 5:51:16have any progress interface if so let's
- 5:51:18do a debug.log
- 5:51:21error and let's say the game object and
- 5:51:24let's pass in this game
- 5:51:28object does not have a component that
- 5:51:31implements I has
- 5:51:34progress so this way if we make a
- 5:51:36mistake we will have a nice error
- 5:51:38message basically this is the one
- 5:51:40workaround that you need to use since
- 5:51:41city does not support dragging
- 5:51:43references in the editor if they are
- 5:51:45interface references okay so with that
- 5:51:48everything is good so all of our
- 5:51:49progress bar UI this should all be
- 5:51:51working perfectly we just need to go
- 5:51:53over here into our cutting cter script
- 5:51:56and let's make it so that we Implement
- 5:51:57our interface so I has progress and we
- 5:52:00got an error just because even though we
- 5:52:02did Define that interface member the on
- 5:52:04progress change again keep in mind that
- 5:52:06the the types depend on not just their
- 5:52:08name but where they're at so this type
- 5:52:10that we have here is the one that we
- 5:52:12Define here which is not the same one
- 5:52:14that we have here so even though they
- 5:52:15have the exact same name because they
- 5:52:17are in different places they are
- 5:52:18actually different types so we need to
- 5:52:20make sure to use the type in the
- 5:52:21interface over here let's just go into
- 5:52:23the I has progress and use that exact
- 5:52:25type and get rid of this one okay so
- 5:52:27that's it that's the change we need and
- 5:52:28down here when firing let's just fire
- 5:52:30with that type and down here the same
- 5:52:32thing with that type okay great so like
- 5:52:35this The Cutting counter should still be
- 5:52:37working exactly the same as previously
- 5:52:39again when refactoring any code always
- 5:52:41do a quick test so let's do that let's
- 5:52:43make sure to save our counter save the
- 5:52:45prefab go back outside hit on play now
- 5:52:47let's pick up some cheese put it there
- 5:52:49cut and there you go the progress bar
- 5:52:50still does work okay great now let's
- 5:52:53apply to the stove and that is actually
- 5:52:54going to be very simple first let's go
- 5:52:56inside the stove so let's find the stove
- 5:52:58counter let's open it up go inside the
- 5:53:00prefab and over here let's drag the
- 5:53:02progress bar UI prefab so let's drag
- 5:53:04that then down here we already has the
- 5:53:06has progress game object so let's drag
- 5:53:07the stove counter and that's it there's
- 5:53:09nothing else we need to touch here we
- 5:53:11just need to go over here into the stove
- 5:53:13counter and it's usual let's implement
- 5:53:15the interface so the I has progress and
- 5:53:18now let's implement it pretty much just
- 5:53:20like we did on the cutting counter so we
- 5:53:21can actually just copy this so we just
- 5:53:23need to implement the event so that's it
- 5:53:26and now for firing the event let's go
- 5:53:28down and see where we are modifying all
- 5:53:30our timers so let's go down to when the
- 5:53:33player drops something so we do the
- 5:53:35onite change and now now let's invoke
- 5:53:37this event so this and for the progress
- 5:53:40bar for the progress normalize this one
- 5:53:42is very simple so just frying timer
- 5:53:45divided by the frying
- 5:53:46recipo do frying timer Max okay that's
- 5:53:50it we are modifying the progress now
- 5:53:51let's go up here when we are in the
- 5:53:53frying State and when we do let's fire
- 5:53:56off the on progress change event okay
- 5:53:58great and finally down here when we have
- 5:54:01the FR over here let's also fire except
- 5:54:04obviously we have the burning timer and
- 5:54:06and the burning timer Max and then just
- 5:54:08to make sure that the bar actually hides
- 5:54:11itself when we go into burn let's also
- 5:54:13fire an event this one doesn't have a
- 5:54:14timer so let's just put it on zerf okay
- 5:54:16that's really it we don't need to touch
- 5:54:19the progress bar UI at all Let's test
- 5:54:21this just make sure to save the prefab
- 5:54:24let's go back outside and head on play
- 5:54:26and right away yep the bar is inde need
- 5:54:28hidden now if I pick up some meat and I
- 5:54:29drop it and there you go got a really
- 5:54:31nice bar going up and yep going up on
- 5:54:34the burning State and as it gets to the
- 5:54:35end let's see if the bar hides so it
- 5:54:37gets to the end and if there you go the
- 5:54:39bar does hide all right awesome and if I
- 5:54:42pick up something actually this was the
- 5:54:44one event that we forgot so let's fix
- 5:54:45that so let's just copy the one where we
- 5:54:47set the progress normalize to zero and
- 5:54:49over here if the player picks up
- 5:54:50something let's set the progress back
- 5:54:52into zero so here we are let's pick up
- 5:54:55some meat drop it on there okay let's
- 5:54:57wait for it to be cooked okay it's
- 5:54:59cooked now before it burns pick it up
- 5:55:01and there you go the bar is gone all
- 5:55:03right awesome okay so here we have again
- 5:55:06another example of the power of writing
- 5:55:08good clean code we made a nice generic
- 5:55:11progress bar and we very easily made it
- 5:55:12work with a completely different counter
- 5:55:15which of course would also work with
- 5:55:16literally anything that implements that
- 5:55:17interface doesn't have to be a counter
- 5:55:19now let me make one note here basically
- 5:55:22I showed you how to make a generic
- 5:55:23progress bar and reuse it but let's say
- 5:55:25you want to do something specific just
- 5:55:27for the so well one approach like I
- 5:55:29mentioned is to duplicate the code and
- 5:55:31make a progress bar that works only with
- 5:55:33stove but another approach is to Simply
- 5:55:35add more elements on top for example
- 5:55:38during the Polish stage we're going to
- 5:55:40do exactly that we're going to add an
- 5:55:42extra UI element that will show up to
- 5:55:44warn the player when the food is about
- 5:55:45to burn so I just wanted to point that
- 5:55:47out how you can mix and match both them
- 5:55:49you can have both generic components
- 5:55:51coupled with specific components but for
- 5:55:54now our progress bar everything is
- 5:55:55looking pretty good so let's leave that
- 5:55:57burden warning just for the poly stage
- 5:55:59now the next very important thing we
- 5:56:01need is some plates so let's do that in
- 5:56:02the next lecture hello and welcome I'm
- 5:56:05your Cod
- 5:56:07in this lecture we're going to create
- 5:56:08the plates counter this one is just
- 5:56:10going to spawn some plates which we can
- 5:56:12then pick up to grab some objects okay
- 5:56:14so let's begin making the counter as
- 5:56:16usual so let's go inside our prefabs
- 5:56:18inside our counters right click the base
- 5:56:20counter make a new prefab variant called
- 5:56:24the plates counter let's go inside and
- 5:56:28let's drag the visual for the plates
- 5:56:30counter let's go into scene view so we
- 5:56:31can see it okay let's duplicate this
- 5:56:34make this the selected let's go inside
- 5:56:36side and we can actually hide the cirle
- 5:56:38Sprite we only need this one so on this
- 5:56:40one let's modify it for the counter
- 5:56:41selected on the selected let's make it
- 5:56:44just 1% bigger and let's add the
- 5:56:47selected counter visual okay then inside
- 5:56:49obviously drag the reference for the
- 5:56:51kitchen counter okay that's our basic
- 5:56:53setup now let's make our script to run
- 5:56:55this so let's create a brand new C
- 5:56:57script for the plates counter let's
- 5:57:00attach the scrip to the plates counter
- 5:57:02and open okay now here as usual let's
- 5:57:05extend our base counter and then first
- 5:57:08let's handle the spawn timer logic so
- 5:57:10basically we want to spawn some plates
- 5:57:12every once amount of time so let's s a
- 5:57:15simple float for the spawn plate timer
- 5:57:19then let's make a simple update on timer
- 5:57:21let's increase SP Point timer by time.
- 5:57:24Delta
- 5:57:26time and then just check if it's above a
- 5:57:29certain
- 5:57:30maximum so if it is above something in
- 5:57:33this case we're going to have a fixed
- 5:57:35value but still like I mentioned in the
- 5:57:37very beginning of this course let us not
- 5:57:39use magic numbers here you should never
- 5:57:41use magic numbers instead if you wanted
- 5:57:43to make it editable you could also make
- 5:57:45it appear as a serialized field but in
- 5:57:47my case for design that I'm going for
- 5:57:48I'm perf content with having a fixed
- 5:57:50value so just appear pretty simple the
- 5:57:53spawn plate timer Max and let's defa it
- 5:57:56to
- 5:57:57forf and let's use it over here okay
- 5:58:00great so this what we want however for
- 5:58:03spawning it's actually going to be a bit
- 5:58:05tricky the the plate is supposed to be a
- 5:58:07kitchen object the player should be able
- 5:58:10to carry the plate and right now for
- 5:58:12design that we Define is that each
- 5:58:13kitchen object can only have one parent
- 5:58:16and each parent can only have one object
- 5:58:18but over here we want to spawn multiple
- 5:58:20objects now let's quickly see what
- 5:58:22happens if we try spawning multiple as
- 5:58:23usual so let's just go into the kitchen
- 5:58:25object spawn a kitchen object which
- 5:58:28means we need the plate so so let's do
- 5:58:30it up here as usual a serialized fi
- 5:58:33private kitchen objecto for the plate
- 5:58:36kitchen object
- 5:58:39so so we're going to need to make this
- 5:58:41and then we're just going to spawn this
- 5:58:43object on
- 5:58:45this okay so this is going to throw an
- 5:58:47error but still let's see let's first
- 5:58:49create the object over here let's go
- 5:58:51inside our script M objects our kitchen
- 5:58:53objects let's create the brand new
- 5:58:55kitchen object call it just the plate
- 5:58:57for the object name this one is a plate
- 5:58:59for the Sprite let's go with the plate
- 5:59:02Sprite and for the prefab let's make it
- 5:59:05so let's see duplicate one of these call
- 5:59:07it the
- 5:59:08plate let's go inside it and obviously
- 5:59:11make sure to change save the changes
- 5:59:13then over here let's drag the plate
- 5:59:15visual get rid the tomato and on the
- 5:59:18plate let's make sure to assign the
- 5:59:20plate and finally let's exit this let's
- 5:59:23make sure to save it and on the plate
- 5:59:24let's drag the plate prefab okay so we
- 5:59:27have the kitchen object ASO now let's
- 5:59:29just go inside our plates counter and
- 5:59:32over here let's drag the reference so
- 5:59:34the reference to the plate kitchen
- 5:59:36object let's also drag the reference to
- 5:59:38the counter top point then on the
- 5:59:39selected drag the reference to our base
- 5:59:41counter and finally start off with the
- 5:59:43selected disabled okay so this should be
- 5:59:45working let's just add a plate counter
- 5:59:47over here onto our scene so let's pick
- 5:59:49up a plates counter and put it somewhere
- 5:59:51in here over there on the side so on an
- 5:59:53X of 7.5 then zero and let's say on zero
- 5:59:57maybe let's make sure we have space for
- 6:00:00one more counter over there so let's
- 6:00:01duplicate this empty counter and let's
- 6:00:04put it over there pointing to the side
- 6:00:05so this one is on 7.5 0 and minus
- 6:00:092 okay so now let's just make sure that
- 6:00:11they perfectly match so let's put this
- 6:00:13one on a set of
- 6:00:15minus5 okay so let's test all right so
- 6:00:18here we are and look at that and after 4
- 6:00:20seconds yep there you go it spawns the
- 6:00:22object and then it immediately tried to
- 6:00:24spawn another one and there you go we
- 6:00:26have the error kitchen object parent
- 6:00:28already has a kitchen object basically
- 6:00:30the way we designed our game and set up
- 6:00:32the code assumes that a single counter
- 6:00:33will only hold a single kitchen object
- 6:00:36so we cannot have multiple plates on the
- 6:00:38same counter now one solution for this
- 6:00:40problem is actually quite simple when we
- 6:00:42spawn the plates instead let's not spawn
- 6:00:45a kitchen object instead we're just
- 6:00:47going to spawn a dumb visual then when
- 6:00:50the player interacts with the counter
- 6:00:51that is when we're going to spawn the
- 6:00:53proper kitchen object so let's do that
- 6:00:55although again let's keep the logic and
- 6:00:57the visual separate so over here let's
- 6:00:59first just handle the logic so we just
- 6:01:01need to keep track of how many plates we
- 6:01:03spawn so for that let's sort up here a
- 6:01:05private t for the plates spawn amount
- 6:01:09and let's also do another private in for
- 6:01:11the plates spawn amount
- 6:01:16Max and let's say we can spawn at most
- 6:01:18four plates okay so over here instead of
- 6:01:21spawning the object let's first of all
- 6:01:23actually reset the timer so let's put it
- 6:01:25back to 0 0 and on the plate spawn
- 6:01:28amount let's check if this one is under
- 6:01:31the plate spawn
- 6:01:33Max and if so
- 6:01:37let's go into the plate spawn amount and
- 6:01:39increase it by one okay so that's a
- 6:01:41logic super simple now let's send the
- 6:01:43visual so let's first make our script so
- 6:01:46let's create a brand new C script for
- 6:01:48the plates counter
- 6:01:51visual now let's make sure to the visual
- 6:01:53so let's go inside the prefab and over
- 6:01:55here we've got the visual let's attach
- 6:01:57it okay open now here basically the
- 6:01:59first thing we need is we need to know
- 6:02:01where to spawn the visuals so let's
- 6:02:03actually add a reference to our counter
- 6:02:04top point so let's add a serialized
- 6:02:07field for private transform for the
- 6:02:10countertop point then let's also add a
- 6:02:13reference for the prefab we're going to
- 6:02:14spawn so let's call it the plate visual
- 6:02:16prefab then here in the editor let's rag
- 6:02:19the references so the counter top Point
- 6:02:21Place it in there and for the plate
- 6:02:22visual prefab let's go up here and find
- 6:02:25the visuals for the kitchen object so
- 6:02:27these are just the visuals and let's rag
- 6:02:29the plate visual so the plate visual not
- 6:02:31the plate citch an object okay now back
- 6:02:33in the code here we obviously need to
- 6:02:35know when it plate is spawned so let's
- 6:02:37go into the plates counter and make a
- 6:02:38nice event so public event event handler
- 6:02:42as usual on Plat
- 6:02:44spawn and down here let's just fire the
- 6:02:47event so we just
- 6:02:50invoke with this and event.
- 6:02:55empty okay that's it very simple and
- 6:02:57then on the other script over here let's
- 6:02:59just listen to it which also means that
- 6:03:01we need a reference to our counter so
- 6:03:02let's add up here the plates counter for
- 6:03:05the ples counter so we're going to need
- 6:03:07to drag the reference and then on start
- 6:03:10let's listen to the on plate spawn event
- 6:03:12and when that happens then let's Spa so
- 6:03:14let's call instantiate on the plate
- 6:03:17visual prefab let's put it inside the
- 6:03:20counter top point so this the transform
- 6:03:22for the plate visual transform and
- 6:03:26that's pretty much it okay so like this
- 6:03:28it should be working when the plate is
- 6:03:30spawned we should be spawning a brand
- 6:03:31new visual back in the editor we just
- 6:03:33need to drag the plates counter
- 6:03:34reference like that
- 6:03:36let's exit save the prefab and let's
- 6:03:38test okay so here we are and if we wait
- 6:03:41for 4 seconds we should be able to see a
- 6:03:42PL spot yep there you go and if we wait
- 6:03:45for a little bit more we should also be
- 6:03:47able to see some more plates being spawn
- 6:03:49except we can't really see them that's
- 6:03:51because we're spawning them on the exact
- 6:03:52same spot every time but if we pause the
- 6:03:55game and over here look in the Hier key
- 6:03:57and find the plates counter and inside
- 6:03:59the counter top Point yep we do have
- 6:04:01four visions and if we wait for longer
- 6:04:03then nope it's not going to spawn
- 6:04:05anymore it's only going to spawn four
- 6:04:06plates okay great so to solve the vision
- 6:04:09let's just offset them by a tiny bit to
- 6:04:12know how much we should offset let's
- 6:04:13keep track of how many plates haven't
- 6:04:15spawned so let's store up here on the
- 6:04:18visual script a list of Game object call
- 6:04:21it the plate visual game object
- 6:04:24list let's also make sure to initialize
- 6:04:27this so let's do on awake let's
- 6:04:29initialize this list and then when we
- 6:04:32spawn them okay so here we have the
- 6:04:33object that we spawned now basally we
- 6:04:36just need to modify the local
- 6:04:38position and let's put it on new Vector
- 6:04:403 on the X let's put it on zero then on
- 6:04:43the Zed we're also going to have zero
- 6:04:45and then over here on the while let's
- 6:04:46offset it by a certain amount and
- 6:04:48basically it's going to be based on how
- 6:04:49many plates have been spawned so let's
- 6:04:52define up here a float for the plate
- 6:04:54offset y let's put it at say
- 6:04:570.1f and over here we're going to offset
- 6:04:59it by this much multiplied by how many
- 6:05:01plates have been spawned so we can go
- 6:05:03into our visual list. count so you can
- 6:05:05do like this and then we just need to
- 6:05:06add it to the list so let's add this
- 6:05:09plate visual transform. game object okay
- 6:05:12so now each game object should spawn at
- 6:05:14a different height so let's see so here
- 6:05:16we are and if we wait for 4 seconds we
- 6:05:18should be able to see a plate and there
- 6:05:19you go and now after 4 seconds we should
- 6:05:22be able to see another one place
- 6:05:23slightly above and yep there it is okay
- 6:05:25great so everything is spawning
- 6:05:28perfectly both in the logic as well as
- 6:05:30the visual now let's actually pick up a
- 6:05:31plate so on the plates counter as usual
- 6:05:34let's implement the interact
- 6:05:36so let's do a public let's override the
- 6:05:38interact function and now for picking up
- 6:05:41let's first see if the player is
- 6:05:43actually
- 6:05:44empty-handed so if and we check the
- 6:05:47player has kitchen object so if the
- 6:05:49player does not have a kitchen
- 6:05:52object then the player is empty-handed
- 6:05:55okay great then let's see if we have a
- 6:05:57plate that we can give them so if the
- 6:06:00plate spawn amount if it is bigger than
- 6:06:04zero then there's at least one plate
- 6:06:07here and if so let's give it to the
- 6:06:09player so how we do that is well over
- 6:06:11here for the logic let's just increase
- 6:06:13it by one then let's actually spawn the
- 6:06:16object so on the kitchen object let's
- 6:06:18spawn the Plate Kitchen object so and
- 6:06:21spawn it on the player and finally we
- 6:06:23just need to update the visuals so let's
- 6:06:26make another event so up here on PL
- 6:06:28spawn and on plate
- 6:06:31removed okay we have this event and then
- 6:06:34down here let's just whenever the player
- 6:06:35picks it up let's invoke this with this
- 6:06:38in event
- 6:06:40arsmt okay great so now on the visual
- 6:06:43let's listen to this so over here on
- 6:06:45start for the plates counter listen to
- 6:06:47this event and when this event happens
- 6:06:50we just want to destroy the VAR last
- 6:06:51plate so let's grab the game object for
- 6:06:54the plate game object and we're
- 6:06:56basically just going to go into our list
- 6:06:58so the plate visual game object list and
- 6:07:01let's pick up the very last one so let's
- 6:07:04go into the list. count minus is one so
- 6:07:06this is going to be the very last
- 6:07:07element of the list then let's remove
- 6:07:09this one from the list so plate. remove
- 6:07:12this one that we just grabbed and then
- 6:07:14we simply call destroy on this
- 6:07:16one all right so that's it super simple
- 6:07:19so we on the plates counter we do all of
- 6:07:21our checks we cut it down by one we
- 6:07:24spawn the actual kitchen object and we
- 6:07:25fire the event and over here the event
- 6:07:27listens and updates the visual okay
- 6:07:29let's test so here we are let's wait for
- 6:07:31a plate to be spawned and when it
- 6:07:33spawned there it is I'm going to pick it
- 6:07:35up and Y there you go the player is now
- 6:07:36carrying a plate let's drop it here and
- 6:07:38there you go there's another one now
- 6:07:39let's wait for a bunch more to be
- 6:07:40spawned okay so the plat counter is full
- 6:07:43now if I pick up it should only
- 6:07:44eliminate the last visual pick it up and
- 6:07:46yep there you go it eliminate that one
- 6:07:48now I can drop it in there and Y there
- 6:07:49you go another in onean all right
- 6:07:51awesome okay so that's really it for the
- 6:07:53basics of the plate counter it
- 6:07:55periodically spawns some plates which
- 6:07:57the player can then pick up now in the
- 6:07:59next lecture we're going to add the
- 6:08:01ability for the player to be holding a
- 6:08:03plate and pick up another object onto
- 6:08:04the plate
- 6:08:06hello and welcome I'm your Cod monkey in
- 6:08:09this lecture we're going to add the
- 6:08:10ability for the player to be carrying a
- 6:08:12plate and pick up objects onto that
- 6:08:14plate okay so here we already have the
- 6:08:16plate counter working it has some basic
- 6:08:18logic after a bunch of time it spawns a
- 6:08:20plate it spawns up to a certain maximum
- 6:08:23and I can pick up a plate and yep the
- 6:08:25player is carrying a plate so I can put
- 6:08:27it anywhere then I can for example pick
- 6:08:29up some Tomatoes slice them and pick
- 6:08:32them up however now I am not able to
- 6:08:34place the tomatoes on the plate so let's
- 6:08:36add that logic let's begin over here on
- 6:08:38the clear counter script first we're
- 6:08:40testing if there's no catching object
- 6:08:42here and the player is carrying
- 6:08:43something that the player drops
- 6:08:44something in there but then we're
- 6:08:46testing if there is a kitchen object
- 6:08:47here and if the player is carrying
- 6:08:49something so it's over here that we want
- 6:08:51to check if this something that the
- 6:08:52player is carrying if it is a plate now
- 6:08:54our plate is also going to have a bit of
- 6:08:56custom logic so to help both identify
- 6:08:59and hold that custom logic let's make a
- 6:09:01proper script to handle it so back in
- 6:09:03unity let's create a brand new script
- 6:09:05script call it the Plate Kitchen object
- 6:09:09and let's open this now over here on
- 6:09:11this one instead of extending mono
- 6:09:13Behavior we're going to extend kitchen
- 6:09:15object so the plate is really just a
- 6:09:18more specific type of a kitchen object
- 6:09:20again like I mentioned quite a while ago
- 6:09:22you want to be very careful with
- 6:09:23inheritance you need to have a very good
- 6:09:25reason to do it here we want the play to
- 6:09:28behave exactly like a kitchen object
- 6:09:30just with a tiny bit of extra logic so
- 6:09:31in this case it makes perfect sense
- 6:09:33let's just go ahead and save this and
- 6:09:35wait for un to compile and over here
- 6:09:38let's find our kitchen object with the
- 6:09:40plate so here there's a pream as you can
- 6:09:42see we have a kitchen object now instead
- 6:09:44of having that one let's replace that
- 6:09:45with the Plate Kitchen object and since
- 6:09:48we are extending kitchen object we have
- 6:09:49the same Fields so let's make sure to
- 6:09:51add the kitchen object as so and get rid
- 6:09:53of the other one okay great so now back
- 6:09:56here on the clear counter when there is
- 6:09:58a kitchen object here and the player is
- 6:09:59carrying something we can check if the
- 6:10:02player is holding a plate and for that
- 6:10:04we can check the type
- 6:10:05so if let's go into the player and let's
- 6:10:08get the kitchen object the player is
- 6:10:09holding and we test if this object is of
- 6:10:12type Plate Kitchen
- 6:10:14object if so then that means player is
- 6:10:17holding a plate and if that is the case
- 6:10:19then we basically want to give the
- 6:10:20player whatever object is over here we
- 6:10:23want to add it to the plate so let's go
- 6:10:24into the plate script to add that
- 6:10:26function so over here let's make a
- 6:10:28public void let's call it add
- 6:10:34ingredient and as a parameter we're
- 6:10:36going to receive a kitchen object so so
- 6:10:38we really only care about the type we're
- 6:10:40going to destroy the actual kitchen
- 6:10:41object like we've been doing when
- 6:10:42creating different types so the plate is
- 6:10:44really just going to store a list of
- 6:10:46types so up here let's store a list of
- 6:10:48kitchen object so for the kitchen object
- 6:10:52so
- 6:10:53list then when we add the ingredient
- 6:10:55let's just add it to the list so this
- 6:10:57kitchen object so let's also make sure
- 6:10:59to initialize list so let's do it on
- 6:11:01awake let's initialize our list and now
- 6:11:04from the other side we just need to call
- 6:11:06this so over here on the clear counter
- 6:11:08if the player is holding a plate let's
- 6:11:10first get the type of plate so Plate
- 6:11:11Kitchen object or the Plate Kitchen
- 6:11:13object we go into the player to get the
- 6:11:16kitchen object and we cast this as a
- 6:11:19plate kitchen object okay so we have
- 6:11:21this and then over here let's call add
- 6:11:23ingredient and let's add whatever is
- 6:11:25currently on this counter so let's get
- 6:11:27the kitchen object and get the kitchen
- 6:11:30object as so okay so we're adding it to
- 6:11:31the plate and then let's destroy what is
- 6:11:33here so get kitchen object and destroy
- 6:11:36itself okay so that's it so if there is
- 6:11:38something here and if the player is
- 6:11:40holding something and that's something
- 6:11:41the player is holding is a plate if so
- 6:11:43we're going to add that ingredient to
- 6:11:44the plate and then destroy the object in
- 6:11:46here so let's test okay so here let's
- 6:11:48pick up a tomato let's slice it let's
- 6:11:51put it on a clear kitchen counter
- 6:11:52because that's the only one where we
- 6:11:53added the logic so on this one let's
- 6:11:55pick up a plate and now once I'm
- 6:11:57carrying the plate and if I approach and
- 6:11:59I interact with it and Y there you go it
- 6:12:01does work the object vanished from the
- 6:12:03counter and supposedly was added to the
- 6:12:04plate again we can use a really nice
- 6:12:06debug inspector to see it so let's pause
- 6:12:08the game Let's select the plate let's
- 6:12:11see the Plate Kitchen object so here it
- 6:12:13is this one and let's change the
- 6:12:15inspector into debug mode and down here
- 6:12:18yep we do see the kitchen object that's
- 6:12:19on list and it does have some tomato
- 6:12:21slices okay awesome so with this here we
- 6:12:24have our Basics we can have some
- 6:12:26ingredient and we can basically pick it
- 6:12:28up from a plate now one thing about our
- 6:12:30plate this is where we're basically
- 6:12:32going to carry the final recipe that
- 6:12:33we're going to deliver to the customers
- 6:12:35and based on the design that I defined I
- 6:12:37want something pretty simple meaning for
- 6:12:39design that I'm going for there won't be
- 6:12:41any kind of double burgers or double
- 6:12:43cheese so each final recipe will only
- 6:12:45have at most one of each ingredient so
- 6:12:48let's add some basic logic just to
- 6:12:49prevent adding duplicates over here on
- 6:12:52the Plate Kitchen object when we add an
- 6:12:54ingredient since the function will now
- 6:12:56not necessarily succeed every time let's
- 6:12:58actually rename this and again use a
- 6:13:01very useful Visual Studio shortcut so
- 6:13:03again press control RR or right click
- 6:13:05and let's rename since this function
- 6:13:07will no longer succeed we're just going
- 6:13:09to try to add an ingredient so try add
- 6:13:11ingredient and then let's also make it
- 6:13:13return a b basically for any function
- 6:13:16where you're not sure if it will succeed
- 6:13:17I like to add try and make it return B
- 6:13:20so this way works pretty much exactly
- 6:13:21like the Trion component that we've
- 6:13:23already seen so many times so it tries
- 6:13:25to do something and returns whether it
- 6:13:27succeeds or not so over here instead of
- 6:13:29always adding the ingredient let's see
- 6:13:30if this one is a duplicate so let's do
- 6:13:33an if and let's go into the list and
- 6:13:35check if the contains and if the list
- 6:13:37already contains this kitchen object as
- 6:13:39so if though then already has this type
- 6:13:43so let's return false and if
- 6:13:45not then that means this is a brand new
- 6:13:48ingredient so let's add it and return
- 6:13:50true okay so that's it now let's go over
- 6:13:53here onto the clear counter so we try to
- 6:13:56add the ingredient but then we only want
- 6:13:58to destroy if this one succeed so let's
- 6:14:00put this one inside an if so if we do
- 6:14:02manage to add the ingredient then yes
- 6:14:05let's destroy itself if not then we
- 6:14:07don't destroy anything okay so let's
- 6:14:09test so let's go ahead and slice two
- 6:14:11tomatoes so one slice it put it here
- 6:14:14then another one slice it and put it
- 6:14:16here now let's pick up a plate go up
- 6:14:18here try to pick up this one and yep it
- 6:14:20does work now for this one and nope it
- 6:14:22doesn't work okay great now one more
- 6:14:24thing in our logic we only want to pick
- 6:14:26up certain things like I said only
- 6:14:28things that won't be used in the final
- 6:14:30recipe for example no customer is ever
- 6:14:32going to request a full entire tomato
- 6:14:35the recipes only have sliced tomatoes so
- 6:14:37we should not be able to drop a full
- 6:14:38tomato directly on top of a plate so
- 6:14:40let's change that so over here on the
- 6:14:42plate script let's basically just create
- 6:14:44a list of our valid
- 6:14:46ingredients so let's make a serialized
- 6:14:48field private make it a list of kitchen
- 6:14:52objecto and call it the valid kitchen
- 6:14:55objecto list okay so we have this list
- 6:14:58and over here in the editor let's just
- 6:14:59drag the ones that we want so let's
- 6:15:01first of all select the plate object
- 6:15:04okay here is the plate pream and over
- 6:15:06here we've got all of our kitchen
- 6:15:07objects so let's just rag the ones that
- 6:15:09we want to add to the plate so the final
- 6:15:12recipes will have some bread yep but
- 6:15:14they will not have entire cabbages they
- 6:15:15will only have cabbage slices same thing
- 6:15:17no cheese only slices for the meat we're
- 6:15:21only going to be able to add meat cooked
- 6:15:23but also meat burned then we're not
- 6:15:25going to be able to add a plate onto a
- 6:15:27plate of course not and finally inside
- 6:15:29of a tomato just tomato slices okay
- 6:15:31that's our valid list and over here
- 6:15:33again it's very simple so we can just go
- 6:15:35if the valid kitchen object is a list if
- 6:15:38this one contains the one that we want
- 6:15:40to add then we can add it but if not
- 6:15:43then let's return false not a valid
- 6:15:47ingredient okay so let's test all right
- 6:15:50so let's pick up a tomato and also some
- 6:15:52tomato slices and now if I pick up a
- 6:15:54plate and I go into the Tomato nope
- 6:15:56doesn't work but the slices yep it does
- 6:15:58work okay great so here we have all of
- 6:16:00our basic plate rules everything is
- 6:16:03working perfectly but it's only working
- 6:16:04over here with the clear counter so
- 6:16:06let's do a little bit of code cleanup
- 6:16:08and then let's add this logic to all the
- 6:16:09other counters so first to clean up this
- 6:16:11code over here we are testing if this is
- 6:16:14a plate kitchen object then we cast to
- 6:16:16an object and then we call the function
- 6:16:18so let's simplify all this and let's do
- 6:16:21it just like un does with their triy get
- 6:16:23component function so let's make a
- 6:16:25custom function that takes an output
- 6:16:27parameter best place to put it is on the
- 6:16:29kitchen object so here we've got the
- 6:16:31kitchen object script okay great let's
- 6:16:33scroll down and making nice function
- 6:16:35here so let's make a public we're going
- 6:16:38to return bullion in case this succeeds
- 6:16:40or not let's call it try get plate and
- 6:16:42over here let's make an out parameter so
- 6:16:45don't forget the out keyword let's
- 6:16:47return of type Plate Kitchen object for
- 6:16:49the Plate Kitchen object and over here
- 6:16:52we do exactly what we did so we test if
- 6:16:54this object is a plate kitchen
- 6:16:56object if so then let's set the Plate
- 6:16:59Kitchen object equals this as a plate
- 6:17:01kitchen object and we return true but if
- 6:17:04not then this is not a plate so let's
- 6:17:06return false and one thing when working
- 6:17:08with output parameters you always need
- 6:17:10to make sure to set the output before
- 6:17:12you exit the function so over here
- 6:17:15that's the error that it's telling us we
- 6:17:17must assign it to something when we
- 6:17:19return so over here we don't have a
- 6:17:20plate citchen object so to solve this we
- 6:17:23just set this to null okay great now
- 6:17:25over here on the clear counter instead
- 6:17:27of doing all this basically let's ask
- 6:17:29the player if this is a kitchen object
- 6:17:32so let's try to get the plate
- 6:17:35out Plate Kitchen object for the Plate
- 6:17:38Kitchen
- 6:17:39object so you try to get it then we try
- 6:17:41to add the ingredient and so on now
- 6:17:43obviously we could further simplify
- 6:17:44things by making a function that would
- 6:17:46try to get the plate and try to add the
- 6:17:47ingredient that could work but since
- 6:17:49some counters are going to have a bit
- 6:17:51more custom logic I think keeping them
- 6:17:53separate like this makes more sense so
- 6:17:55first we try to get the plate then we
- 6:17:56try to add the ingredients so let's
- 6:17:58apply the same logic to The Cutting
- 6:18:00counter so over here on the cutting
- 6:18:02counter let's scroll down to where there
- 6:18:04is a kitchen object here and the plate
- 6:18:06is carrying something so on the counter
- 6:18:08we just want to copy all of this so
- 6:18:10let's go over here and we do the exact
- 6:18:12same thing okay that's it and the other
- 6:18:14counter from where we can pick up things
- 6:18:16is from the stove
- 6:18:18counter so here we are on the stove
- 6:18:20let's scroll down until we find the
- 6:18:22interaction okay there's something here
- 6:18:23the player is carrying something so it's
- 6:18:25over here let's do that and do the exact
- 6:18:27same thing except on the stove again
- 6:18:28let's remember that this is using a
- 6:18:30state machine so when we pick up
- 6:18:32something let's do pretty much the same
- 6:18:33thing that we did here so so let's make
- 6:18:35sure to reset the State Fire the events
- 6:18:38and so on okay so those are the only
- 6:18:40counters that we need to implement we
- 6:18:41cannot drop things on top of a container
- 6:18:43we cannot drop things on top of the
- 6:18:45plate counter or the trash so these are
- 6:18:47the only three types that we need to
- 6:18:48implement so with this let's test okay
- 6:18:51so let's begin with some meat so let's
- 6:18:52pick up some meat put it on the stove
- 6:18:54let's pick up a plate wait for it to
- 6:18:56cook pick it up and yep there you go it
- 6:18:57does work now let's test The Cutting
- 6:18:59counter so let's pick up some cheese
- 6:19:01let's slice it pick up some plate and go
- 6:19:04and yep there you go it's it doeses work
- 6:19:05and again if we inspect we can make sure
- 6:19:07that it is indeed working so let's go
- 6:19:08into the plate and let's put this on
- 6:19:11debug inspector and Y there we do see
- 6:19:13this one has a meat Patty cooked and
- 6:19:14some cheese slices okay great now the
- 6:19:17last piece of logic that we need is
- 6:19:19pretty much the opposite so right now it
- 6:19:21works if there's a sliced object on the
- 6:19:22plate and the player is holding a plate
- 6:19:24object but now we want the opposite so
- 6:19:27let's say there's a plate in here and we
- 6:19:29slice some cheese and now I want to drop
- 6:19:31the cheese on the plate so let's do that
- 6:19:33and basically for this one this one is
- 6:19:34only going to happen on the clear
- 6:19:36counter that's the only counter type
- 6:19:38that can have a plate on top of it so
- 6:19:40over here on the clear counter then we
- 6:19:42check if there's no object there but
- 6:19:44that's not what we want we want if
- 6:19:45there's a plate on the counter so if
- 6:19:47there is an object there and if the
- 6:19:49player is carrying something then we
- 6:19:51check if the player is holding a plate
- 6:19:53but if not so if the player is not
- 6:19:55holding a plate so player is not
- 6:19:58carrying plate but something else over
- 6:20:01here we need pretty much exact same
- 6:20:03logic except just testing for the object
- 6:20:05on this counter so let's do if let's get
- 6:20:07the kitchen object on this counter this
- 6:20:09one try to get the plate so out Plate
- 6:20:12Kitchen object for the Plate Kitchen
- 6:20:13object so if so if so there's a plate
- 6:20:17over
- 6:20:18here that means the counter is holding a
- 6:20:22plate so then let's go into this Plate
- 6:20:25Kitchen object let's add the ingredient
- 6:20:28and we're going to try to add whatever
- 6:20:29the player is currently carrying so the
- 6:20:31player. get kitchen object
- 6:20:34and get the kitchen object as
- 6:20:38so so we're going to try to add
- 6:20:41this and if we can't add then we're just
- 6:20:44going to destroy whatever is on the
- 6:20:46player okay that's it and over here
- 6:20:49we've got a nice error just because we
- 6:20:50defined with the same name up here so up
- 6:20:53here we're already defining the variable
- 6:20:55and over here we're defining the same
- 6:20:56variable with the same name so we can
- 6:20:59either give this a different name or
- 6:21:00just not Define a brand new variable
- 6:21:01here so just it's defined up here and
- 6:21:03we're using it here
- 6:21:05okay so on logic is working now here
- 6:21:07make very sure that you're not mixing
- 6:21:08references keep in mind when you're
- 6:21:10referencing the kitchen object on this
- 6:21:12counter and the one on the player those
- 6:21:13are two different things so over here if
- 6:21:16the player is not carrying a plate but
- 6:21:17something else then you check the
- 6:21:19kitchen counter so over here you're not
- 6:21:21checking the player but checking the
- 6:21:22counter then you go into that plate and
- 6:21:24you try to add the ingredient and you
- 6:21:26try to add the one that the player is
- 6:21:27carrying and then you destroy the one
- 6:21:28the player is carrying so again be very
- 6:21:30careful here make sure you don't mix
- 6:21:32references so with this it should work
- 6:21:34so let's make sure to save our script
- 6:21:36and let's test okay so here we are let's
- 6:21:38first pick up a nice plate let's drop
- 6:21:40the plate in there pick up some bread
- 6:21:42drop the bread and yep there you go it
- 6:21:44does work all right so now we can do a
- 6:21:46bit more natural interactions so for
- 6:21:48example let's pick up some meat and put
- 6:21:49it on cooking and there you go the meat
- 6:21:51is fried so now I'm currently carrying
- 6:21:53just some meat so I place it there then
- 6:21:55I pick up some bread and put some bread
- 6:21:56on top of the meat and yep everything
- 6:21:58does work FY okay so here we created a
- 6:22:00plate and we created some custom logic
- 6:22:02to Define what the plate can and cannot
- 6:22:04pick up now that's left is actually
- 6:22:06being able to see what is on the plate
- 6:22:08so let's do that in the next
- 6:22:10lecture hello and welcome I'm your Cod
- 6:22:13monkey in this lecture we're going to
- 6:22:15add a nice visual to our plate okay so
- 6:22:17right now we can already pick up
- 6:22:18ingredients onto the plate so if I pick
- 6:22:20up the plate and I pick up some cheese
- 6:22:22there you go there's some cheese on the
- 6:22:23plate but we cannot see it so let's
- 6:22:24solve that and way we're going to do
- 6:22:27that actually in a very simple way if
- 6:22:29you look in the included assets inside
- 6:22:31the prefab visuals there's this nice
- 6:22:33plate complete that I built basically
- 6:22:36it's a full burger that contains all the
- 6:22:38ingredients what we're going to do is
- 6:22:39actually very simple we're just going to
- 6:22:41enable or disable these game objects
- 6:22:43that's it so let's do exactly that let's
- 6:22:46make a new C script quality plate
- 6:22:49complete visual let's attach a script
- 6:22:52over here and let's also make sure to
- 6:22:54put this one inside the plate so let's
- 6:22:56save this prefab let's go inside the
- 6:22:58plate prefab so inside the prefabs here
- 6:23:01the kitchen objects we've got the plate
- 6:23:03so inside the PL let's drag that let's
- 6:23:05drag the plate complete visual okay
- 6:23:08great so now let's open up this script
- 6:23:10over here let's first add a reference to
- 6:23:12our Plate Kitchen object so we serialize
- 6:23:15field private for the Plate Kitchen
- 6:23:17object for the Plate Kitchen object back
- 6:23:19in the editor let's drag the reference
- 6:23:21okay great so now here basically we need
- 6:23:23to update this visual whenever the plate
- 6:23:25gets any ingredient added to it so let's
- 6:23:28go over here into the plate script and
- 6:23:30basically just need to fire off an event
- 6:23:31when that happens so let's make a public
- 6:23:34event event event handler and let's call
- 6:23:36it on ingredient
- 6:23:40added okay and for this one let's also
- 6:23:42make an event ARS to contain the data of
- 6:23:44what object we added so let's make a
- 6:23:46public class on ingredient added event
- 6:23:50args let's extend event args and inside
- 6:23:54let's make just a kitchen object so
- 6:23:57kitchen
- 6:23:59objecto okay great and let's make the
- 6:24:01event of this timee all right so now
- 6:24:04let's just fire off this event so down
- 6:24:06here when we try to add an ingredient if
- 6:24:08we do add the ingredient let's fire off
- 6:24:10this event so let's invoke with this and
- 6:24:13let's create a brand new one passing the
- 6:24:15kitchen object so as this kitchen object
- 6:24:17so okay so we have our event correctly
- 6:24:20being sent now over here on the plate
- 6:24:22complete visual let's listen to it again
- 6:24:24as always let's make sure to do it only
- 6:24:25on start so the plate cchen object on
- 6:24:28ingredient added let's listen to this
- 6:24:30event and over here we just need to
- 6:24:32either enable or disable the visuals
- 6:24:33that Rel to the kitchen object inside
- 6:24:36over here the event ARS however of
- 6:24:38course the question is how do exactly do
- 6:24:39we find them the plate complete visual
- 6:24:42has all of these game objects how do we
- 6:24:44know which one belongs to that kitchen
- 6:24:46object now technically one way would be
- 6:24:48to do a simple transform find and find
- 6:24:50the child objects by name technically
- 6:24:53that would work but like I mentioned in
- 6:24:55the beginning of the course strings are
- 6:24:56a horrible way to identify things they
- 6:24:58are very air prone so let's not do that
- 6:25:01instead let's use a proper approach
- 6:25:03where we can Define some kind of link
- 6:25:05between a kitchen object so and a game
- 6:25:07object and we can do that very easily by
- 6:25:09just defining a struct so up here in our
- 6:25:11script let's do exactly that let's
- 6:25:14define a public make it a
- 6:25:17struct and name it kitchen object soore
- 6:25:21game
- 6:25:24object then inside it's very simple we
- 6:25:26just have a kitchen objecto
- 6:25:30field and then also a game object field
- 6:25:37that's it super simple by the way if you
- 6:25:40don't know what is a struct basically
- 6:25:41it's very similar to a class except it's
- 6:25:44stored in different places in memory and
- 6:25:46behaves somewhat differently I have a
- 6:25:48very very important video on that
- 6:25:50subject what is the difference between
- 6:25:51value types and reference types classes
- 6:25:54are reference types so when you pass in
- 6:25:56a class into a parameter you are passing
- 6:25:58in a reference to that object whereas
- 6:26:00structs are value types so when you
- 6:26:02passing a struct onto a parameter you
- 6:26:03are passing in a copy it's a bit of a
- 6:26:06tricky thing so definitely make sure you
- 6:26:08go watch that video for more detail so
- 6:26:09you don't get confused in the future
- 6:26:11here I defined it as a strug simply as
- 6:26:13kind of a teaching moment but also
- 6:26:15because it just makes sense that if I
- 6:26:16just want to store some data without any
- 6:26:18logic then it should probably be a
- 6:26:20struct and not a class although in this
- 6:26:22case a class would work just as well
- 6:26:24anyway so here we have a struct inside
- 6:26:26the struct we have a field of type
- 6:26:28kitchen object so and another one of
- 6:26:29type game object so now let's just make
- 6:26:31a list of this type that we can expose
- 6:26:33in the editor so here a serialized field
- 6:26:36private let's make it a list of kitchen
- 6:26:38objecto game object and call it kitchen
- 6:26:41object so game object list okay that's
- 6:26:45it super simple so let's save and make
- 6:26:47sure this compiles so actually let's
- 6:26:48just comment this out just make sure our
- 6:26:50code compounds okay and over here in the
- 6:26:52editor we see the tricky thing when it
- 6:26:54comes to using fields of custom types if
- 6:26:56we look in the inspector nope we don't
- 6:26:58see anything so we cannot see our custom
- 6:27:00type in the inspector if you make a
- 6:27:02custom type like this struct and you
- 6:27:04want to show it in the inspector then
- 6:27:06you need to add the attribute
- 6:27:08serializable which exists inside system
- 6:27:11so let's go up here using
- 6:27:14system and let's add the attribute
- 6:27:16serializable just like this okay so do
- 6:27:19this save and let's look and if there
- 6:27:22you go now we do see our custom struct
- 6:27:24so we've got a list and we can click on
- 6:27:25the plus icon and there you go we've got
- 6:27:27an element and it does have a field for
- 6:27:28a kitchen object as so and one for a
- 6:27:30game object so that's great with this
- 6:27:32now we have a really nice place where we
- 6:27:34can link one object to another so let's
- 6:27:37just do exactly that so for example
- 6:27:38let's put the bread over there and let's
- 6:27:41assign the kitchen object as so for the
- 6:27:42one with bread let's do the same thing
- 6:27:44for all the others so let's add a whole
- 6:27:47bunch more Okay so we've got the bread
- 6:27:49then we're going to have the meat Patty
- 6:27:50cooked then the tomato slices then we
- 6:27:54have the cheese slices the Cabbage
- 6:27:56sliced and finally the meat Patty burned
- 6:27:58so we've got number 0 through five so we
- 6:28:00have six elements and over here yep we
- 6:28:02do got six so we have all of them we can
- 6:28:03get get rid of these last two okay great
- 6:28:06and now let's assign the proper objects
- 6:28:08so this one for the meat Patty cooked
- 6:28:10then we've got the tomato slices then we
- 6:28:13have the cheese slices then the Cabbage
- 6:28:17slices and finally the meat Patty burned
- 6:28:20okay great so all the references match
- 6:28:22now back in the code here so we have
- 6:28:24this List fully filled out and when we
- 6:28:26have this really very simple we just
- 6:28:29cycle through the list to find the right
- 6:28:30game object so let's do a 4 each of type
- 6:28:33kitchen object so game object in our
- 6:28:37kitchen object so game object list and
- 6:28:39we check if this kitchen object so.
- 6:28:42kitchen object matches the one that we
- 6:28:44received in the event if they do match
- 6:28:46then go into this one grab the game
- 6:28:48object and set active into
- 6:28:50true okay so that's it some very simple
- 6:28:53logic and also we can start with them
- 6:28:55disabled by default in the editor or
- 6:28:57just over here just do something very
- 6:28:59simple just do a four each cycle through
- 6:29:02every single one of them and set every
- 6:29:04single one of them to false so that they
- 6:29:06are HID okay so with this all the
- 6:29:08ingredients on the plate should be
- 6:29:10visible so here in the editor let's just
- 6:29:12make sure all the references have been
- 6:29:14set let's go back save the prefab and
- 6:29:16let's set on play okay so here we are
- 6:29:18and by default look at that an empty
- 6:29:19plate and yep it is empty and now let's
- 6:29:22slice some cheese now let's Place some
- 6:29:23cheese on there and yep there you go
- 6:29:25we've got some cheese now let's pick up
- 6:29:27some bread drop some bread and there you
- 6:29:28go got some cheese and some bread then
- 6:29:31let's cook some meat so let's cook it
- 6:29:34and let's pick it up with a plate and as
- 6:29:36soon as I go boom there you go I've got
- 6:29:37a nice cheeseburg all right awesome so
- 6:29:40with this I can now do a complete Burger
- 6:29:42so let's finish it let's just add some
- 6:29:44more tomatoes so slice them and add the
- 6:29:46tomatoes and finally some sliced
- 6:29:49cabbages slice them put them there and
- 6:29:51there you go here we have a fully
- 6:29:52complete Burger okay so that's great all
- 6:29:55of our visual logic is indeed working
- 6:29:57however this visual is a bit hard to see
- 6:29:59it's not very clear to the player so
- 6:30:02just looking at it from this distance
- 6:30:03does that have a tomato or not there's a
- 6:30:07tiny sliver of red in there but you
- 6:30:08can't really see it so we should
- 6:30:10probably add some nice clear icons on
- 6:30:12top to clearly indicate what exactly is
- 6:30:14on this plate so that's exactly what
- 6:30:16we're going to do in the next
- 6:30:19lecture hello and welcome I'm your Cod
- 6:30:21monkey in this lecture we're going to
- 6:30:23add some really nice icons on top of our
- 6:30:25plate so we can easily see what is on
- 6:30:27there okay so for the icons let's do the
- 6:30:29exact same thing that we did for the
- 6:30:31progress bar meaning let's use a world
- 6:30:33space canvas so let's go inside our
- 6:30:35Plate Kitchen object prefab and over
- 6:30:37here let's right click let's create a
- 6:30:39brand new canvas let's name this the
- 6:30:42plate icons UI then for the settings
- 6:30:45let's make it World space put it on 0 0
- 6:30:48everything width and height also on zero
- 6:30:50then let's lift it up a little bit so
- 6:30:52put it on a y of one okay like that now
- 6:30:55inside let's define an icon so let's
- 6:30:58start by making an empty game object
- 6:31:00call this just the icon template let's
- 6:31:03put it with a size of 3.3 it's okay
- 6:31:06something like that then inside let's
- 6:31:08add a new UI image name this the
- 6:31:11background and make it stretch to fill
- 6:31:14the parents so put zero on everything
- 6:31:17okay there's our background for the
- 6:31:19background image instead of a square
- 6:31:20let's actually go with a circle for that
- 6:31:23un actually has a bunch of built-in
- 6:31:25Sprites that it added in the last
- 6:31:27versions however it's not actually over
- 6:31:29here by default in order to see those
- 6:31:31default Sprites we need to install the
- 6:31:332D Sprite p package so let's quickly
- 6:31:35just go into window package manager
- 6:31:37let's make sure we are in the unity
- 6:31:39registry make sure we are looking at all
- 6:31:41and over here let's find the 2D Sprite
- 6:31:43package okay so let's install this okay
- 6:31:46there's the package so now if we go into
- 6:31:48the background and we search for a
- 6:31:49Sprite and over here make sure you click
- 6:31:52to actually show the assets from the
- 6:31:54packages and now we see a bunch of
- 6:31:56default hexagons a bunch of isometric
- 6:31:58tiles the square so on and if we search
- 6:32:01for Circle yep here we've got a bunch of
- 6:32:03circle so let's use this one over here
- 6:32:05on this path so let's use it there you
- 6:32:06go we have a nice circle now let's
- 6:32:09duplicate this image and for the second
- 6:32:11one let's name it icon and for this one
- 6:32:14let's assign just a random Sprite so
- 6:32:15let's say the bread and again remember
- 6:32:18how the Sorting order on the UI this one
- 6:32:20is based on the ordering the Hier so
- 6:32:22make sure that the icon is underneath
- 6:32:24the background the Hier that way it
- 6:32:26shows up on top okay so we have our icon
- 6:32:29template that's great of course we're
- 6:32:31going to dynamically generate all of
- 6:32:32this through code we're going to have
- 6:32:34multiple icons and for positioning them
- 6:32:36Unity actually has some really useful
- 6:32:38components let's select the plate icons
- 6:32:40UI and over here let set a component now
- 6:32:43for example a built-in component is the
- 6:32:45grid layout group this basically helps
- 6:32:48you position all the child objects so
- 6:32:50let's put the size of the canvas over
- 6:32:52here on
- 6:32:530.9.9 okay so there you go a nice Square
- 6:32:55window then over here on the settings
- 6:32:57for this for the cell size let's put it
- 6:32:59at 3.3 and if there you go already shows
- 6:33:02up over there on the corner and we can
- 6:33:04see what it will look like if we just
- 6:33:06duplicate this object so let's make a
- 6:33:07bunch more templates and yep there you
- 6:33:09go that's what it looks like so as you
- 6:33:11can see this component is super useful
- 6:33:12for automatically positioning all the
- 6:33:14child objects now if we want we can play
- 6:33:16around all of these we can add a little
- 6:33:18bit of spacing on the X or on the Y but
- 6:33:20let's actually leave both those with
- 6:33:22zero let's leave everything on defaults
- 6:33:24just over here on the child alignment
- 6:33:26let's put it on middle Center okay so
- 6:33:28there you go that looks pretty nice so
- 6:33:30you can see how this built-in component
- 6:33:31is super useful there's actually two
- 6:33:33more so this one for the grid layout C
- 6:33:35this is great when you want to put
- 6:33:37things horizontally and vertically but
- 6:33:39if you just want horizontally then there
- 6:33:41is the horizontal layout group and if
- 6:33:43you just want vertically there's the
- 6:33:45vertical layout group so all these
- 6:33:47components are really awesome really
- 6:33:48useful okay so with this our objects are
- 6:33:51placed and note how I name this an icon
- 6:33:54template basically a template is just
- 6:33:56what I call something that is kind of
- 6:33:57like a prefab but not really a prefab
- 6:34:00through code we're going to duplicate
- 6:34:02this template and dynamically modify the
- 6:34:03icon so we're going to use it very much
- 6:34:05like a prefab we could actually make
- 6:34:08this into a proper prefab so I could
- 6:34:10just drag it over here onto the project
- 6:34:12files and make a regular prefab that
- 6:34:14could work and the only reason why I
- 6:34:16prefer this method of not using a prefab
- 6:34:19is just because this object this
- 6:34:21template stays here on the object as
- 6:34:23opposed to cluttering over here your
- 6:34:24project files if you have tons of
- 6:34:26single-use UI elements with tons of
- 6:34:28objects you need to spawn you can end up
- 6:34:30with tons and tons of prefabs and you
- 6:34:32might not even know where each of those
- 6:34:33is used whereas with this method the
- 6:34:35template stays exactly where it's used
- 6:34:37and does not take an asset slot over
- 6:34:39here on the project files so personally
- 6:34:41this is just the approach that I prefer
- 6:34:42for spawning UI elements but like I said
- 6:34:45prefabs work as well so if you prefer
- 6:34:47using prefabs go ahead and make it okay
- 6:34:49so let's make our script to run the
- 6:34:51plate icon zy so let's go into our
- 6:34:54scripts and on the scripts folder let's
- 6:34:56create a brand new C script for the
- 6:34:58plate icons UI over here let's attach a
- 6:35:00script and open it okay so now the first
- 6:35:03thing we need is a reference to our
- 6:35:05plate so let's begin by making a
- 6:35:07serialized field private for the Plate
- 6:35:09Kitchen object for our Plate Kitchen
- 6:35:12object okay let's save it and drag the
- 6:35:14reference so over here there's the plate
- 6:35:16icons let's just drag the plate
- 6:35:18reference okay great now on the plate we
- 6:35:20already made this event when an
- 6:35:21ingredient is added so basically we just
- 6:35:24need to listen to this in order to add
- 6:35:25the new icon so over here on the UI
- 6:35:28let's do as usual private void start and
- 6:35:30on start let's go into the plate citchen
- 6:35:32object and listen to that event
- 6:35:34and when that happens let's spawn an
- 6:35:35icon although here let's actually use a
- 6:35:37different method from the one we used on
- 6:35:39the plate visual over here on the plate
- 6:35:41visual whenever we had the event we
- 6:35:44really just modified the object that was
- 6:35:46added so over here the equivalent would
- 6:35:48be to spawn a new icon whenever that one
- 6:35:50was added but instead of doing that
- 6:35:53right now let's listen to this event and
- 6:35:54when this happens let's update all the
- 6:35:56icons in this display basically this
- 6:35:58other method is useful when the contents
- 6:36:00can be added as well as removed now in
- 6:36:02this case there are never going to be
- 6:36:03removed so in this case both methods
- 6:36:05work fine but still I want to show you
- 6:36:07the second method just so you can use it
- 6:36:08when you need it so for that method we
- 6:36:10just need to know exactly what is on the
- 6:36:12plate so over here on the Plate Kitchen
- 6:36:14object we just need to expose the
- 6:36:15kitchen object as s list so let's do
- 6:36:17example that so public we're going to
- 6:36:19return a list of kitchen object so let's
- 6:36:23call it get kitchen object so list and
- 6:36:26we just return the kitchen object as
- 6:36:28list okay very simple then over here on
- 6:36:30the plate icons UI let's just make a
- 6:36:32function to update the visual
- 6:36:34so private void let's call it update
- 6:36:38Visual and when we have the event let's
- 6:36:40call our update visual
- 6:36:42okay so now here let's basically just
- 6:36:46cycle through all the ingredients so
- 6:36:47let's do a 4 in kitchen object so in the
- 6:36:51plate and get the kitchen object so list
- 6:36:55okay so we're cycling through all the
- 6:36:56ingredients on the plate and then we
- 6:36:59want to duplicate our template so that
- 6:37:00means we need a reference up here so
- 6:37:02let's add AC field private type
- 6:37:04transform call it the icon template okay
- 6:37:08let's save the code and over here in the
- 6:37:10editor let's drag the reference so let's
- 6:37:11drag the icon template by the way I'll
- 6:37:14left the others over here that's not a
- 6:37:15problem since these are going to be
- 6:37:17destroyed those we're going to see in a
- 6:37:18little bit the only one that matters is
- 6:37:20the first one okay so here we have the
- 6:37:22icon template so to spawn it we do it
- 6:37:24just like we do with any preone so we
- 6:37:26just call instantiate pass in the icon
- 6:37:29template and then transform parents so
- 6:37:32let's put it as a child of this object
- 6:37:34this part is important we need to make
- 6:37:36sure the object is spawned as a child of
- 6:37:38this object if over here you put
- 6:37:40something like null then the template
- 6:37:41won't be spawned as a global object so
- 6:37:43it won't be somewhere in the world so in
- 6:37:46order to make it position properly let's
- 6:37:47make sure to use transform to become a
- 6:37:49child of this object okay and then since
- 6:37:51we're using the other script the GRE
- 6:37:54layout group this is already going to be
- 6:37:56automatically positioned so just like
- 6:37:58this it should be spawning the icon and
- 6:38:01with the icon spawned all that's left is
- 6:38:02really just sending the image and now
- 6:38:04again the quick andary approach would be
- 6:38:06over here when we spawn let's say we
- 6:38:08pick up the item
- 6:38:10transform and over here we could go
- 6:38:12inside and do a find in order to find
- 6:38:15the image in order to get the component
- 6:38:17of Type image and so on so that is one
- 6:38:20approach that would be the quick and D
- 6:38:21approach but again we want to do things
- 6:38:23properly so let's do it the proper way
- 6:38:25instead so instead of this let's make a
- 6:38:28proper script that we're going to run on
- 6:38:29the icon template so let's create a new
- 6:38:32script so new C script call it the plate
- 6:38:35icon single UI so this one represents
- 6:38:38just a single icon let's go ahead and
- 6:38:41attach it to the template so over here
- 6:38:43let's drag it and now when using this
- 6:38:45template method really the only one we
- 6:38:47need to worry about is this one the
- 6:38:48other duplicates we can just leave them
- 6:38:50they don't really matter but still just
- 6:38:52to avoiding confusion I'm actually going
- 6:38:54to delete them so okay we just have one
- 6:38:56icon template okay and it has our script
- 6:38:58okay let's open now for here let's
- 6:39:00basically just make a function to set a
- 6:39:02kitchen object so so public void let's
- 6:39:05call set kitchen object
- 6:39:09so and we receive parameter of type
- 6:39:11kitchen object so so okay great so then
- 6:39:14we need to set the image so let's just
- 6:39:16go into a serialized field private of
- 6:39:19Type image which is inside
- 6:39:20unityengine.ui so for this one for the
- 6:39:23image we have a reference and then we
- 6:39:25set the image. Sprite go into the
- 6:39:27kitchen object and grab the
- 6:39:29Sprite okay so all we need to do is drag
- 6:39:32this reference so over here in our
- 6:39:34template let's drag the icon image okay
- 6:39:36great so now back here on the plate
- 6:39:38icons UI so we spawn it that's great
- 6:39:40then let's do a get component in order
- 6:39:42to get our
- 6:39:43script so the plate icon single UI okay
- 6:39:47and then we just call set kitchen object
- 6:39:49as so and pass in this okay that's great
- 6:39:52this is much better now again you might
- 6:39:54be thinking that this method is a lot
- 6:39:56more for Bose and just setting the image
- 6:39:57Sprite here we had to create another
- 6:40:00completely new script we had to write
- 6:40:02this logic over here get it and use it
- 6:40:05the quick and dirty approach would
- 6:40:06indeed be quicker but remember that
- 6:40:08while the quick and dirty approach might
- 6:40:10be faster at first it will mess you up
- 6:40:12over time so just take a few extra
- 6:40:14seconds to do things properly this
- 6:40:16approach is much more scalable let's say
- 6:40:18for example on this function you want to
- 6:40:20change not just Sprite but also trigger
- 6:40:22some kind of Spawn effect or animation
- 6:40:24with this it's very simple we've got
- 6:40:25this function right here we receive the
- 6:40:27kitchen object as so and we can do
- 6:40:28whatever we want with it so like this we
- 6:40:30have this grip that is responsible for
- 6:40:32anything related to the single template
- 6:40:35and we've got the general one which just
- 6:40:37spawns them and just gives them the
- 6:40:38kitchen object so so all of our logic is
- 6:40:41nicely separate okay so just like this
- 6:40:43it should already work however like this
- 6:40:46you might already be thinking won't this
- 6:40:47spawn way too many icons and yep it will
- 6:40:50basically every time we add an
- 6:40:51ingredient we're updating the visual
- 6:40:53where we're cycling through every single
- 6:40:54one and spawning all of them so with
- 6:40:56this we're constantly going to spawn
- 6:40:58more and more items this is not what we
- 6:41:00want over here on the update visual we
- 6:41:02do want to update and spawn all the
- 6:41:04icons but before we do that we actually
- 6:41:06need to clean it up we need to clean up
- 6:41:08the icons from the previous event so
- 6:41:10before we do that let's just cycle
- 6:41:12through all the children on this
- 6:41:13transform so that's pretty simple you
- 6:41:15can just do a for each transform child
- 6:41:18in the transform so this way Cycles
- 6:41:21through all the children and then just
- 6:41:23call destroy on this child. game object
- 6:41:26so that won't work that won't destroy
- 6:41:27all the previous children however of
- 6:41:30course we also have one issue the icon
- 6:41:32template itself is also a child so if we
- 6:41:35do this we're going to destroy the icon
- 6:41:37template which then over here we're
- 6:41:38going to have an error because we're
- 6:41:40going to instantiate null so we want to
- 6:41:42destroy all the children except for the
- 6:41:44template so over here that's pretty
- 6:41:46simple we just check if the child equals
- 6:41:48the icon template if so then let's just
- 6:41:51skip it so we can just call continue and
- 6:41:53there you go it skips okay great so just
- 6:41:57one more final thing if we leave the
- 6:42:00template like this meaning the game
- 6:42:02object is enabled like this the template
- 6:42:04will always be visible plus whatever
- 6:42:06ingredients we have we don't really want
- 6:42:08the template to be visible this is just
- 6:42:10meant to be a template that we can
- 6:42:11essentiate so that's pretty simple to
- 6:42:13fix let's make a private void awake and
- 6:42:16on awake let's grab the icon template
- 6:42:18grab the game object set active into
- 6:42:20false okay so now the icon template
- 6:42:23won't be disabled so it won't be visible
- 6:42:25and then over here when we are insena
- 6:42:27the intiated ones will also be disabled
- 6:42:29so let's make sure we go in there and
- 6:42:32enable these all right that should do it
- 6:42:34so all of our logic should be working
- 6:42:36there's only one more tiny thing we need
- 6:42:38to take care of this one is a world
- 6:42:40canvas so like we saw with the progress
- 6:42:42bar we need extra logic to make it look
- 6:42:44towards the camera and thankfully we
- 6:42:46already wrote an excellent generic
- 6:42:48script to do just that so let's go into
- 6:42:50the plate icons zi and let's add a
- 6:42:52component and let's add our very nice
- 6:42:54look at camera so like this and let's
- 6:42:57set the mode the same that we use so
- 6:42:58let's put it camera. Forward okay so
- 6:43:00everything is great everything should be
- 6:43:02perfect so let's finally touch test
- 6:43:03let's leave the scene save the prefab
- 6:43:05and head on play all right so let's go
- 6:43:07pick up a plate and there you go there
- 6:43:09are no icons visible okay that's great
- 6:43:11now I'm going to place a bread on top of
- 6:43:13the plate and there you go I've got a
- 6:43:14nice bread icon okay great now let's
- 6:43:16make some meat cook it and as soon as
- 6:43:19it's done going to pick it up and there
- 6:43:20you go I've got a bread and some meat
- 6:43:23now let's put some cheese slice it put
- 6:43:25it there and there you go now I can
- 6:43:26easily see that plate has some bread
- 6:43:28some meat and some cheese now let's just
- 6:43:30add the rest of the ingredients to make
- 6:43:32a full Mega Burger so let's add some
- 6:43:34tomatoes and add some nice cabbage
- 6:43:36slices and yep there you go it works
- 6:43:38perfectly so here we have a complete
- 6:43:41burger with everything and we can easily
- 6:43:43see on the icons everything this
- 6:43:44contains all right awesome okay so here
- 6:43:48you learn how to make yet another Super
- 6:43:50useful element that you can easily add
- 6:43:51to all of your games personally I use
- 6:43:54this kind of logic a ton in all kinds of
- 6:43:56UI things for example in my upcoming
- 6:43:58steam game total World Liberation the
- 6:44:01items in the inventory they're all added
- 6:44:02using using this method so there's a
- 6:44:05template and I duplicate that template
- 6:44:07same thing for all of the action buttons
- 6:44:09all of those are based on having a
- 6:44:10template and duplicating it it's a
- 6:44:12really easy way to do this kind of thing
- 6:44:14with all that here we have a full plate
- 6:44:16and we can easily see what is on there
- 6:44:18so with this the next obvious step is to
- 6:44:20actually deliver some orders so let's do
- 6:44:22that in the next
- 6:44:24lecture hello and welcome I'm your Cod
- 6:44:26monkey in this lecture we're going to
- 6:44:28build the delivery counter this is where
- 6:44:30we're going to drop some items that the
- 6:44:31customers have requested in order to
- 6:44:33complete the orders also just for fun
- 6:44:35we're going to learn how to use Shader
- 6:44:37graph to make a simple custom Shader
- 6:44:39okay so let's begin by making our
- 6:44:41counter so let's go into our base
- 6:44:43counter let's create a new prefab
- 6:44:45variant for delivery counter let's go
- 6:44:48inside and now let's find the visual the
- 6:44:51visual for delivery counter let's
- 6:44:53duplicate it to make the selected let's
- 6:44:56go inside modify the material then on
- 6:44:59the selected make it 1% bigger one1 add
- 6:45:02the component the selected counter
- 6:45:05visual let's drag the kitchen counter
- 6:45:06like that okay that's our basic setup
- 6:45:09and also start with the kitchen count
- 6:45:11disabled okay great now let's make a
- 6:45:13script to run this so let's go into our
- 6:45:15counters folder let's create a brand new
- 6:45:17C script for the delivery counter let's
- 6:45:21attach it and open okay so now here as
- 6:45:24usual let's begin by extending our base
- 6:45:26counter class all right now let's
- 6:45:29override the interact function and for
- 6:45:32now let's let actually do it ex s like
- 6:45:34the trash counter meaning let's just
- 6:45:35destroy the object so we just check if
- 6:45:38the player is holding something so if
- 6:45:39the player has a kitchen object let's go
- 6:45:42into the player the kitchen object and
- 6:45:44let's destroy it however another rule
- 6:45:46over here for the LI counter is this is
- 6:45:48only going to accept plates so let's see
- 6:45:51if the player is carrying a plate object
- 6:45:53so player get kitchen object and test
- 6:45:56try to get the plate so out Plate
- 6:45:59Kitchen object for the Plate Kitchen
- 6:46:01object we try to get this this and if it
- 6:46:03is a plate then we destroy
- 6:46:07it okay that's it here in the editor
- 6:46:10let's just compile the script and drag
- 6:46:12the references so the counter top point
- 6:46:14and on the selected let's drag the
- 6:46:16counter reference and let's exit this
- 6:46:18save the prefab and let's drop it over
- 6:46:20here on the corner so let's find over
- 6:46:22here the delivery counter let's put it
- 6:46:24over there angle it on this side put it
- 6:46:27like this let's also just quickly
- 6:46:29reposition all of our counters since we
- 6:46:31already have all the types that going to
- 6:46:33use so on delivery counter let's put it
- 6:46:35over here on this corner so x 7.5 0 and
- 6:46:38Z of two then next to it let's put the
- 6:46:40plates counter so over there okay then
- 6:46:43next to it let's put a clear counter
- 6:46:45after that let's put the trash counter
- 6:46:48and then let's also put another empty
- 6:46:49one there so let's duplicate this one
- 6:46:51move it up to about this and put it like
- 6:46:54that now we just need to move all of
- 6:46:55these down here so just select all of
- 6:46:58these counters and let's move them down
- 6:47:01by about this okay so on minus 5.5 like
- 6:47:04this okay so everything is nicely
- 6:47:06positioned just over there right now we
- 6:47:08cannot access that container so let's
- 6:47:10actually modify those as well which by
- 6:47:12the way over here there's the canvas in
- 6:47:14front so as I click I'm actually
- 6:47:15selecting the canvas in the Hier key so
- 6:47:18here's a quick in TP on the Hier key on
- 6:47:20the left side you've got these two
- 6:47:21buttons so one of them hides the object
- 6:47:23and the other one simply makes it
- 6:47:24unselectable so if I click on this and I
- 6:47:26click through and you have the click
- 6:47:28goes through the canvas so that makes it
- 6:47:29much easier to select over here all the
- 6:47:31items in our scene so let's just select
- 6:47:33all of these okay all of these now just
- 6:47:36push them all to the side and make
- 6:47:39another empty one and put it over here
- 6:47:41okay that's a nice layout now let's just
- 6:47:43finish the rest so over here let's just
- 6:47:45duplicate our empty counters and place a
- 6:47:47bunch more let's put one more to the
- 6:47:50side and now these ones over here so
- 6:47:52let's put it over there and rotate it
- 6:47:54here and duplicate another one and
- 6:47:56another one and another one and just one
- 6:48:00more and get rid of this one okay great
- 6:48:03so here we have pretty much our complete
- 6:48:04map let's also just move the camera tiny
- 6:48:07tiny bit just make sure that it is
- 6:48:08nicely organized so put it over there
- 6:48:11just so everything is nice and centered
- 6:48:13okay so there's our map now let's get
- 6:48:14back to working on our delivery counter
- 6:48:17we already added this code so let's just
- 6:48:18quickly test so here we are and if I
- 6:48:20pick up something like for example some
- 6:48:22cheese going to delivery counter and
- 6:48:23interact and nope nothing happens
- 6:48:25because that one only accepts plates now
- 6:48:27if I pick up a plate go there deliver
- 6:48:28and yep there you go it does work okay
- 6:48:30great so this is the basic logic that we
- 6:48:32want for defining the actual recipe
- 6:48:35logic we're actually only going to do
- 6:48:36that in the next lecture but for now
- 6:48:38let's add one more nice thing let's add
- 6:48:40a simple custom visual over here using
- 6:48:42Shader graph this is a great way for you
- 6:48:44to learn the part of Shader graph and
- 6:48:45just how easy it is to use this is a
- 6:48:47visual tool for making shaders it's
- 6:48:49really very easy personally I don't know
- 6:48:52how to write shaders with code but I can
- 6:48:53build some pretty nice things using
- 6:48:55Shader graph as usual I have a dedicated
- 6:48:57video on it I also have an entire
- 6:48:59playlist showcasing how to make all
- 6:49:01kinds of interesting effects and even
- 6:49:03one special video covering some changes
- 6:49:04in recent sharew versions so over here
- 6:49:07let's learn the basics how to use it so
- 6:49:09first here in our project window let's
- 6:49:11create a brand new folder let's name it
- 6:49:13just shaders and now inside let's create
- 6:49:15one so let's create then go up here into
- 6:49:18Shader graph then we're using urp so
- 6:49:20let's go inside there and here we've got
- 6:49:22a bunch of options now don't worry about
- 6:49:24picking the quote unquote wrong option
- 6:49:26all this does is just create a template
- 6:49:28so for example if you accidentally
- 6:49:30create an unlit Shader you can then
- 6:49:31easily swap it out from l so right now
- 6:49:34let's go with theit Shader and for the
- 6:49:35name let's name it moving visual okay
- 6:49:38there's our Shad graph file now now
- 6:49:40let's just double click to open it and
- 6:49:42up here we have the nice Shad graph
- 6:49:44window by the way you can make this full
- 6:49:45screen so you can either right click
- 6:49:47over there on the tab and maximize or
- 6:49:50alternatively you can just click on this
- 6:49:51window and you use the hotkey shift
- 6:49:54space y there you go it doesn't maximize
- 6:49:56okay great now by default we have this
- 6:49:58down the center this is called the
- 6:49:59master stack these are the actual
- 6:50:02properties that we're going continue to
- 6:50:03use then on the left side we have the
- 6:50:05properties Blackboard on the right side
- 6:50:08we've got the graph inspector and
- 6:50:10finally down here we've got the main
- 6:50:12preview all of these windows can be
- 6:50:13scaled and also if you don't see these
- 6:50:15windows or if you accidentally hide them
- 6:50:17they're all appear here on these three
- 6:50:19buttons so the Blackboard that's on the
- 6:50:20left the graph inspector and the main
- 6:50:22preview okay so now here we've got a
- 6:50:24nice empty board so we can add whatever
- 6:50:26nodes we want so we can right click and
- 6:50:28go into create node and then we can
- 6:50:30write something or just click anywhere
- 6:50:31and press on space and and there you go
- 6:50:33now we can cycle through and browse all
- 6:50:35of these menus to see all of the nodes
- 6:50:37that exist there's tons and tons of them
- 6:50:39or alternatively just go up here and use
- 6:50:41the search bar so for example let's find
- 6:50:43the sample texture to the node so here
- 6:50:45it is this one okay we've got this node
- 6:50:48what this one does is it takes a texture
- 6:50:50and grabs the color from it so on the
- 6:50:52left side of the node are the inputs and
- 6:50:54on the right side are the outputs within
- 6:50:57the parentheses you can actually see the
- 6:50:58types so for the input texture this one
- 6:51:00is of type T2 so that means it's a
- 6:51:02texture 2D then on the output you can
- 6:51:04see there's a four meaning it contains
- 6:51:06four floats which in this case refers to
- 6:51:08the four colors so that's red green blue
- 6:51:11and Alpha so for an input we want a
- 6:51:13texture so let's set it over here as a
- 6:51:15property let's click on the plus icon
- 6:51:17and we've got a whole bunch of types for
- 6:51:19texture we want a texture 2D so let's go
- 6:51:21with that and then for the name now
- 6:51:23usually there are two standard names
- 6:51:25there's one called main Tex or Bas map
- 6:51:28main Tex used to be the more common name
- 6:51:30but when working with urp for some
- 6:51:32reason they decided to name the main
- 6:51:33texture as base map so we're here let's
- 6:51:35stick within the urp standard and just
- 6:51:37call this base map okay there's our
- 6:51:39property and if we click to select it
- 6:51:41and on the right side we can see the
- 6:51:42graph inspector and we can see all the
- 6:51:44properties for this actual property so
- 6:51:46we see a name reference and a bunch more
- 6:51:48things now the really important one is
- 6:51:50over here the reference this is the
- 6:51:52actual name that you're going to use if
- 6:51:54you want to interact with this Shader
- 6:51:55through code the name on the property
- 6:51:57this one is just a text ring so this can
- 6:51:59be whatever you want you can even have
- 6:52:00spaces and so on whereas the reference
- 6:52:03name this is the really important one
- 6:52:04and by default when you set up a name it
- 6:52:06should already set the correct reference
- 6:52:09usually the standard is to name it just
- 6:52:10like the name both without any spaces
- 6:52:12and with an underscore in the beginning
- 6:52:14so just like this okay then we can give
- 6:52:16it a default texture so let's go ahead
- 6:52:18and select something for example over
- 6:52:20here the bread texture remember this is
- 6:52:22just a default this will not be
- 6:52:24hardcoded directly into the Shader we
- 6:52:26can then modify this okay so we have our
- 6:52:28nice Bas map property definition now we
- 6:52:30can just drag it over here on the board
- 6:52:32and yep there it is and now we can just
- 6:52:34click on the Cal icon in order to drag a
- 6:52:36connection and let's connect it over
- 6:52:37here onto the simple texture to the
- 6:52:39input and yep right away we do see it
- 6:52:41does work so we are correctly sampling
- 6:52:42the texture however if you look on the
- 6:52:45main preview over here there's still
- 6:52:46nothing that's because we don't have
- 6:52:48this node connect to anything we need to
- 6:52:50connect it to the final Master sack in
- 6:52:52order to render something so again on
- 6:52:54the output over here we can see a four
- 6:52:56so these are all of our colors and
- 6:52:58actually one very useful note is the
- 6:53:00preview since so many things in Shader
- 6:53:02graph can be hard to visualize so we can
- 6:53:05move these nodes around and let's add
- 6:53:06the preview node and this does exactly
- 6:53:09that so you can fit it an input and you
- 6:53:11can see down here what that input
- 6:53:12contains so for example let's drag just
- 6:53:15the red Channel and Y there you go over
- 6:53:17there we can see the red channel for
- 6:53:18this texture we can drag the green
- 6:53:20channel the blue Channel or look at the
- 6:53:22alpha Channel yep there you go it does
- 6:53:24work so this preview note is super
- 6:53:26useful for being able to see what your
- 6:53:28shaded is actually doing over here we
- 6:53:30have the colors so let's get rid of the
- 6:53:32preview right now and in order to make
- 6:53:34it work we really just need to connect
- 6:53:35the rgba and go up here into the base
- 6:53:38color and right away it should work but
- 6:53:41you might not be able to see anything
- 6:53:42over here on the main preview I believe
- 6:53:44this is a rendering bug in the current
- 6:53:46Tech version so right now nothing is
- 6:53:48shown so if you still don't see anything
- 6:53:50it's actually pretty simple just go up
- 6:53:52here on the top left side and make sure
- 6:53:54to save the asset okay save it great
- 6:53:56then let's exit from our maximize View
- 6:53:59and now let's close this tab let's click
- 6:54:01on Play Just to play the game now let's
- 6:54:03stop playing and now if we open the
- 6:54:05Shader again y there you go now we do
- 6:54:08see the Shader compiling over there that
- 6:54:09color that is the Shaded compilation and
- 6:54:11after a little bit it should work let's
- 6:54:13just maximize this see if there you go
- 6:54:15there we do see our texture okay great
- 6:54:17so again this just a simple rendering
- 6:54:19bug on the current Tech version if
- 6:54:21you're watching this video in the future
- 6:54:22chances are you don't even have this bug
- 6:54:24so there's no need to worry okay so
- 6:54:26right now we do see it working we can
- 6:54:27see our bread texture and it's currently
- 6:54:29being applied on a sphere for a use case
- 6:54:31where working with 2D textures so this
- 6:54:34would be best to be seen on a quad so we
- 6:54:35can right click over here on the preview
- 6:54:37in order to select the preview mesh so
- 6:54:39let's go with a simpon quad and Y there
- 6:54:40it is we have our nice quad okay great
- 6:54:43so over here we have our basic Shader
- 6:54:45all it does is just shows a texture
- 6:54:47that's it now let's actually use this
- 6:54:50and first let's always make sure to save
- 6:54:52the asset on the top left side on the
- 6:54:54moving visual if you see an ass is here
- 6:54:56that means you have unsaved changes so
- 6:54:58always make sure to save them in my case
- 6:55:00I don't but still never hurts to save
- 6:55:02now over here in scene view let's go
- 6:55:04inside our delivery counter so let's
- 6:55:06open it and now for the display for our
- 6:55:08Arrow let's make it a flat quad so let's
- 6:55:11right click in the Hier key let's create
- 6:55:12a new 3D object and let's make it a quad
- 6:55:15let's call this the delivery
- 6:55:17Arrow let's place this on top of the
- 6:55:19counter so let's rotate it to face
- 6:55:21upwards by the way on the rotation make
- 6:55:23sure the color is facing upwards most
- 6:55:25shaders by default they only render one
- 6:55:27face and not the other one so make sure
- 6:55:29you put the face with the collar upwards
- 6:55:31and not the other one okay so let's
- 6:55:33rotate this one upwards so there we go
- 6:55:3590 over there and let's just put it just
- 6:55:38exactly on top of the counter so just
- 6:55:39enough so that it's visible okay great
- 6:55:42so now let's make a material for our
- 6:55:44Arrow so let's go inside the materials
- 6:55:46folder and over here let's create a
- 6:55:48brand new material let's call this the
- 6:55:51delivery Arrow let's make sure to use
- 6:55:53this material on the quad so let's just
- 6:55:54drag it over there on the mesh render
- 6:55:56okay so it's using our custom material
- 6:55:58and over here on this Shad of graph drop
- 6:56:01down menu over here we can select what
- 6:56:03Shader we want to use so in our case
- 6:56:05let's go inside the fer Shader graphs
- 6:56:07and inside yep here we have our moving
- 6:56:09visual Shader so let's go ahead and use
- 6:56:11this and here right away we do see that
- 6:56:13it does work here we have our texture
- 6:56:15being drawn exactly on top of our
- 6:56:17material okay so far so good now again
- 6:56:20here remember one very very important
- 6:56:22thing that I said the texture that you
- 6:56:24define the Shader over here the default
- 6:56:26for the property this one is only the
- 6:56:28default the important one is the one
- 6:56:30that we have on the material I'm
- 6:56:32emphasizing this point because I've seen
- 6:56:34a bunch of people make this mistake if
- 6:56:36you modify default texture whilst inside
- 6:56:38the Shader like for example if I change
- 6:56:40here from bread let's say into the
- 6:56:42Cabbage slices if I modify that note how
- 6:56:45it does not modify any materials that
- 6:56:47were created we are only changing
- 6:56:49defaults so if you want to change the
- 6:56:51texture that is actually used make sure
- 6:56:53you change the one on the material that
- 6:56:55you created and not the default I
- 6:56:57changed the default but did not change
- 6:56:58this Shader however if I now were to
- 6:57:00make another material which by the way
- 6:57:02here's a quick tip you can right click
- 6:57:04directly on the Shader file and go into
- 6:57:06create and create new material and it
- 6:57:08will automatically create the material
- 6:57:09using that Shader naturally here didn't
- 6:57:11update default just because I didn't
- 6:57:13save the Shader so I modified this one
- 6:57:15for the cab slices and now if I save the
- 6:57:17asset and now if I right click there and
- 6:57:19I create a brand new material and yep
- 6:57:21now that one does have the new default
- 6:57:23but again remember what you said over
- 6:57:25here is just the default what really
- 6:57:27matters is what is on the material after
- 6:57:30the material has been created modifying
- 6:57:32default here does nothing so always keep
- 6:57:34that in mind in most cases you want to
- 6:57:36be changing the property on the material
- 6:57:38itself not the default on the Shader
- 6:57:40okay let's just clean up both these all
- 6:57:42right so let's continue now here we have
- 6:57:44our Sprite working okay except we don't
- 6:57:46want to show some bread so let's
- 6:57:47actually use the proper Arrow Sprite so
- 6:57:49let's select this one and yep it does
- 6:57:51work it is printing the Sprite however
- 6:57:53one obvious thing is that the arrow is
- 6:57:55not transparent like it should be so
- 6:57:56let's solve that back in our Shader
- 6:57:59graph in order to make this a
- 6:58:00transparent Shader we need to actually
- 6:58:02go into the graph settings so on the
- 6:58:04graph inspector go into graph settings
- 6:58:05and over here you see a bunch of
- 6:58:07settings that relate to the graph itself
- 6:58:08and not any selected properly so let's
- 6:58:10go into graph settings for example like
- 6:58:12I mentioned a while ago you can modify
- 6:58:13between lit and lit and so on so this is
- 6:58:16where you would change that you can also
- 6:58:18up here add multiple targets so you can
- 6:58:20create a Shader in Shader graph and make
- 6:58:21it work with the universal render
- 6:58:23pipeline or the high definition render
- 6:58:25pipeline or the built-in R pipeline all
- 6:58:27of those are supported through Shader
- 6:58:28graph now for our goal in order to make
- 6:58:30this a transparent Shader let's just go
- 6:58:32over here onto surface type instead of
- 6:58:33opaque let's change to transparent and
- 6:58:36as soon as we do look what happens there
- 6:58:38and if there you go it adds a brand new
- 6:58:39Alpha Channel if we just save the asset
- 6:58:41right now and no look at that it still
- 6:58:43doesn't work it's still not transparent
- 6:58:46basically we made this Shader
- 6:58:47transparent but now we need to fit in
- 6:58:49the transparent Channel over here onto
- 6:58:51the alpha this is the one thing that is
- 6:58:53different from a previous version of
- 6:58:54Shader graph previously you could just
- 6:58:56feed the alpha Channel over here onto
- 6:58:57the base collar and Shader graph would
- 6:58:59automatically apply it but in recent
- 6:59:01version you need to add it over here
- 6:59:03separately so if you have any issues
- 6:59:05with transparency when following some
- 6:59:07older share graph tutorials always
- 6:59:08remember this change I covered that
- 6:59:10along with some other changes in a very
- 6:59:12useful video so if you're following
- 6:59:13along some older shade graph tutorials
- 6:59:15make sure you watch that video to learn
- 6:59:17what you need to do to update them to
- 6:59:18the latest version okay so here on the
- 6:59:20sem texture we already have the alpha
- 6:59:22channel so we just connect this onto the
- 6:59:23master Alpha and right there we already
- 6:59:26see it working let's just go ahead save
- 6:59:28our asset and here in scene view yep
- 6:59:30there you go now we do see our error
- 6:59:33now one more small thing you might
- 6:59:35notice that from some angles it's not
- 6:59:36exactly transparent basically it
- 6:59:38actually is transparent but since we
- 6:59:40made this a lit Shader sometimes the
- 6:59:42light might make the transparent Parts
- 6:59:43visible one option to solve that is over
- 6:59:45here on the graph settings instead of
- 6:59:47making it lit let's make it unlit that
- 6:59:49would work so yep with the unlit Shader
- 6:59:50the transparency is perfect but if you
- 6:59:53really want to keep it lit then the
- 6:59:55other thing you can do is just over here
- 6:59:56play around with these settings you've
- 6:59:58got smoothness AO and so on and over
- 7:00:00here you can even modify the workflow
- 7:00:01mode so for transparency instead of
- 7:00:03making it metallic let's go with a
- 7:00:05specular workflow and then over here set
- 7:00:07the smoothness to one and the ENT cusion
- 7:00:09down to zero and now if we save this
- 7:00:11Shader look at that and yep now the
- 7:00:14transparent parts are indeed fully
- 7:00:15transparent finally over here on the
- 7:00:17right side on the mesh render if you
- 7:00:19want you might want to play around over
- 7:00:20here with the cast Shadows so maybe you
- 7:00:22don't want this one to cast Shadows
- 7:00:25maybe you don't want it to impact light
- 7:00:26probes and so on okay so with this we
- 7:00:28have our nice transparent Arrow let's
- 7:00:30make sure to save our deliver counter so
- 7:00:32let's go outside back into scenes and
- 7:00:35let's head on playing and there you go
- 7:00:36we have our transparent counter with our
- 7:00:38nice Arrow now we want the arrow to
- 7:00:40actually move and doing that is actually
- 7:00:42super simple going back here in our Shad
- 7:00:45graph let's just modify default just so
- 7:00:46we can see the arrow that we want to see
- 7:00:48so let's select the arrow Sprite okay
- 7:00:51there's our Arrow now for moving over
- 7:00:53here on the sample texture we've got an
- 7:00:55input for the UV the UV is what defines
- 7:00:58what portion of the texture we're going
- 7:00:59to grab which by default just gets the
- 7:01:01whole texture so since this field
- 7:01:04represents where we're going to grab
- 7:01:06from texture by playing around with this
- 7:01:07we can grab different parts so to do
- 7:01:10that let's just add a standard UV node
- 7:01:12so here it is this is the standard UV
- 7:01:14channel so if we connect this then
- 7:01:16nothing changes everything still renders
- 7:01:17exactly the same but now we can modify
- 7:01:20this and to do that we're really just
- 7:01:22going to use some basic math remember
- 7:01:24that when working with shaders even
- 7:01:26though you do see colors everything is
- 7:01:27really just numbers so uv2 is just
- 7:01:30number the color is just a number the
- 7:01:32alpha is just a number so visually
- 7:01:33everything might look like images might
- 7:01:35look like colors but really in the end
- 7:01:37it's all just numbers so for example how
- 7:01:39do we move this texture well that's
- 7:01:41actually pretty simple we just add a
- 7:01:42number onto it so over here on the UV
- 7:01:44let's just add an add node so this just
- 7:01:47adds two numbers together very basic so
- 7:01:50let's take the regular UV and let's add
- 7:01:52something on top of it for example we
- 7:01:54can make a vector two and let's put it
- 7:01:57on say
- 7:01:580.10 and let's add this one onto this
- 7:02:00one and now if we drag this one onto the
- 7:02:03input look over there on the preview
- 7:02:04what happens and there go look that it
- 7:02:06moves slightly to the left so if I
- 7:02:08modify this one put it down zero there
- 7:02:10you go at that 0.1 on that point 2 on
- 7:02:12that and so on so you can see that by
- 7:02:14modifying here I'm essentially
- 7:02:15offsetting the texture I'm offsetting on
- 7:02:17the X and over here I can also offset it
- 7:02:19on the y basically I'm offsetting the
- 7:02:21texture by 10% duv is a normalized value
- 7:02:24this is not pixels so that is why 0.1 is
- 7:02:2710% regardless of how big the texture is
- 7:02:30and if we go way past one then texture
- 7:02:32essentially Loops back so this is really
- 7:02:34all we need for our moving Arrow we're
- 7:02:37going to have zero on the Y and on the X
- 7:02:40we're going to constantly either
- 7:02:41increase or decrease that's how we're
- 7:02:43going to have our moving Arrow so again
- 7:02:45the only issue here is that I'm
- 7:02:46modifying this manually we don't want a
- 7:02:48fixed amount on the Shader instead we
- 7:02:50want a nice animation so for that we
- 7:02:52have the very useful the time node this
- 7:02:55one has various time based outputs the
- 7:02:58one that we want for this case is the
- 7:02:59time which is just the total time this
- 7:03:01one is constantly increasing since the
- 7:03:03start of the game by the number of
- 7:03:04seconds so if you use this over here
- 7:03:06directly on the ad and there going look
- 7:03:08that texture is constantly scrolling
- 7:03:11okay so that's great except obviously we
- 7:03:13have one issue we don't want it to
- 7:03:14scroll diagonally we only want to scroll
- 7:03:17in One Direction so for that we can
- 7:03:18essentially create a simple property to
- 7:03:20act as our Spen so let's over here on
- 7:03:23the Blackboard let's create a new Vector
- 7:03:252 call it our speed property and for
- 7:03:28default let's Def and say 0.1 on the X
- 7:03:30zero on the Y
- 7:03:32and now if I drag the speed over here
- 7:03:34onto our Blackboard okay great this is
- 7:03:36basically a multiplier so we just need
- 7:03:38to multiply the time by this so let's
- 7:03:40add a multiply node also by the way
- 7:03:43quick tip over here on each node you've
- 7:03:44got a nice little arrow so if you want
- 7:03:45to make it a bit more compact so if you
- 7:03:47don't actually need to see the preview
- 7:03:49so make that and in this case let's take
- 7:03:51our time multiply by our speed and then
- 7:03:54for the output pass it into the add okay
- 7:03:56so look at that now it is indeed moving
- 7:03:58in this direction and over here on the
- 7:03:59speed we can play around the values so
- 7:04:01if we put put it at 0.5 now it's moving
- 7:04:03faster and if I put it on the Y now it's
- 7:04:06moving diagonally put zero on the X and
- 7:04:08now it's only moving vertically okay so
- 7:04:10this is really what we want let's just
- 7:04:12go ahead save our Shader and now let's
- 7:04:14just select our delivery Arrow material
- 7:04:17and over here yep we've got the speed if
- 7:04:19you don't see it make sure that on the
- 7:04:20speed property over here you have it
- 7:04:22exposed so we have the speed instead of
- 7:04:24moving on the Y let's move on the X and
- 7:04:27actually like this it's revers going
- 7:04:29backwards so over here we can just put a
- 7:04:31negative value so let's put it on minus
- 7:04:32one and Y there you go now the arrow is
- 7:04:34moving perfectly also here let me make
- 7:04:37one important note just in case you're
- 7:04:39using this Shader with a custom texture
- 7:04:41instead of the one including in the
- 7:04:42course if you do that make sure that the
- 7:04:44texture that you use over here I'm using
- 7:04:45the arrow texture over here on the Arrow
- 7:04:48import settings down here under WAP mode
- 7:04:50make sure it is set to repeat if you set
- 7:04:52it as clamp you might get some weird
- 7:04:54visuals or nothing at all in order for
- 7:04:57the texture to constantly Loop and
- 7:04:58constantly repeat itself that one needs
- 7:05:00to be set to repeat okay so here it is
- 7:05:02in game and we have a really nice moving
- 7:05:04texture for that we created a simple but
- 7:05:06really nice useful custom Shader
- 7:05:09definitely go ahead and watch the
- 7:05:10various effects that I made in the
- 7:05:11Shader graph playlist this tool is super
- 7:05:13useful definitely make sure you know how
- 7:05:15to use it I've used it for making a
- 7:05:17building effect I've made some nice
- 7:05:19outlines a really nice wind Shader also
- 7:05:22a really interesting dissolve effect and
- 7:05:24even a cool transition Shader just like
- 7:05:26in the game Hades so this really is a
- 7:05:28super powerful tool make sure you watch
- 7:05:30that playlist to really learn learned
- 7:05:31how to use it all right so here we
- 7:05:33learned about Shad graph and created a
- 7:05:35really nice custom Shader however the
- 7:05:37delivery counter still only has a visual
- 7:05:40so let's create some proper Logic for
- 7:05:41generating and delivering the correct
- 7:05:43recipes in the next
- 7:05:45lecture hello and welcome I'm your cm in
- 7:05:48this lecture we're going to build a
- 7:05:50proper delivery manager that will
- 7:05:51generate recipes that the customers are
- 7:05:53ordering and validate to see if the
- 7:05:55player May the right dishes all right so
- 7:05:57right now we have the player capable of
- 7:05:58making dishes so for example I can put
- 7:06:00some cheese cook some meat meat cut the
- 7:06:02cheese and then pick up both them then
- 7:06:05let's say pick up some bread there you
- 7:06:06go got a nice cheeseburger and deliver
- 7:06:08it okay so that works but right now they
- 7:06:10just vanish on delivery counter so
- 7:06:13there's no recipe we need to follow no
- 7:06:14validation none of that so let's add
- 7:06:16both those things okay first of all
- 7:06:18let's make our script so let's create a
- 7:06:20brand new script for the delivery
- 7:06:22manager let's make a new game object to
- 7:06:25run it so a new delivery manager attach
- 7:06:27the script let's make sure to keep
- 7:06:28things clean so reset the transform and
- 7:06:30also by the way since over here let's go
- 7:06:32ahead and put the plates and delivery
- 7:06:33counter inside the counter so everything
- 7:06:35is nice and organized okay great so
- 7:06:38let's open up this script now here
- 7:06:40basically we need to Define some sort of
- 7:06:42list to store all the recipes that the
- 7:06:44customers are waiting for which of
- 7:06:46course begs a question what type is that
- 7:06:47going to be now technically one thing we
- 7:06:50could do since a recipe is really just a
- 7:06:52list of kitchen objects over here we
- 7:06:54could have a list of list of kitchen
- 7:06:57object this would be our recipe list
- 7:07:00technically that would work but that
- 7:07:01really it looks quite dirty instead of
- 7:07:03having a list of list we should probably
- 7:07:05have a proper type for this so let's
- 7:07:07write some good clean code and Define a
- 7:07:09proper recipe script M object back in
- 7:07:11unity let's go inside the script M
- 7:07:13object folder and create a brand new one
- 7:07:15let's call this the recipe so and over
- 7:07:18here let's make this a script M object
- 7:07:19so extend script M object make the
- 7:07:22create asset menu and now over here for
- 7:07:25the fields for the data that we need
- 7:07:27really like I said a recipe is just a
- 7:07:29list of ingredients so just a list of
- 7:07:31kitchen objecto for the kitchen objecto
- 7:07:35list okay that's it that's really all
- 7:07:37the data that we need to define a recipe
- 7:07:39just to be able to identify them for the
- 7:07:40player let's also add a public string
- 7:07:43for the recipe name so just a nice name
- 7:07:46String okay great now back in the editor
- 7:07:48let's define so let's go inside the
- 7:07:50script objects and make a brand new one
- 7:07:52for our recipe so and now inside let's
- 7:07:56create a brand new recipe so for this
- 7:07:58one let's call it just burger and over
- 7:08:00here first of all for the name just name
- 7:08:02it burger and then for the kitchen
- 7:08:04object list well to make a burger let's
- 7:08:06well first let's add some meat and we
- 7:08:08want some cooked meat we don't want to
- 7:08:10serve uncooked or burnt meat so only the
- 7:08:12cooked meat then for a simple Burger
- 7:08:14obviously we need some bread and that's
- 7:08:16about it so some bread some meat that's
- 7:08:18our very basic Burger now let's also
- 7:08:20make another one so let's duplicate this
- 7:08:22one and name this one the cheeseburger
- 7:08:24over here let's name it cheese
- 7:08:27burger and like name implies has bread
- 7:08:30meat and obviously some nice cheese
- 7:08:32slices so there you go okay we have a
- 7:08:35cheeseburger now let's also make a mega
- 7:08:38Burger so something with everything so
- 7:08:40let's call this one the mega burger and
- 7:08:42over here for the string name for the
- 7:08:44Mega burger and for that we have meat
- 7:08:46bread cheese let's also have some nice
- 7:08:50cabbage slices and also some tomato
- 7:08:52slices all right that's our Mega burger
- 7:08:54with everything and finally let's also
- 7:08:56make just a nice simple salad so let's
- 7:08:58duplicate this for a salad let's name it
- 7:09:02salad and for the salad we don't have
- 7:09:04any meat we don't have any bread and
- 7:09:06also no cheese so just cabbage slice and
- 7:09:09tomato slice that's a simple salad okay
- 7:09:11so here we have all of our recipes so
- 7:09:14back here on the delivery manager script
- 7:09:16instead of making a list of list of Game
- 7:09:18object let's just make a list of recipe
- 7:09:20recipe so and name it the recipe so list
- 7:09:23this is where we're going to place the
- 7:09:24recipes that the customers are waiting
- 7:09:26for so let's actually rename this let's
- 7:09:28put it waiting recipe list okay so the
- 7:09:31customers are waiting for whatever is
- 7:09:33inside this list and now we could make
- 7:09:35this a serialized feel and then set it
- 7:09:36in the editor but we don't want to have
- 7:09:38a fixed list we want to periodically
- 7:09:40spawn new recipes and in order to spawn
- 7:09:43new recipes we also need to know which
- 7:09:44ones we can spawn so for that we could
- 7:09:46add a list of all of the recipes then we
- 7:09:49could pick a random one from the list
- 7:09:51and add it over here to the waiting list
- 7:09:53that would work that's one good approach
- 7:09:54but since we already did something
- 7:09:56similar to that various times on this
- 7:09:57course here let me teach you a different
- 7:09:59approach that sometimes might make more
- 7:10:01sense for that second approach we just
- 7:10:03need one thing we need a script M object
- 7:10:04to hold all of our recipes so let's do
- 7:10:07that let's do a brand new C script this
- 7:10:10is the recipe and list script M object
- 7:10:12and then inside this one is going to be
- 7:10:15a script M object let's add the create
- 7:10:18asset menu and inside we're just going
- 7:10:20to have a list of recipe so for the
- 7:10:23recipe so list so that's it super simple
- 7:10:27now let's just create one object of this
- 7:10:29type we can put it inside the recipe so
- 7:10:31list since we're only going to have one
- 7:10:32so let's make a recipe list so name it
- 7:10:35the recipe list so and then over here
- 7:10:37let's just drag our recipe so we've got
- 7:10:39a burger a cheeseburger we have a mega
- 7:10:42burger and finally a salad okay so
- 7:10:44basically we have a script B object with
- 7:10:46all of our recipes and now just for
- 7:10:48safety since we only want to ever have a
- 7:10:50single one of these objects a recipe
- 7:10:52list as so for this one we can go back
- 7:10:54here in the script and simply comment
- 7:10:56out the create asset menu so now back in
- 7:10:58the game over here we can no longer
- 7:11:00create another type of recipe list as so
- 7:11:02so just a nice safety thing since we
- 7:11:04probably only need just one and let's
- 7:11:06also add an underscore just so it shows
- 7:11:08up at the top of the list okay great so
- 7:11:10we have this and now over here on the
- 7:11:13recipe manager we can basically expose
- 7:11:15that in a serialized field so let's make
- 7:11:16a serialize
- 7:11:18field make it private of type recipe so
- 7:11:21list recipe list so for the recipe list
- 7:11:25so and now here in the editor we just
- 7:11:27drag that reference all right that's it
- 7:11:29so basically the difference that we did
- 7:11:31with this method is over here on
- 7:11:32delivery manager instead of having a
- 7:11:34list of all of our recipes we just have
- 7:11:35a reference to one object and then that
- 7:11:37object holds a list of all the recipes
- 7:11:39in this specific use case like I said
- 7:11:41this approach doesn't really have many
- 7:11:42benefits compared to just storing the
- 7:11:44list here but let's say we had another
- 7:11:46script that also need the list of all of
- 7:11:48our recipes if we did that we would
- 7:11:50basically have duplicate references so
- 7:11:53this script would have a list of all the
- 7:11:54recipes then some other script would
- 7:11:55also have a list of all the recipes and
- 7:11:57then if you wanted to add a brand new
- 7:11:59recipe you would need to add it to all
- 7:12:00the list on all the scripts whereas like
- 7:12:03this any script that needs to know about
- 7:12:05all the recipes just needs a reference
- 7:12:07to the recipe list as so and whenever we
- 7:12:09want to add or remove a recipe we just
- 7:12:11need to update this one object and
- 7:12:12everything works perfectly that's one of
- 7:12:14the benefits of this approach where you
- 7:12:16have a scriptable object to hold a list
- 7:12:18of all the objects of some type
- 7:12:20personally I find this pattern to be
- 7:12:21quite useful okay so on delivery manager
- 7:12:24we have a list of all of our recipes now
- 7:12:26let's just make a simple timer to spawn
- 7:12:28them like I mentioned previously in the
- 7:12:29spawn plate logic you could just use a
- 7:12:31co- routine if you like that co-
- 7:12:33routines can be useful for running
- 7:12:35timers but personally like I mentioned I
- 7:12:37do not like co- routines I don't like
- 7:12:38the pattern they force you to use so
- 7:12:40over here I'm just going to make a
- 7:12:42simple float timer so a private float
- 7:12:44for the spawn recipe timer and another
- 7:12:47one for the recipe timer Max and let's
- 7:12:50say 4 seconds then we just do a simple
- 7:12:53private void update on update let's
- 7:12:56count down the timer so time. Delta time
- 7:12:59and if the spawn timer is is under 0f
- 7:13:02let's reset the timer and now let's
- 7:13:05basically spawn a recipe so for that
- 7:13:06let's grab a random one from the list so
- 7:13:09we go into the recipe listo and grab the
- 7:13:11recipe so list then we're going to grab
- 7:13:14a random one so let's get a random index
- 7:13:16so random. range between zero and the
- 7:13:19recipe and listo do recipo list. count
- 7:13:23so you get a random one this is going to
- 7:13:24be a recipe so for the waiting recipe so
- 7:13:28and then we simply go into the waiting
- 7:13:30recipe so list
- 7:13:31and we add a brand new recipe okay
- 7:13:34that's it super simple let's just make
- 7:13:35sure to initialize the list so let's do
- 7:13:37here a simple awake for the waiting
- 7:13:39recipe ass on list and just initialize
- 7:13:41it okay so like this it should be
- 7:13:43working however we're also going to
- 7:13:45generate recipes non-stop we don't want
- 7:13:47that so let's find some kind of Maximum
- 7:13:50so let's find a simple in for the
- 7:13:52waiting recipes
- 7:13:55Max let's say we can have a maximum of
- 7:13:58four recipes waiting and then down here
- 7:14:01when time elapses so if the waiting
- 7:14:03recipe has only stock count if it is
- 7:14:05under the maximum then we generate an
- 7:14:07added okay that's it pretty simple now
- 7:14:10for testing let's just add a log here to
- 7:14:12print the name so debug. log on the
- 7:14:14waiting recipe so that we generate so
- 7:14:17let's print out the recipe name okay so
- 7:14:20let's test so here we are and yep one
- 7:14:22will spawned right away so we have a
- 7:14:23salad and after 4 seconds yep there you
- 7:14:25go another salad and if we wait for 4
- 7:14:27seconds we should have another one there
- 7:14:29you go a mega burger recipe and finally
- 7:14:31after 4 seconds we have yep we have
- 7:14:33another burger and now no matter how
- 7:14:35much time passes there should be no more
- 7:14:38since we're at the limit and yep time
- 7:14:40passed and no more okay all right
- 7:14:41awesome so we are correctly generating
- 7:14:44recipes that the customers are waiting
- 7:14:45for now let's set logic to try to
- 7:14:47fulfill these orders so over here on
- 7:14:49delivery manager let's make a function
- 7:14:51to deliver a recipe so let's make a
- 7:14:54public void make it public since we're
- 7:14:56going to access this from the delivery
- 7:14:57counter call it deliver recipe and the
- 7:15:01recipes are going to be delivered whilst
- 7:15:03on a plate so let's receive a parameter
- 7:15:05of type Plate Kitchen object and over
- 7:15:08here the logic is actually going to be
- 7:15:09pretty simple we just need to cycle
- 7:15:11through all the recipes that the
- 7:15:13customers are waiting for and see if the
- 7:15:15ingredients on this plate matches the
- 7:15:17ones on any waiting recipe so over here
- 7:15:20let's cycle through all of our recipes
- 7:15:22so let's do a four enti zero going
- 7:15:25through the entire recipe list count i++
- 7:15:29okay let's grab the recip PSO for the
- 7:15:31waiting
- 7:15:33recipo and we grab from the waiting
- 7:15:35recipo list on this index okay so we
- 7:15:37have that then first let's do a quick
- 7:15:39test just to check if the waiting recipe
- 7:15:42has the same number of ingredients as
- 7:15:43there are on the plate if not then we
- 7:15:45already know that it's not valid so over
- 7:15:47here let's do a quick test SO waiting
- 7:15:50recipe so let's check the catchen object
- 7:15:52ass list. count if this one matches the
- 7:15:55play kitchen object let's get the
- 7:15:57kitchen object s on list and also check
- 7:15:59the count so over here we know that has
- 7:16:01the same number of ingredients so this
- 7:16:04is the first check then we need to cycle
- 7:16:07through all the ingredients on this
- 7:16:08recipe and all of the ingredients on the
- 7:16:10plate and basically see if both of them
- 7:16:12match so let's first cycle through the
- 7:16:14ingredients on the recipe so for each
- 7:16:18kitchen object ASO let's call it the
- 7:16:20recipe kitchen object so in the waiting
- 7:16:24recipe so let's go into the waiting
- 7:16:26recipe and get the kitchen object list
- 7:16:29okay so here we are cycling through all
- 7:16:32ingredients in the recipe then we need
- 7:16:35to cycle through all the ingredients on
- 7:16:37the plate so let's do another cycle for
- 7:16:40the Plate Kitchen object so and we're
- 7:16:42going to go inside the Plate Kitchen
- 7:16:44object get the kitchen object so list
- 7:16:46like this so here we are cycling through
- 7:16:49all the ingredients on the
- 7:16:51plate okay so now here basically we need
- 7:16:53to see if this ingredient that we're
- 7:16:55cycling through if this one matches the
- 7:16:57ingredient on the recipe so here we
- 7:17:00check if the Plate Kitchen object do so
- 7:17:03if this one matches the recipe kitchen
- 7:17:05object as so if so then the ingredient
- 7:17:08does match so in order to keep track if
- 7:17:11it does match over here before we cycle
- 7:17:14through all the ones on the plate let's
- 7:17:16define a bow for found or ingredient
- 7:17:19found let's defaed to false and over
- 7:17:23here if we have match and this one
- 7:17:25becomes true and by the way over here we
- 7:17:27can also break out of the cycle now if
- 7:17:29you're not familiar with break basically
- 7:17:31this is going to break out at four each
- 7:17:33so let's say the plate has 10
- 7:17:35ingredients and the second one matches
- 7:17:37when this cycle gets to the second one
- 7:17:38it triggers a break so it no longer goes
- 7:17:40through the remaining eight so basically
- 7:17:42it breaks out of the cycle so it keeps
- 7:17:43writing some code right down here okay
- 7:17:45so we cycle through all of the ones on
- 7:17:47the recipe then we cycle through the
- 7:17:49plate and if we do find that ingredient
- 7:17:51on that plate then we have an ingredient
- 7:17:53found so over here if we have a not
- 7:17:57ingredient
- 7:17:59found then over here that means means
- 7:18:01this
- 7:18:02recipe ingredient was not found on the
- 7:18:06plate so if that happens then
- 7:18:08essentially over here we have a fail
- 7:18:09state so the ingredient that this recipe
- 7:18:11requires is not on the plate so let's go
- 7:18:14up here when we have the same number of
- 7:18:15ingredients let's find a bullion called
- 7:18:18the plate contents matches recipe let's
- 7:18:21seea it to true and over here if we
- 7:18:23don't find at least one of them then the
- 7:18:25plate contents do not match the recipe
- 7:18:27and afterwards we can check this B again
- 7:18:31so if this one is true that means they
- 7:18:32all match if just one of them does not
- 7:18:35matches then this one won't be false so
- 7:18:37over here we know player delivered the
- 7:18:40correct recipe so over here let's do a
- 7:18:43quick debug. log and print out a
- 7:18:46message and after we do let's also do a
- 7:18:48return so we stop the rest of the
- 7:18:50execution so basically if we find a
- 7:18:52waiting recipe that matches we don't
- 7:18:53want to keep going and also here if we
- 7:18:56do find it let's also remove it from the
- 7:18:58list so let's go into waiting Q remove
- 7:19:00remove at and remove at this index okay
- 7:19:03so we're going to remove this recipe but
- 7:19:05if this doesn't happen then it's going
- 7:19:07to be keep cycling and it's going to
- 7:19:08cycle through all the recipes so
- 7:19:10basically if it reaches the end this
- 7:19:12four then basically no matches
- 7:19:16found so the player did not deliver a
- 7:19:20correct
- 7:19:22recipe so let's do another debug. log in
- 7:19:28here okay so this don't for logic
- 7:19:31it looks a bit complex but I hope this
- 7:19:32was easy to follow when we see it in
- 7:19:35action It all becomes a bit more clear
- 7:19:37so all that's left is just calling this
- 7:19:39function from the delivery counter so
- 7:19:40let's do that over here on the delivery
- 7:19:43counter it accepts plates it destroys
- 7:19:45plates but before we destroy let's go
- 7:19:48into delivery manager which means we
- 7:19:49need to access a reference so again we
- 7:19:51could add a serialized field or in this
- 7:19:53case it makes perfect sense to make this
- 7:19:55a Singleton so let's make it here public
- 7:19:57static of type delivery manager call it
- 7:20:00in
- 7:20:01with a public get and a private
- 7:20:05set okay then over here on awake let's
- 7:20:08set instance equals
- 7:20:10this all right so now over here on the
- 7:20:12delivery counter we can go into the
- 7:20:14delivery manager access the instance and
- 7:20:17deliver our recipe and pass in the Plate
- 7:20:19Kitchen
- 7:20:21object okay that should do it let's test
- 7:20:24all right so let's look in the log to
- 7:20:25see what they are waiting for so there
- 7:20:27are two cheeseburgers waiting another
- 7:20:29Mega burger and a cheeseburger so let's
- 7:20:32make a cheeseburger to deliver so first
- 7:20:34of all let's cook some meat let's slice
- 7:20:36some cheese let's pick up the meat
- 7:20:38before it burns pick up the cheese and
- 7:20:40we just need the bread okay this is a
- 7:20:42valent cheeseburger so let's deliver it
- 7:20:45and if there we go the player deliver
- 7:20:47the correct recipe okay great now let's
- 7:20:49deliver something that nobody asked for
- 7:20:51let's say just some meat actually let's
- 7:20:53burn it just for fun all right so there
- 7:20:56we have a bunch of charred meat so
- 7:20:57nobody really wants this but if we
- 7:20:59deliver yep there you go player did not
- 7:21:01deliver a correct recipe all right
- 7:21:03awesome so over here everything worked
- 7:21:05we have a bunch of recipes being
- 7:21:07generated and then we have the logic so
- 7:21:10that when the player delivers something
- 7:21:11it checks if the player delivered
- 7:21:13something correct or incorrect so
- 7:21:15everything is great all that's missing
- 7:21:16is obviously some nice UI so let's do
- 7:21:19that in the next
- 7:21:20lecture hello and welcome I'm your Cod
- 7:21:22monkey in this lecture we're going to
- 7:21:24create a nice UI visual to display our
- 7:21:26waiting recipes okay so our delivery
- 7:21:29manager is already working we are are
- 7:21:30randomly spawning some random recipes
- 7:21:32every once in a while now instead of
- 7:21:34looking at the console let's add a
- 7:21:35proper UI so for that over here in the
- 7:21:38editor let's go inside the canvas and by
- 7:21:39the way let's click on the button to
- 7:21:41unlock the canvas and this is actually
- 7:21:43the first time we're using the regular
- 7:21:44canvas quite a while ago we just created
- 7:21:46it we didn't really set it up so let's
- 7:21:48quickly do that for the random mode this
- 7:21:50one is meant to be a regular UI so let's
- 7:21:53leave it on the screen space overlay
- 7:21:55then over here on the canvas scaler
- 7:21:57instead of constant pixel size let's go
- 7:21:59with scale with screen size then for the
- 7:22:01reference resolution I like to use 1920
- 7:22:03by 1080 and finally I like to fully
- 7:22:06match with the height basically this
- 7:22:08means that objects in the canvas will
- 7:22:09only be scaled if the height changes for
- 7:22:12example let's head inside just a quick
- 7:22:14UI image just a test let's look in the
- 7:22:16game view there you go there's the image
- 7:22:18let's just put on a different color okay
- 7:22:20so there's the image and note how if I
- 7:22:22modify the aspect ratio here so let's
- 7:22:24say I put it on 5x4 there you go the
- 7:22:26horizontal size of the window changed
- 7:22:28but note how the element was not scaled
- 7:22:31so I can put it even on free aspect so
- 7:22:33really wide and does not change the size
- 7:22:35whereas if I modify this if I modify the
- 7:22:37vertical size the image does indeed get
- 7:22:40Scaled up or down personally I like the
- 7:22:42setup because means that I only have to
- 7:22:44worry about positioning things
- 7:22:45horizontally if the vertical part gets
- 7:22:47changed everything gets automatically
- 7:22:48scaled okay so great so over here let's
- 7:22:51go back into full HD all right and let's
- 7:22:53get rid of the image all right back in
- 7:22:55the scene view let's quickly look at the
- 7:22:57canvas so we can select the canvas press
- 7:22:59the F in order to zoom out and also we
- 7:23:01can press the 2D button up here to go
- 7:23:03into 2D mode okay so here's our nice UI
- 7:23:06now inside the canvas let's create an
- 7:23:07empty game object call it the delivery
- 7:23:10manager UI then in the inspector let's
- 7:23:12make it stretch to occupy the whole
- 7:23:14thing so let's put zero on everything
- 7:23:17okay so this window now occupies the
- 7:23:18entire screen now inside let's do just
- 7:23:21like we did a while ago for the plate
- 7:23:23icons meaning let's make the template
- 7:23:25that we can then clone but let's also
- 7:23:27put those templates inside of a
- 7:23:29container so first of all let's make the
- 7:23:30the container so a new empty game object
- 7:23:32call it just the container the reason
- 7:23:34why I'm going with this approach is
- 7:23:36because I also end to have other objects
- 7:23:38outside of here if you remember how we
- 7:23:40did with the templates we can actually
- 7:23:43go there and see so let's go inside the
- 7:23:45prefabs inside the counters actually
- 7:23:47it's on the kitchen objects let's go
- 7:23:49inside the plate over here for the
- 7:23:51template basically we use the plate
- 7:23:53icons UI this main canvas as the
- 7:23:55container but if you remember how we did
- 7:23:57that in order to make sure we didn't end
- 7:23:58up with duplicate icons we always
- 7:23:59destroy the previous one when we spawned
- 7:24:01a brand new one so every time we were
- 7:24:04cycling through the children of this
- 7:24:05object in order to destroy all of them
- 7:24:07except the template so over here we're
- 7:24:09going to use a container so that we can
- 7:24:10apply that logic only to the children of
- 7:24:12the container and that way we can have
- 7:24:14other objects outside of the container
- 7:24:16for example outside of here let's say we
- 7:24:18want some nice text just saying recipes
- 7:24:20in waiting so on delivery manager let's
- 7:24:23make it a child of that one let's go
- 7:24:24into UI and let's make a text textmesh
- 7:24:27Pro and this is the first time that
- 7:24:28we're using textmesh Pro so this window
- 7:24:31pops out let's actually import the text
- 7:24:32mesh Pro Essentials okay just let it
- 7:24:34import okay that's it we don't need the
- 7:24:36examples are extra so let's just close
- 7:24:38this window over here on this window
- 7:24:40let's name this the title text let's set
- 7:24:43the text to something like recipes
- 7:24:45waiting let's put it up there on the
- 7:24:47corner so let's anchor it on the top
- 7:24:49left corner also for the text I like to
- 7:24:51put it on a width and height of zero but
- 7:24:53of course that makes the text really
- 7:24:55vertical so then down here on the
- 7:24:56wrapping let's just disable it so there
- 7:24:58you go looks like that and let's put it
- 7:25:00over there on that corner now in scene
- 7:25:02view we are seeing things different so
- 7:25:04if you want to see what this looks like
- 7:25:06just go into the game View and over
- 7:25:07there yep we do see the recipes let's
- 7:25:08just make it in Bol so there you go just
- 7:25:10some nice text okay so that's our text
- 7:25:12and then for the container let's make
- 7:25:15inside the delivery template so let's
- 7:25:17create an empty game object let's call
- 7:25:19it the recipe template and for this one
- 7:25:22we're going to want to Anchor it to the
- 7:25:23top left corner so with the template
- 7:25:26selected over here in the inspector
- 7:25:27let's click and we want to click up here
- 7:25:30however
- 7:25:30we also want to set the pivot so let's
- 7:25:33make sure to hold down shift in order to
- 7:25:34set the pivot over there okay great
- 7:25:37that's exactly what we want so we want
- 7:25:38the template around the corner then
- 7:25:40let's give it a size of say 250 by 100
- 7:25:43okay now instead of template we just
- 7:25:45need two things we want the name of the
- 7:25:47recipe as well as the list of all the
- 7:25:49ingredients although before that let's
- 7:25:51actually make a nice visual for the
- 7:25:52background so a new UI image for the
- 7:25:55background let's make this one stretch
- 7:25:57to occupy the whole thing let's put
- 7:25:59everything on zero okay that's the
- 7:26:00background let's put it on a black with
- 7:26:03just a little bit lower Alpha okay
- 7:26:05that's good then for the name let's make
- 7:26:07a text field so inside the template
- 7:26:09let's create another text call it the
- 7:26:11recipe name text then over here let's
- 7:26:14put it a bit small so on a font size of
- 7:26:15maybe just 20 let's put it in bold and
- 7:26:19let's also again put the width and
- 7:26:20height of zero and over here make sure
- 7:26:22to disable wrapping okay so that's the
- 7:26:25text so we've got it up there let's just
- 7:26:26anchor it to the top left corner okay
- 7:26:28great over here we we can change the
- 7:26:30name to recipe and then what we need is
- 7:26:33the icons down here and for that we're
- 7:26:35going to do pretty much the exact same
- 7:26:37thing that we did on plate but before we
- 7:26:39do that logic let's just get this basic
- 7:26:40setup working so let's just position
- 7:26:42everything so first of all the container
- 7:26:44for all the templates let's anchor it on
- 7:26:47the top left corner and let's push it
- 7:26:49all the way over there and for
- 7:26:51positioning them let's use this time the
- 7:26:53vertical layout group so inside let's
- 7:26:56duplicate template just to be able to
- 7:26:57see them okay so that's pretty much what
- 7:26:59we want we can actually set the width
- 7:27:01and height both to zero and let's set
- 7:27:03the spacing to something like 30 okay so
- 7:27:05that's our basic UI now let's make the
- 7:27:07script to run this so over here in our
- 7:27:10scripts let's create a brand new C
- 7:27:12script for the delivery manager UI let's
- 7:27:15go into the parent game object and let's
- 7:27:17attach to script let's open okay so now
- 7:27:19here first we need a field for the
- 7:27:21container and another one for the
- 7:27:23template so let's do a serialized field
- 7:27:26private transform for the
- 7:27:28container and another another one for
- 7:27:30the transform and this is going to be
- 7:27:32the recipe template then let's do pretty
- 7:27:35much the same thing we did previously so
- 7:27:36first of all let's actually go onw in
- 7:27:38order to hide the template so game
- 7:27:40object set active into false okay so
- 7:27:43first we hide the template then let's
- 7:27:45make an update visual function so
- 7:27:46private void update Visual and for
- 7:27:49updating we're going to do the exact
- 7:27:51same thing that we did so first let's
- 7:27:53cycle through the container and destroy
- 7:27:54everything except for the template so do
- 7:27:57a 4 in transform child in the container
- 7:28:02and if the child is the
- 7:28:04template if so then we're going to
- 7:28:06continue and if not we're going to
- 7:28:08destroy the child game object okay so we
- 7:28:11have the cleanup now all we need is to
- 7:28:13cycle through all the waiting recipes so
- 7:28:16that means that over here on delivery
- 7:28:17manager we need to expose our waiting
- 7:28:19recipe as on list so let's go down here
- 7:28:21make a function to do that public going
- 7:28:23to return a list of recipe so get
- 7:28:25waiting recipe so list and we just
- 7:28:29return return the waiting recipe as on
- 7:28:32list okay great so now here on the UI we
- 7:28:37can now go into the liy manager accy
- 7:28:39static instance in order to get the
- 7:28:41waiting recipes on list so let's cycle
- 7:28:44through this so do a 4 in for each
- 7:28:46recipe so recipe so in the waiting
- 7:28:49recipe on list and for each of them
- 7:28:51let's
- 7:28:53instantiate and let's spawn our recipe
- 7:28:56template spawn it inside the container
- 7:28:59and then we just need to set this to
- 7:29:00enabled so let's grab the transform for
- 7:29:02the recipe transform we grab this one
- 7:29:05grab the game object and set active into
- 7:29:07true okay so like this the only thing
- 7:29:09missing is the text but that's okay for
- 7:29:11now let's just see where we're going to
- 7:29:13call this function to update the visuals
- 7:29:15and as usual we want to be smart and
- 7:29:17write some good clean code so let's not
- 7:29:20do the dirty approach of just updating
- 7:29:22this on every single update instead
- 7:29:24let's only call this function when
- 7:29:25something actually changes so over here
- 7:29:27on the delivery manager let's just make
- 7:29:29some simple events
- 7:29:30so public event event handler let's call
- 7:29:34on recipe spawn and another one call it
- 7:29:37on recipe
- 7:29:40completed and actually as soon as I add
- 7:29:42the event handler which also add using
- 7:29:44system now here we have an interesting
- 7:29:46thing we've got a nice namespace
- 7:29:47Collision it's telling us that random is
- 7:29:49an ambiguous reference between Unity
- 7:29:51engine. random and system. random that
- 7:29:53is because both these name spaces Unity
- 7:29:55engine and system both of them have a
- 7:29:57class named exactly random so the here
- 7:30:00does not know which class we're trying
- 7:30:01to use to solve this conflict we really
- 7:30:04just need to be more specific in this
- 7:30:06case here we want to use the unity
- 7:30:07engine version so let's just write the
- 7:30:08full name Unity engine. random and yep
- 7:30:11that works okay so now let's fire off
- 7:30:13the events so first of all the on recipe
- 7:30:16spawn so over here when we spawn a
- 7:30:18recipe let's invoke this event so this
- 7:30:21event tars empty and let's also get rid
- 7:30:23of along we don't long need that okay
- 7:30:25now we could also add the waiting recipe
- 7:30:27on the event ARS but in this case we
- 7:30:29don't need it just firing the event is
- 7:30:30enough and then down here when the
- 7:30:32player delivers something if the player
- 7:30:34delivers the correct recipe we remove it
- 7:30:35from the list and then let's fire off
- 7:30:38the event so on recipe completed let's
- 7:30:40invoke with this and event arsmt okay so
- 7:30:44we have the event and down here we also
- 7:30:45don't need a log okay so that works and
- 7:30:49finally over here on the delivery men UI
- 7:30:51let's just make a private void start on
- 7:30:54start going to delivery manager access
- 7:30:56the static instance and listen to both
- 7:30:58these events so the spawn and let's also
- 7:31:00listen to the other one so delivery
- 7:31:02manager instance on recipe completed
- 7:31:05when either of these work let's just go
- 7:31:07and update the visual so just like this
- 7:31:10let's also rename this because again
- 7:31:12instance doesn't sound like a very good
- 7:31:13name let's actually rename this to
- 7:31:15delivery manager and same thing up here
- 7:31:18by the way I'm using the visual studio
- 7:31:20shortcut control RR in order to rename
- 7:31:22this to delivery
- 7:31:24manager and finally we also need to
- 7:31:27update the visual on start just to make
- 7:31:28sure the previous ones do not show up
- 7:31:31okay that's it so like this it should be
- 7:31:33working we should be able to see no
- 7:31:35Visual and then as more are spawned we
- 7:31:37should be able to see each one being
- 7:31:38spawned until the maximum so let's see
- 7:31:40just over here in the U let's make sure
- 7:31:42to drag the references so the container
- 7:31:44and the template and let's set on play
- 7:31:46and okay right away actually it spawned
- 7:31:48one recipe it spawned instantly then
- 7:31:50after 4 seconds there you go a second
- 7:31:51one and after 4 seconds we should be
- 7:31:54able to see yep another one now four
- 7:31:56more seconds and we should see the final
- 7:31:58one and now no matter how long we wait
- 7:32:00it should no longer spawn anymore and
- 7:32:02yep that works all right awesome so the
- 7:32:05basic logic is working now let's handle
- 7:32:07the proper Logic on the template for
- 7:32:09that like I mentioned previously one
- 7:32:11approach would be over here you could go
- 7:32:14and do a transform. find find the actual
- 7:32:18recipe name text then get the text mesh
- 7:32:20component set it that would work but
- 7:32:22like I mentioned previously that would
- 7:32:23be very dirty not good at all we should
- 7:32:26avoid using find at any time and we
- 7:32:28should also avoid the individual logic
- 7:32:30from the total logic so let's do it
- 7:32:33properly and make a proper script to
- 7:32:35handle each spawn template so let's
- 7:32:37create a brand new C script call this
- 7:32:39delivery manager single UI single just
- 7:32:43because refers to a single recipe and
- 7:32:45also right now we already have quite a
- 7:32:47few UI scripts so let's organize our
- 7:32:50project again so let's organize a new
- 7:32:51folder for the UI and inside let's put
- 7:32:54all of our UI scripts so the LI manag is
- 7:32:56single this one D play icons play icons
- 7:32:59and the progress bar let's put all of
- 7:33:02these nicely organized in the UI folder
- 7:33:04okay so with the script let's go into
- 7:33:05the recipe template and attach script
- 7:33:07now let's open and over here let's begin
- 7:33:09by adding a field for our text so a
- 7:33:12serialized field and over here it's also
- 7:33:15very important for the text we are not
- 7:33:17using the text inside unityengine.ui
- 7:33:20this is the Legacy text it is not textes
- 7:33:23Pro so this is not what we were using
- 7:33:25instead we want to use text mesh Pro UGI
- 7:33:29which is in inside TM Pro so we need to
- 7:33:32go up here and add using TM Pro and now
- 7:33:34we can use this type and also make sure
- 7:33:36you're using text mes Pro Yi and not
- 7:33:38text mesh Pro this one also exists but
- 7:33:40don't mix these two these are two very
- 7:33:42different types if we go over here in
- 7:33:45the editor and if outside the canvas if
- 7:33:48I just create and create new 3D object
- 7:33:50and new text object if I do that then if
- 7:33:53we'll look over here in the inspector we
- 7:33:54see this one is of type text mesh Pro
- 7:33:56whereas for the ones that we're using
- 7:33:58inside the canvas if we look this is
- 7:34:00text mesh Pro it's a UI text so these
- 7:34:02are the two different classes within
- 7:34:04text mesh Pro you have text mesh Pro and
- 7:34:07text mesh Pro UGI we're working on the
- 7:34:09UI so we want this one okay so we name
- 7:34:12this the recipe name text okay that's it
- 7:34:16over here into the editor let's drag our
- 7:34:18reference all right so on the script
- 7:34:19let's make a function to set the recipe
- 7:34:21so a public void and let's call it set
- 7:34:24recipe
- 7:34:28so and we going to receive a recipo
- 7:34:31recipe so then we just go into the
- 7:34:34recipe name text and we set the text to
- 7:34:36recipo do recipe name okay so that's
- 7:34:39pretty much it now over here on the U
- 7:34:41script when we instantiate our recipe
- 7:34:44transform let's get component of type of
- 7:34:48our delivery manager single UI and call
- 7:34:52set recipes so and pass in the recipe so
- 7:34:54okay so let's see if the name shows up
- 7:34:56and if right way it does show up so we
- 7:34:58can see that we generate the
- 7:34:59cheeseburger recipe and right now a mega
- 7:35:02burger recipe okay great so all that's
- 7:35:04left are the icons down here so like I
- 7:35:06said that is going to be yet another
- 7:35:08usage of our template pattern so inside
- 7:35:12the recipe template let's create an mty
- 7:35:14game object call it the icon container
- 7:35:17and then inside that let's make the
- 7:35:19template and template is just going to
- 7:35:20be an image so we can just create an
- 7:35:21image St away call it the ingredient
- 7:35:25image let's scale it with a size of 40
- 7:35:28and 40 let's put a image by default just
- 7:35:31like that and on the icon container
- 7:35:33let's put the width of zero height of
- 7:35:35zero and let's put a horizontal layout
- 7:35:37group put it over there on the left side
- 7:35:40and we can create a bunch more just to
- 7:35:42see how it looks okay so that's pretty
- 7:35:44much it now over here on the single
- 7:35:46script let's add a serialized field
- 7:35:49private transform for the icon container
- 7:35:52and another one for the icon
- 7:35:55template then we do the same thing as
- 7:35:57usual so when we set the recipe so let's
- 7:36:00first of all clean up the container so
- 7:36:01let's do for each transform child in the
- 7:36:05icon
- 7:36:06container and if the child is the
- 7:36:09template then we want to continue and
- 7:36:11ignore it if not we want to destroy the
- 7:36:13child. game object okay so that's a
- 7:36:16cleanup and then let's do for each
- 7:36:19kitchen object so in the recipe so do
- 7:36:23kitchen object ass own
- 7:36:25list second through all this let's
- 7:36:28instantiate our icon temp
- 7:36:30template instantiated inside the icon
- 7:36:33container so this going to be the
- 7:36:35transform for the icon
- 7:36:37transform then as usual we need to go
- 7:36:39into the game object set active in order
- 7:36:41to enable it and also let's go up here
- 7:36:45make a private void awake and on awake
- 7:36:46the icon template game object let's
- 7:36:49disable it okay we don't want the
- 7:36:51template to be visible okay so we
- 7:36:54insantiy template we set it as active
- 7:36:58then since this one just has an image we
- 7:36:59can just do a get component of Type
- 7:37:02image that's image not image
- 7:37:05conversion so image so it's this one the
- 7:37:08one inside unityengine.ui so let's get
- 7:37:11this image and let's modify the Sprite
- 7:37:13and set it to this kitchen object as so.
- 7:37:15Sprite okay so that's it that should do
- 7:37:18it let's test over here in the editor
- 7:37:20let's just go into the template let's
- 7:37:22drag the container reference and the
- 7:37:24template reference and let's also rename
- 7:37:26this instead of ingredient image put
- 7:37:28icon template just to be AIT more clear
- 7:37:30and we can get rid of the other ones or
- 7:37:31leave them doesn't really matter okay
- 7:37:33great so let's head on play and see and
- 7:37:36yep right away it does work so we can
- 7:37:37see a burger is composed of a burger and
- 7:37:39a bun a salad yep there you go some
- 7:37:42sliced cabbage and sliced tomatoes then
- 7:37:44cheeseburger same thing as the burger
- 7:37:45with some cheese and then another Burger
- 7:37:47let's just deliver until we see the mega
- 7:37:49Burger so let's deliver a cheeseburger
- 7:37:52let's cut
- 7:37:53it get this get some bread place it in
- 7:37:56there pick it up before it burns that's
- 7:37:58a cheeseburgers so that one should
- 7:38:00vanish and Y there we go it does vanish
- 7:38:02let's see if something else not
- 7:38:03cheeseburger so let's keep doing until
- 7:38:05we get the mega burger just to see that
- 7:38:07everything works so let's deliver a
- 7:38:09regular burger okay now let's deliver a
- 7:38:12regular
- 7:38:16salad okay just pick up like that like
- 7:38:19that and drop it okay let's see any yep
- 7:38:23there it is the mega bar all right great
- 7:38:26so the visual logic is fully working and
- 7:38:28the delivery logic all of it is working
- 7:38:31so I can deliver the right recipes and
- 7:38:33get rid of them from the recipe waiting
- 7:38:34list and more are spawn every time here
- 7:38:37we can see the name of the recipe as
- 7:38:38well as all of the nice icons okay so
- 7:38:41with all this our game is really taking
- 7:38:42shape everything is very close to being
- 7:38:44done one massive thing we're still
- 7:38:46missing is an obvious one which is sound
- 7:38:48so let's do that in the next
- 7:38:51lecture hey again quick intermission
- 7:38:53you're almost at the end so once again
- 7:38:55congrats for making it this far this is
- 7:38:57the second secret call out go ahead Post
- 7:38:59in the comments a time stamp and a nice
- 7:39:01monkey emoji it won't be fun to see how
- 7:39:03many people make it to this point by now
- 7:39:05you already know about the website I
- 7:39:07hope it's been very useful to you and
- 7:39:09you already know to ask any questions in
- 7:39:10the comments if you need help with
- 7:39:12anything so all that's left for me to
- 7:39:14say right now is thanks for watching the
- 7:39:15course so far and I really hope you've
- 7:39:17already learned a ton there's only a
- 7:39:19bunch more lectures until we get to the
- 7:39:21final polished game so let's continue on
- 7:39:23the next
- 7:39:24lecture hello and welcome I'm your Cod
- 7:39:26monkey in this lecture we're going to
- 7:39:28add some audio to our game starting with
- 7:39:30a really nice music track okay so our
- 7:39:33game is already looking pretty good but
- 7:39:34everything is still way too silent so
- 7:39:37let's begin by adding some music adding
- 7:39:39this is actually extremely easy to do in
- 7:39:42the included assets over here inside the
- 7:39:44sounds we've got a really nice music
- 7:39:45track I hired the musician to make this
- 7:39:48it sounds really good it's a seamless
- 7:39:50Loop so to add to our game it's going to
- 7:39:51be super simple we just want a constant
- 7:39:54never ending Loop so let's begin by
- 7:39:56creating an mty game object call it the
- 7:39:58Music Manager manager let's reset
- 7:40:01transform keep things organized and
- 7:40:03let's add a component and we want the
- 7:40:04component an audio Source here is this
- 7:40:07one like new implies this one acts like
- 7:40:10a source of audio you will note how by
- 7:40:12default on the main camera down here it
- 7:40:15already has an audio listener so the
- 7:40:17source plays some sound and The Listener
- 7:40:18listens to it now for here we just need
- 7:40:20to set these fields so for example on
- 7:40:22the audio clip let's make sure to drag
- 7:40:24the music audio clip okay great next
- 7:40:27over here let's enable play on awake we
- 7:40:29wanted to start playing right away and
- 7:40:31for this track we do want to enable
- 7:40:33looping okay great then for priority
- 7:40:36basically Unity has a limit to how many
- 7:40:38sounds can be played at once if you play
- 7:40:40too many then some sounds won't play and
- 7:40:42which ones do you play is all based on
- 7:40:44priority we always want the music to
- 7:40:46play so let's put this one on Max
- 7:40:48priority then for the volume later on
- 7:40:51we're going to make a proper option
- 7:40:52screen to handle this but for now let's
- 7:40:55put it on something like 04 or5 just
- 7:40:58make a nice background track
- 7:41:00then we have here the spatial blend for
- 7:41:02this music track we wanted to play the
- 7:41:04same regardless of where the camera is
- 7:41:06so let's make this all the way fully a
- 7:41:082d sound okay and that's it we don't
- 7:41:10need to play around with any of the
- 7:41:11other settings and just like this if we
- 7:41:13are on play any up there's the music now
- 7:41:16if you're not hearing anything make sure
- 7:41:18that on the game view first of all that
- 7:41:20the game is actually selected make sure
- 7:41:21the scene is in Focus so over here I can
- 7:41:24move around so the game is in Focus then
- 7:41:26on the game view over here on the top
- 7:41:27right corner make sure this sound sound
- 7:41:29icon is toggled if not then everything
- 7:41:31is muted and also again make sure like I
- 7:41:34mentioned on the main camera that it has
- 7:41:35the audio listener component with all of
- 7:41:37that yep you should be able to hear the
- 7:41:39music now this song is playing and it
- 7:41:41won't Loop forever just like we wanted
- 7:41:43personally I really like how it sounds
- 7:41:45I'm really happy with what the composer
- 7:41:47made it perfectly matches the vibe of
- 7:41:48the game so it really is this simple to
- 7:41:51add some music to the game let me just
- 7:41:53point out one thing also related to
- 7:41:54sound one of the things you can make is
- 7:41:57an audio mixer so for example on the
- 7:41:59project files let's create a brand new
- 7:42:02and let's find over here the audio mixer
- 7:42:04so there you go here is an audio mixer
- 7:42:06then you can double click to open up the
- 7:42:07audio mixer window and then over here
- 7:42:09you have the master node and then you
- 7:42:12can create multiple groups so let's
- 7:42:14create a brand new group for something
- 7:42:16else and then you can play around over
- 7:42:18here with the effects with the volume
- 7:42:20all kinds of things all kinds of effects
- 7:42:21everything then for each sound where you
- 7:42:24have the audio Source over here note how
- 7:42:25you have an output and for this output
- 7:42:28you can set it to play on the fter so it
- 7:42:29plays on everything or set it on just
- 7:42:31one individual group so with this you
- 7:42:33could assign a group to one individual
- 7:42:35type of sound effect or the music or so
- 7:42:37on maybe you could even have your music
- 7:42:40split into multiple stems so there's
- 7:42:42lots you can do but for me I'm not an
- 7:42:44audio engineer audio is probably the
- 7:42:46part of game development that I know
- 7:42:47least about I just stick with the
- 7:42:49absolute Basics but if you want to learn
- 7:42:51more definitely look into the audio
- 7:42:52mixer this is an extremely powerful tool
- 7:42:55but like I said for me I don't know how
- 7:42:56to work with it so I'm just going to
- 7:42:58stick with basics
- 7:42:59so on the output let's revert back into
- 7:43:01none close the audio mixer and get rid
- 7:43:03of this and there it is the music is
- 7:43:06playing and it all sounds really nice
- 7:43:08all right so here we very easily added
- 7:43:10some music to our game this lecture is
- 7:43:12actually super short because it is
- 7:43:13genuinely that simple now the next thing
- 7:43:15that we need is going to be a little bit
- 7:43:17more complex and that is adding sound
- 7:43:19effects so let's do that in the next
- 7:43:22lecture hello and welcome I'm your code
- 7:43:24monkey in this lecture we're going to
- 7:43:26add some sound effects for our game okay
- 7:43:28so previously we already added some
- 7:43:30really nice music now let's add a whole
- 7:43:32bunch of sound effects in the project
- 7:43:34files if we go inside the assets over
- 7:43:36here we've got all kinds of sound
- 7:43:37effects basically I heard a really nice
- 7:43:40sound designer to make all of these and
- 7:43:41I think they all sound really great so
- 7:43:43let's add them to our game now when it
- 7:43:45comes to sound effects there are two
- 7:43:47main ways to play a sound one is just
- 7:43:49like we did for the music so we can
- 7:43:50create a game object add the audio
- 7:43:52Source component and play it that's one
- 7:43:54approach but that basally requires pre-
- 7:43:56preparing the sound objects so there is
- 7:43:58an another simpler way that just
- 7:44:00requires one line of code so let's begin
- 7:44:02by making a Sound Manager game object so
- 7:44:04a new empty game object for The Sound
- 7:44:06Manager let's reset the transform now
- 7:44:09let's make our script so let's go in the
- 7:44:11scripts folder create a brand new C
- 7:44:13script for The Sound Manager let's
- 7:44:16attach a script and open okay so now
- 7:44:18here let's make a function to play
- 7:44:20Simple sound so let's do a private void
- 7:44:23just call it play sound and over here
- 7:44:26the way we play sound through codes
- 7:44:27actually super simple we just just go
- 7:44:29inside the audio Source class and in
- 7:44:32here there's a static function play clip
- 7:44:34at point this as you can see takes an
- 7:44:36audio clip a vector 3 for the position
- 7:44:38and finally a volume so basically it
- 7:44:40won't play that sound on that position
- 7:44:42by default Unity already has 3D sound so
- 7:44:45if you play the sound on the left or the
- 7:44:46right side of the camera it will play in
- 7:44:48the correct place also for the volume
- 7:44:50the further away it is from the camera
- 7:44:51the lower it will be and if we don't
- 7:44:53want the 3D sound we can just play
- 7:44:55directly on top of the camera position
- 7:44:57okay so in this function let's receive
- 7:44:58our arguments so for the audio clip it's
- 7:45:02going to be our audio clip then let's
- 7:45:05receive Vector 3 for the position and
- 7:45:07let's also receive an optional one for
- 7:45:09the volume let's just default this to 1f
- 7:45:13okay so here we just pass this in into
- 7:45:15our function so the position and the
- 7:45:16volume okay great so now let's call this
- 7:45:19nice function and for example let's
- 7:45:21start with a simple one so let's start
- 7:45:23with the delivery sounds so over here on
- 7:45:25the delivery manager script down here we
- 7:45:28have the logic for delivering a recipe
- 7:45:30and over here we know when we completed
- 7:45:32a successful recipe or when we failed
- 7:45:34and the player delivered a wrong recipe
- 7:45:36so this is where we want to play some
- 7:45:38sounds and again here we have yet
- 7:45:40another very important clean code
- 7:45:42question we could technically call the
- 7:45:44play sound function directly from here
- 7:45:46that would work but of course that would
- 7:45:48make this class tightly coupled with The
- 7:45:49Sound Manager for a simple game on this
- 7:45:52scale that approach can work just play
- 7:45:54sounds directly from the logic code
- 7:45:56however again to make things properly we
- 7:45:58should should really separate the logic
- 7:46:00from the sound just like we separated
- 7:46:01the logic from the visuals so instead
- 7:46:04let's not call the sound directly from
- 7:46:06here instead let's make two more events
- 7:46:09so let's make one on recipe success and
- 7:46:12another one on recipe
- 7:46:14failed okay so now let's fire off these
- 7:46:17events so over here we have the success
- 7:46:19so on recipe success and if we get down
- 7:46:22here then we have a fail so on recipe
- 7:46:25fail okay great we have two events now
- 7:46:28back here on The Sound Manager we can
- 7:46:30just listen to those so let's do a start
- 7:46:31go into delivery manager access the
- 7:46:33instance and listen to the on success
- 7:46:36and on failed events so listen to that
- 7:46:39one delivery manager instance on recipe
- 7:46:42failed listen to both of these again
- 7:46:44let's write some good clean codes let's
- 7:46:46rename this one instead of instance
- 7:46:48let's put it delivery manager and same
- 7:46:51thing on this one also name it correctly
- 7:46:54delivery manager okay great so now when
- 7:46:58we have this we want to call play sound
- 7:47:02and now want to pass in a reference to
- 7:47:04the recipe fail sound so technically one
- 7:47:07approach would be up here to add a
- 7:47:08serialized fi for an audio clip that
- 7:47:10would work but since we've already done
- 7:47:12that so many times in this course here
- 7:47:14let's use a different approach that I
- 7:47:15also like to use let's create a script M
- 7:47:18object to hold a reference to all of our
- 7:47:20sounds so similar to how we Define the
- 7:47:22script M object hold all of our recipes
- 7:47:24let's just comment this out just to make
- 7:47:26sure the code compiles okay great so
- 7:47:28back here in the other edor let's make a
- 7:47:29new Script Mod object type so let's
- 7:47:31create a brand new C script for the
- 7:47:33audio clip refs Script Mod object now
- 7:47:37here let's make this a simple scriptable
- 7:47:40object with a create asset
- 7:47:42menu okay so now for the fields if we
- 7:47:46look in the S over here the audio design
- 7:47:48that I hired actually made several
- 7:47:50variations for each sound so we've got
- 7:47:52multiple chops multiple delivery fails
- 7:47:54and so on so back in the code here
- 7:47:56instead of storing a reference for a
- 7:47:57single audio clip
- 7:47:59let's store an array for all of them so
- 7:48:01we have the chop then we have all the
- 7:48:03others so let's just add all of the
- 7:48:06references so there's a chop there's the
- 7:48:08delivery
- 7:48:09fail then we have delivery success then
- 7:48:13we have
- 7:48:16footsteps then the object drop then the
- 7:48:19object pickup then we have the stove
- 7:48:23Sizzle although this one is just one
- 7:48:25then we have the trash and finally we
- 7:48:28have the warning
- 7:48:31all right so these are all the sound
- 7:48:32references we're going to use back in
- 7:48:34the editor let's just create the object
- 7:48:36so on the script M objects let's create
- 7:48:38a brand new one let's make it of audio
- 7:48:41clip refs so just name it audio clip
- 7:48:44refs
- 7:48:45Soo and over here let's just wrag the
- 7:48:47references so let's use that quick un
- 7:48:49tip in order to un lock the inspector
- 7:48:51now I can select all the chops and drag
- 7:48:53them all delivery fails drag them
- 7:48:56delivery success drag it then for all of
- 7:48:59the footsteps after that are all of the
- 7:49:02object drops then the pickups then we
- 7:49:06have the sizzle which is just one
- 7:49:08finally we have the trash and the
- 7:49:10warning okay those are all the
- 7:49:12references so our script object now has
- 7:49:15all of the data we need let's unlock the
- 7:49:18inspector okay and back in the code here
- 7:49:20on The Sound Manager let's make another
- 7:49:22version of this function so let's make
- 7:49:24one play sound except instead of
- 7:49:25receiving an audio clip it receives an
- 7:49:27array of audio clip I then basically we
- 7:49:30just call the other function so we call
- 7:49:32the other play sound function and pass
- 7:49:34in an audio clip from this array so
- 7:49:35let's actually rename this so audio clip
- 7:49:38array and let's pass in an audio clip
- 7:49:40from here so do a simple random.
- 7:49:43range between zero and the array. length
- 7:49:47passing the position and the
- 7:49:50volume okay so just like this now we
- 7:49:52need is a reference to our scrip object
- 7:49:54so a seriz film private of the audio
- 7:49:57clip refs so
- 7:50:00okay we have this then here in the
- 7:50:02editor let's just assign the reference
- 7:50:04so the audio clip reference okay great
- 7:50:06and over here when we have the recipe
- 7:50:08failed let's go into the audio clip reps
- 7:50:11and let's pick up this one is delivery
- 7:50:13fail and then the other one is going to
- 7:50:15be delivery
- 7:50:16success for the position let's just
- 7:50:19default to the camera. main
- 7:50:21transform.position
- 7:50:24so like this the sounds will play
- 7:50:26exactly on top of the camera okay so
- 7:50:28let's and see if it all works okay so
- 7:50:30here we are and let's do a wrong
- 7:50:32delivery now quick warning if you're
- 7:50:34following along or if you're just
- 7:50:35watching the video this sound will
- 7:50:37probably be way too loud but let's test
- 7:50:40so if I just pick up the plate and I
- 7:50:41just deliver an empty plate yep there
- 7:50:44you go there's the sound and now if I
- 7:50:46deliver a correct one so someone wants a
- 7:50:48salad so let's cut a nice salad chop
- 7:50:51that chop this pick up the plate pick up
- 7:50:54that one and that one deliver the
- 7:50:56correct salad and yep there you go it
- 7:50:58does work all right great so the sound
- 7:51:00effects work they played perfectly but
- 7:51:02they're a bit too loud basically that's
- 7:51:04because these sounds were designed to be
- 7:51:06played in the world rather than on top
- 7:51:07of the camera so when we play the sound
- 7:51:10let's actually play it on the position
- 7:51:11of the delivery counter here is the
- 7:51:14delivery counter script and based on our
- 7:51:16design we're only going to have a single
- 7:51:18delivery counter so we can just make
- 7:51:20this a Singleton so as usual public
- 7:51:23static of type delivery counter call it
- 7:51:25instance with a public get and a private
- 7:51:28set
- 7:51:29then on private void awake let's just
- 7:51:32set the instance equals
- 7:51:34this okay so now over here on The Sound
- 7:51:37Manager we can just grab delivery
- 7:51:39counter delivery counter and we just go
- 7:51:42delivery counter and grab the static
- 7:51:44instance and then for the sound position
- 7:51:47we can just go delivery counter access
- 7:51:49the transform.
- 7:51:51position okay so just like this on that
- 7:51:53one and on this one
- 7:51:59okay so let's test now it shouldn't be
- 7:52:00as loud okay so here we are and let's do
- 7:52:03a wrong delivery and yep it does work
- 7:52:06now let's do a successful delivery so
- 7:52:08let's make a nice cheeseburger so grab
- 7:52:10some cheese slice it grab a plate just
- 7:52:13need some
- 7:52:15bread and deliver it and yep there you
- 7:52:18go it worked all right
- 7:52:20awesome okay so this is really it this
- 7:52:22is how we're going to play our simple
- 7:52:24sounds now there are some that are going
- 7:52:26to require more logic like the footstep
- 7:52:27sounds and stove Sizzle but first let's
- 7:52:30begin by adding the simple ones so let's
- 7:52:33begin with the chop sounds this is super
- 7:52:35simple we just need to go over here onto
- 7:52:37the cut en counter and actually we
- 7:52:39already have the uncut event that we
- 7:52:41made previously this was used to spawn
- 7:52:43the visual so we can also use it to
- 7:52:45spawn the sounds however there's
- 7:52:47actually one difference we're going to
- 7:52:49have multiple cutting counters and this
- 7:52:52one as you can see this one is not a
- 7:52:54static event meaning each different
- 7:52:56counter is going to have each list of
- 7:52:57listeners and we really don't want to
- 7:52:59have to subscribe to every single one of
- 7:53:01the counters individually so what we can
- 7:53:03do is instead of making it a regular
- 7:53:05event that belongs to each instance of a
- 7:53:07cutting counter we can make a static
- 7:53:09event which will belong to the entire
- 7:53:11class but we still want to leave this
- 7:53:13one just for the visual so let's do
- 7:53:14another one a public static event event
- 7:53:17handler and let's call it on any cut
- 7:53:21basically for any static events that
- 7:53:23belong to any object type I like to add
- 7:53:25the keyword any we're going to fire this
- 7:53:27event when any any cutting counter is
- 7:53:29going to trigger a cut action so where
- 7:53:32we fire this event is exactly the same
- 7:53:33thing so over here we've got the uncut
- 7:53:35let's do the exact same thing so on any
- 7:53:37cut with this and event rs. empty okay
- 7:53:39so we have our nice static event now
- 7:53:42over here on The Sound Manager let's
- 7:53:43listen to it so let's go into the cut en
- 7:53:45counter again we're going to access
- 7:53:46through the class name and let's listen
- 7:53:48to the on any cut event and over here
- 7:53:51let's just play the sound so let's play
- 7:53:53the sound let's go inside the audio clip
- 7:53:56refs so and let's grab the chop sound
- 7:53:59then for the position we want to know
- 7:54:01who fired this event and by following
- 7:54:03the C standard over here we already have
- 7:54:05the object sender so we know this was
- 7:54:08the object that fired this event and we
- 7:54:09know this is going to be of type cutting
- 7:54:11counter so we can just get cutting
- 7:54:12counter cutting counter and we just grab
- 7:54:15the sender as a cutting counter okay so
- 7:54:18we have this then over here very simple
- 7:54:20access transform.
- 7:54:22position okay that's it great that won't
- 7:54:25play The Cutting sound on that position
- 7:54:27on that cutting counter okay great now
- 7:54:29let's handle the player picking up
- 7:54:31something and for that let's go over
- 7:54:33here onto the player class and the way
- 7:54:35we set up the kitchen object parent
- 7:54:36system is actually already perfect for
- 7:54:38this down here we have a function so if
- 7:54:41we scroll down Yep this function set
- 7:54:43kitchen object this one is called
- 7:54:45whenever the player receives a kitchen
- 7:54:47object which means really when the
- 7:54:49player picks up something so if this
- 7:54:51kitchen object is not n then that means
- 7:54:53the player picked up something so let's
- 7:54:54do that so here let's make the event so
- 7:54:58a public event event handler call it on
- 7:55:02picked
- 7:55:03something and then down here just we
- 7:55:05test so if the catch an object is not
- 7:55:07null so if the player did pick up
- 7:55:09something then let's just fire off this
- 7:55:11event so just do our usual invoke with
- 7:55:14this and event RX that
- 7:55:18empty okay so that's great then on the
- 7:55:21sound manual let's just listen to it so
- 7:55:23let's go into the player class let's
- 7:55:25access the static instance and let's
- 7:55:27listen to the on picked up something
- 7:55:29event and again let's rename this to a
- 7:55:31proper name so player onp picked
- 7:55:33something and over here let's just play
- 7:55:35the sound and for the sound go into the
- 7:55:38refs and grab in this case the object
- 7:55:41pickup and for the position let's just
- 7:55:43go player do instance and grab the
- 7:55:46transform. position okay that's it next
- 7:55:49for item dropping now we can only drop
- 7:55:52items on a counter so over here we have
- 7:55:54the base counter class and again we have
- 7:55:56the same thing so we have the set
- 7:55:58kitchen object and again the same thing
- 7:56:00as with the cutting counter we don't
- 7:56:02want to be required to listen to every
- 7:56:04single counter we just want to listen to
- 7:56:06one event so let's make it up here so a
- 7:56:08public static event of type event
- 7:56:10handler and let's name it on any object
- 7:56:14placed
- 7:56:16here and then down here when we have the
- 7:56:18set kitchen object we do the usual if
- 7:56:20kitchen object is not null if so then
- 7:56:23let's fire off this event
- 7:56:28okay great and on the sound maner let's
- 7:56:31listen so go into the base counter on
- 7:56:33any object placed here when that happens
- 7:56:36play the sound and let's go into the
- 7:56:38other PRS and this one is the object
- 7:56:41drop so that one and for the position
- 7:56:44let's do the same thing we did so we
- 7:56:46cast the base counter equals the cender
- 7:56:48as a base counter and then we go into
- 7:56:51the base counter and let's grab the
- 7:56:53transform. position okay so we just need
- 7:56:56one more special counter type here we
- 7:56:58have the trash counter and this one it
- 7:57:01never really changes the parent it just
- 7:57:02destroys the object so over here on the
- 7:57:04trash counter itself let's fire off an
- 7:57:06event but again let's make it static
- 7:57:08even though we're only going to have one
- 7:57:10trash but make it static just to be able
- 7:57:11to support multiple so public static
- 7:57:14event event handler on any object
- 7:57:21trashed and then over here just fire off
- 7:57:24this event so invoke with this and event
- 7:57:28R is empty okay so now if we go into The
- 7:57:32Sound Manager and over here once again
- 7:57:34the trash counter on any not the on any
- 7:57:38object plac but on any object trashed
- 7:57:41and on this one let's do pretty much
- 7:57:43exactly the same thing so let's copy
- 7:57:44this the sound is going to be the trash
- 7:57:46sound instead of a base counter we could
- 7:57:50just cast it to a base counter but let's
- 7:57:51make it proper so let's make a trash
- 7:57:53counter as a trash counter and this is a
- 7:57:56trash counter okay great that's that's
- 7:57:58it so these are all of our basic simple
- 7:58:00sounds as you can see all the logic is
- 7:58:02super simple so let's test and see if it
- 7:58:04all works okay so first of all let's
- 7:58:06pick up an object so if I go into a
- 7:58:08container and I pick it up and Y there
- 7:58:10you go there's the sound now if I drop
- 7:58:11it somewhere and yep there's the sound
- 7:58:13now for the trash pick it up drop it on
- 7:58:15the trash and yep there's the trash
- 7:58:17sound okay great then also let's check
- 7:58:21out the cutting so I pick up some cheese
- 7:58:23drop it there and cut and you there you
- 7:58:25go got a really nice cutting sound okay
- 7:58:28so far so good now let's s on the more
- 7:58:30complex ones starting off with the stove
- 7:58:33for this one the sound is meant to be
- 7:58:35looping but only when the stove is on so
- 7:58:37we don't want to just play once but play
- 7:58:39and stop playing depending on the state
- 7:58:41of the stove so for this one instead of
- 7:58:44spawning the sound through code let's
- 7:58:45actually spawn it on the object itself
- 7:58:47so let's go inside the stove object
- 7:58:50let's go on the stove counter and open
- 7:58:52up the prefab and inside this prefab
- 7:58:55let's create a brand new empty game
- 7:58:57object name it sound let's reset
- 7:59:00transform make sure it's on 0 0 0 okay
- 7:59:02great now let's add an audio Source
- 7:59:05component and for the auto clip let's
- 7:59:07use the pan Sizzle let's make sure to
- 7:59:10not toggle play on awake but we do want
- 7:59:12it to Loop and let's also make it a 3D
- 7:59:16sound okay so that's a basic setup Now
- 7:59:19to control this let's make a script so
- 7:59:22let's go into our scripts folder and
- 7:59:24let's create a brand new C script called
- 7:59:27the stove counter
- 7:59:29sound let's attach the script over here
- 7:59:32and let's open it so now here first
- 7:59:34let's grab the audio Source component so
- 7:59:36we've got a private audio source for the
- 7:59:39audio source and just go on awake and
- 7:59:42audio Source equals get component of
- 7:59:44type audio Source okay then we're also
- 7:59:47going to need a reference to the stove
- 7:59:49counter so let's add up here eiz field
- 7:59:52private of type stove counter for the
- 7:59:55stove counter then back in the editor
- 7:59:58let's drag that reference all right now
- 8:00:01in the stove counter over here we
- 8:00:02already have the states and we have the
- 8:00:04on state change event again the same one
- 8:00:06that we use to modify the visual so on
- 8:00:08the sound let's do pretty much exactly
- 8:00:10the same thing over here let's do a
- 8:00:12private void start and on start let's go
- 8:00:15into the stove counter and listen to the
- 8:00:17on state Chang
- 8:00:18event and basically when this changes we
- 8:00:21want to check if it's frying or fried if
- 8:00:24so then we want to play the sound if no
- 8:00:25then we don't want to play it so let's
- 8:00:27find a b call it play sound and we're
- 8:00:29going to play if the state equals we are
- 8:00:33fry or the state equals that it is
- 8:00:37currently fried and about to burn Okay
- 8:00:39then if we have a play sound then let's
- 8:00:42go into the audio source and call
- 8:00:46play and if not then let's go into audio
- 8:00:49source and call
- 8:00:51pause all right so that's it pretty
- 8:00:53simple let's just make sure to save our
- 8:00:55prefab go back outside and let's set on
- 8:00:57play and okay four stars there's no
- 8:00:59sound playing now if I pick up some meat
- 8:01:01and I drop it on there and if there we
- 8:01:03go there's the sizzling sound and
- 8:01:05continues going and now it is still
- 8:01:07sizzling but if it burns it should stop
- 8:01:09so if I go and if there you go the
- 8:01:11sizzling sound sto all right awesome so
- 8:01:14let's take this one out let's actually
- 8:01:15trash it now let's pick up another one
- 8:01:17let it cook and once it's cooked pick it
- 8:01:20up and there you go the sound does stop
- 8:01:22all right awesome so we just have one
- 8:01:25more final sound remaining that's the
- 8:01:27footsteps
- 8:01:28by the way the warning sound this is
- 8:01:29going to be added during the Polish
- 8:01:31lecture for the footsteps we want very
- 8:01:34much the same thing that we did on the
- 8:01:35stove so we're going to want a script to
- 8:01:38handle that logic but this time we don't
- 8:01:40need an audio Source on the player we're
- 8:01:42going to use the same play Method as the
- 8:01:43other ones let's just make a script to
- 8:01:46run the sounds so let's make a new C
- 8:01:48script for the player sounds let's go
- 8:01:51into the player game object and attach
- 8:01:54the sound okay so now here let's first
- 8:01:56grab the player reference
- 8:01:58so private player player and on private
- 8:02:01void awake let's get component of type
- 8:02:04player and assign it to the player okay
- 8:02:08then for the footsteps basically we want
- 8:02:09to play them every certain amount of
- 8:02:11time so let's do up here a private float
- 8:02:14for the footstep timer another one for
- 8:02:16the footstep timer Max and let's say we
- 8:02:18want to play say 10 times per second
- 8:02:21then we do a basic update and on update
- 8:02:24footstep timer countdown by time. time
- 8:02:27and and if the footstep timer is under
- 8:02:30zero then let's reset it so set it to
- 8:02:32the maximum and it's in here that we're
- 8:02:35going to play the sound so now here we
- 8:02:37have two options we can fire an event
- 8:02:40here and we can listen to it on The
- 8:02:41Sound Manager so exactly the same thing
- 8:02:43that we've been doing previously or we
- 8:02:46can just trigger the sound directly from
- 8:02:47here doing that will mean that this
- 8:02:50class is tightly coupled with The Sound
- 8:02:52Manager usually we want to avoid tight
- 8:02:54couplings however in this case the
- 8:02:56player sounds class this one is really
- 8:02:57only meant to exist alongside the sound
- 8:02:59manager so in this case it's perfectly
- 8:03:01fine to title couple them so let's play
- 8:03:04the sound directly from here which means
- 8:03:05we need a reference to The Sound Manager
- 8:03:07we could make a serialized field or just
- 8:03:09make this a Singleton so let's do that
- 8:03:12so a public static type sound
- 8:03:15manager name it instance with a public
- 8:03:18get and a private
- 8:03:20set then on private void
- 8:03:24awake we just set the instance equals
- 8:03:26this okay so then over here we can just
- 8:03:29access it so just go into the sound
- 8:03:31manager access the instance and we call
- 8:03:33play
- 8:03:34sound which we actually need to make
- 8:03:37public however this function also takes
- 8:03:39a reference to the audio clip array so
- 8:03:42that means we need a reference to the
- 8:03:43audio clips so again we have multiple
- 8:03:45options we could add over here on the
- 8:03:48player sounds add a serialized field for
- 8:03:50the footstep sounds or we can just make
- 8:03:52a specialized function over here on The
- 8:03:54Sound Manager both options can work just
- 8:03:56fine let's go with the second one just
- 8:03:58to be different so just make here a
- 8:04:00public void play footstep
- 8:04:04sound we're just going to receive a
- 8:04:06vector three for the position and then
- 8:04:09we just call play sound let's go into
- 8:04:12the audio clip
- 8:04:13refo and let's pick up the footsteps and
- 8:04:17play it on this position and let's also
- 8:04:19receive the volume just appear a FL for
- 8:04:22the volume okay so that's great now we
- 8:04:24just need to call this function so over
- 8:04:26here on the player instead of calling
- 8:04:28play sound let's call the other one play
- 8:04:30the footstep sound then for the position
- 8:04:32that's see player transform. position
- 8:04:35and for the volume I just exposed the
- 8:04:36volume just in case you want to make the
- 8:04:38footsteps a bit more sent or not but for
- 8:04:41now let's begin with 1 F and then see if
- 8:04:42that's way too loud as usual instead of
- 8:04:45using magic numbers let's define a float
- 8:04:47for the volume put it at 1f and over
- 8:04:50here use the volume okay great however
- 8:04:52you might be noticing an obvious issue
- 8:04:54here right now this is going to play
- 8:04:56non-stop obviously we don't want to do
- 8:04:58that we only want to play footstep
- 8:04:59sounds if the player is actually moving
- 8:05:01so this pretty simple we just need to
- 8:05:03ask the player if it is moving and we
- 8:05:06already did that so player is walking so
- 8:05:09if the player is walking then we play
- 8:05:10The Sounds if not we don't okay that's
- 8:05:12it so let's test so here we are and if
- 8:05:15I'm standing still there's no footsteps
- 8:05:17okay that's great and as soon as I move
- 8:05:19yep there you go we got some nice
- 8:05:20footstep sounds all right great so with
- 8:05:23all of that we added all of our sounds
- 8:05:26now here note how we mostly use this
- 8:05:28method of going into the audio source
- 8:05:29and using the play clip at Point
- 8:05:31function this one is great because it is
- 8:05:33so simple but it does have limitations
- 8:05:35specifically with regards to all the
- 8:05:37options if we look on the audio Source
- 8:05:39component here we have all these options
- 8:05:42so you can use an output use an audio
- 8:05:44mixer like we saw in the previous
- 8:05:45lecture we can play around priority play
- 8:05:48around the pitch make it 2D or 3D play
- 8:05:50around over here with how the sound
- 8:05:51falls off so tons and tons of options
- 8:05:54that you can't really access if you use
- 8:05:55that simple function so when approach if
- 8:05:58you need these options you could make
- 8:06:00each sound a prefab so make a prefab for
- 8:06:02each different audio clip and then
- 8:06:04instead of calling that function you
- 8:06:05would simply ineni that prefab to spawn
- 8:06:07that audio so you've got lots of options
- 8:06:09depending on how complex you want your
- 8:06:11sound to be but for a simple game and
- 8:06:13for simple sounds this one line of code
- 8:06:16is super simple all right so here we
- 8:06:18have added sound effects to our game
- 8:06:20that coupled with the music that we add
- 8:06:22previously already makes everything
- 8:06:23sound so much more Al it's really
- 8:06:25starting to look like a proper game
- 8:06:28the one thing we still don't have is
- 8:06:30some kind of game start and game end
- 8:06:31scenario so let's add that in the next
- 8:06:36lecture hello and welcome I'm your Cod
- 8:06:38monkey in this lecture let's add a
- 8:06:40simple beginning state to our game so
- 8:06:43right now we can play the game all of
- 8:06:45the mechanics everything works perfectly
- 8:06:47it's all been implemented however in the
- 8:06:49beginning of the game it just starts
- 8:06:50right away as it loads there's no start
- 8:06:52no countdown no time for the player to
- 8:06:54get ready so let's sort that out with a
- 8:06:56simple countdown
- 8:06:58let's begin by making a general game
- 8:06:59manager script to handle all of our
- 8:07:01general game States so let's create a
- 8:07:03brand new C script and now here you
- 8:07:06could use the name game manager so you
- 8:07:09could use this name however for some
- 8:07:11reason Unity un likes to add this custom
- 8:07:13icon when a script is named exactly game
- 8:07:15manager personally I don't like this I
- 8:07:17don't want it to be a different icon I
- 8:07:20want this script to look and behave just
- 8:07:21like any other one of my scripts so
- 8:07:23personally I don't like this but if it
- 8:07:25doesn't bother you then go ahead use it
- 8:07:26doesn't really change anything just a
- 8:07:28visual but in my case I prefer to give
- 8:07:30it a different name so sometimes I call
- 8:07:32it game Handler or other times just
- 8:07:34something related to this game like for
- 8:07:35example the kitchen game manager and
- 8:07:38just like that it won't have that custom
- 8:07:39icon just need to go inside and rename
- 8:07:42this to Kitchen game manager okay save
- 8:07:44the script and all right now let's make
- 8:07:46a game object to run it so a new game
- 8:07:48object with the same name let's attach a
- 8:07:50kitchen game manager and reset transform
- 8:07:52okay let's open now here we're going to
- 8:07:54Define all the various game states that
- 8:07:56our game can be in so for that let's
- 8:07:58define an enum so a simple enum call it
- 8:08:01State and for the various States let's
- 8:08:04say we are first of all waiting to start
- 8:08:07then we are on countdown to start then
- 8:08:10the game is playing and then we have a
- 8:08:13game over okay so these are our states
- 8:08:16let's do a private void awake and on
- 8:08:18awake let's set the state so we need to
- 8:08:20store a state for our state and on awake
- 8:08:23we set the state equals and let's begin
- 8:08:26on waiting to start by by the way the
- 8:08:27point with this waiting to start state
- 8:08:29will also be very important in the next
- 8:08:31video covering multiplayer basically
- 8:08:33we're going to wait until everyone is
- 8:08:34connected before we start the actual
- 8:08:36countdown but over here for now we're
- 8:08:38just going to wait a little bit on the
- 8:08:39waiting to start then we're going to
- 8:08:41trigger the countdown and then after
- 8:08:42some time trigger the game playing state
- 8:08:44so pretty much all of these states are
- 8:08:45going to be time based so let's make a
- 8:08:48simple timer so a private float for the
- 8:08:51waiting to start timer let's begin on
- 8:08:54something like 1f so we just wait for 1
- 8:08:57second then let's make a private void
- 8:08:59update and let's make a state machine
- 8:09:01just like we've done previously so do a
- 8:09:03switch on our
- 8:09:05state in case we are on state. waiting
- 8:09:08to start if so then let's go into the
- 8:09:11waiting to start timer count it down by
- 8:09:13time. Delta time then if the waiting to
- 8:09:16start timer if it is under zero if so
- 8:09:19then let's move into the state equal
- 8:09:21state DOT let's go into the countdown to
- 8:09:23start okay so that's it and the other
- 8:09:25states are going to be pretty much
- 8:09:26exactly the same so let's just copy this
- 8:09:28so we have the winning to start then the
- 8:09:29countdown to start then we have the game
- 8:09:32playing and finally we have the game
- 8:09:34over and that one doesn't have anything
- 8:09:36so just like this like I said we could
- 8:09:38reuse the same timer but let's write our
- 8:09:40code nice and proper so let's make
- 8:09:42different timers for each so let's make
- 8:09:44three timers so we're going to have the
- 8:09:47countdown to start timer so countdown
- 8:09:50for this one let's see found two three
- 8:09:52so we're going to wait 3 seconds before
- 8:09:54we start and then the game playing timer
- 8:09:57and for this one let's put it something
- 8:09:58short just for testing so let's put it
- 8:10:00just test and then down here let's just
- 8:10:02use them so on the countdown let's
- 8:10:04countdown this timer on the game playing
- 8:10:06countdown this timer when the countdown
- 8:10:08ends we go into game playing and when
- 8:10:10the game playing ends we go into game
- 8:10:12over all right so that's our super basic
- 8:10:14state machine just a bunch of timers
- 8:10:16super simple let's do a quick log just
- 8:10:19to see so over here just a debug.log and
- 8:10:21let's just print out the current state
- 8:10:24okay so just like this let's test and
- 8:10:26yep right away we are waiting to start
- 8:10:28after 1 second going to countdown then
- 8:10:30after 3 seconds going to game playing
- 8:10:32and now if we wait for 10 seconds after
- 8:10:3510 seconds we should be able to see just
- 8:10:38a little bit and yep there you go we've
- 8:10:39got our game over okay great all the
- 8:10:41logic is working although we actually
- 8:10:43didn't change anything technically the
- 8:10:45game right now is on a game over but
- 8:10:46everything still works the same as
- 8:10:47previously so I can still play I can
- 8:10:49still do everything so let's sort that
- 8:10:52when we are in any state other than the
- 8:10:54game playing State we don't want the
- 8:10:56player to be able to interact with
- 8:10:57anything we want to leave it movement
- 8:10:59cuz that's usually nice and fun but we
- 8:11:01don't want it to be able to interact
- 8:11:03pick up objects or do anything so let's
- 8:11:04do that basically over here on the game
- 8:11:07manager let's just expose a function so
- 8:11:09public bow let's call this is game play
- 8:11:12Then over here pretty simple just return
- 8:11:14if the state equals state. gameplay
- 8:11:17that's it so now we can go into the
- 8:11:19player script so over here on the player
- 8:11:22script let's go down into the
- 8:11:24interaction function so over here we've
- 8:11:26got the interact alternate and the
- 8:11:27interact and on both of these basically
- 8:11:30let's just ask if the game is in the
- 8:11:32game playing state if so we want to
- 8:11:34interact but if not then we don't want
- 8:11:35to do anything so to access the game
- 8:11:37manager we could add a pi calized field
- 8:11:39or as usual let's just make a nice
- 8:11:41Singleton so Pi public static of type
- 8:11:43kitchen game manager the instance make a
- 8:11:46public get and a private
- 8:11:48set then down here on awake let's set
- 8:11:51the instance equals this okay so now for
- 8:11:54here on the player let's just go into
- 8:11:55the kitchen game manager access the in
- 8:11:57and test is game playing and we're going
- 8:12:00to do an if if the game is not playing
- 8:12:02so if we are not playing we want to stop
- 8:12:04this so let's just do a return so if the
- 8:12:06game is not playing the code is going to
- 8:12:07stop executing here and same thing on
- 8:12:09the interaction so just like that we
- 8:12:11won't be able to interact with anything
- 8:12:13once we are not in the game playay State
- 8:12:15okay so here we are waiting to start
- 8:12:17nope I cannot pick up anything count on
- 8:12:18to start nope I can't and as soon as we
- 8:12:20go into game playing yep now I can
- 8:12:22interact so I can cut a bunch of things
- 8:12:24and as soon as it goes into game
- 8:12:26overstate
- 8:12:28there you go currently in game overstate
- 8:12:29so now if I try to interact nope can't
- 8:12:31do it okay awesome everything works
- 8:12:34perfectly so in terms of logic this is
- 8:12:36really it there's nothing else we need
- 8:12:38to do but of course right now the player
- 8:12:40would have no clue as to why sometimes
- 8:12:42they can grab and sometimes they can't
- 8:12:44so let's add a proper visual first let's
- 8:12:46add a visual to the starting countdown
- 8:12:49so let's do that as a canvas element so
- 8:12:51let's go inside our canvas create an
- 8:12:52empty game object name this the game
- 8:12:55start countdown you want
- 8:12:58let's press F to focus on the object
- 8:13:00press two to turn this into 2D okay so
- 8:13:02let's see now over here we really just
- 8:13:04need a text object so let's leave this
- 8:13:06one anchored on the center let's put the
- 8:13:07width and height both on zero we don't
- 8:13:09need that and then let's go inside
- 8:13:11create a new text object call this the
- 8:13:13countdown text and then inside let's
- 8:13:15just put a number so just a three let's
- 8:13:18put the width and height both on zero
- 8:13:20then down here let's put it in bold on a
- 8:13:22really big font size so let's say some
- 8:13:24like 250 okay really nice big number
- 8:13:27then let's also put it centered and down
- 8:13:29the middle okay that's great we've got
- 8:13:31our nice big countdown number also by
- 8:13:33the way when using text M Pro we can
- 8:13:35easily add a whole bunch of effects if
- 8:13:37we look down here we have the default
- 8:13:39text mesh Pro material and over here we
- 8:13:41can add an outline underlay and so on so
- 8:13:43that's really great however there's one
- 8:13:46very very crucial thing when you want to
- 8:13:48add some effects always remember that
- 8:13:50the effects are being apply to the
- 8:13:51material meaning any text objects that
- 8:13:53are sharing this material all of them
- 8:13:55will modify so for the most most part
- 8:13:57usually you don't want to modify the
- 8:13:59default material if you do then
- 8:14:01everything using this default material
- 8:14:02will change like for example I want to
- 8:14:04add a nice thick outline to this one but
- 8:14:07over here I've got some regular text
- 8:14:09that is also using the default material
- 8:14:11so if I now add an outline and I
- 8:14:13increase the thickness and there you go
- 8:14:14those also got an outline as well as
- 8:14:16this and if I want to downlo and make it
- 8:14:18quite a lot bigger there you go all of
- 8:14:20them modify because all of them are
- 8:14:22sharing the same material so usually you
- 8:14:24don't want to modify the default
- 8:14:26material if you want to add some kind of
- 8:14:28special effects always make sure to
- 8:14:30create a brand new material beforehand
- 8:14:32so over here let's remove the outline P
- 8:14:34back on the dilation and let's go up
- 8:14:37here to create the brand new material
- 8:14:38first we need to find our font so over
- 8:14:39here on the font asset we can just click
- 8:14:41on it and we can see it over here
- 8:14:42highlighted on the project window so
- 8:14:45it's inside the textmesh pro folder the
- 8:14:46resources fonts and so on so here is the
- 8:14:48default font and inside this one is the
- 8:14:50font that we're using now this font
- 8:14:52there's a nice little arrow icon and
- 8:14:54inside we can see the default material
- 8:14:56so let's duplicate this material
- 8:14:58although it's important make sure you
- 8:14:59duplicate the material and not the font
- 8:15:01so with this material selected I'm going
- 8:15:03to press contrl D and there you go it
- 8:15:04duplicates the material and over here
- 8:15:06let's give it some name so let's say
- 8:15:09this is the material that I want to use
- 8:15:10for the start countdown so there we go
- 8:15:12just like this also one very very
- 8:15:15important thing the name of the material
- 8:15:17needs to include the font name otherwise
- 8:15:19it won't show up for example if I get
- 8:15:21rid of this The Liberation Sans SDF if I
- 8:15:23name the material just like this and now
- 8:15:25I look over here on the countdown text
- 8:15:27look on text mesh Pro here is the drop-
- 8:15:29down menu for selecting material and
- 8:15:31over here note how that one does not
- 8:15:33show up so it is extremely important in
- 8:15:35order for it to show up in here it needs
- 8:15:37to have the same staring name so over
- 8:15:39here if I rename this material put
- 8:15:41Liberation SS SF and then the name and
- 8:15:43now back in here now look and yep now I
- 8:15:45do see my material okay so that's great
- 8:15:48and now over here we can add what kind
- 8:15:50of effects we want and it will only
- 8:15:52affect this one and not any others okay
- 8:15:54so for this one let's add a nice outline
- 8:15:56and let's make make some nice thick
- 8:15:57numbers so over here on dilation let's
- 8:15:59diate by quite a little bit then for the
- 8:16:02outline color let's put it maybe on a
- 8:16:04blue something a bit like this okay
- 8:16:07let's push it back just a little bit
- 8:16:09okay I think that looks pretty good now
- 8:16:11if you want you could add even more
- 8:16:13effects to this I made another video
- 8:16:15covering how to use custom Textures in
- 8:16:17your font doing that you can just import
- 8:16:20the font directly into Photoshop and
- 8:16:21edit it with all kinds of effects for
- 8:16:23example that method is exactly what I
- 8:16:25use in my game hyperight to make the
- 8:16:27head counter look really nice I also
- 8:16:29have a tutorial specifically on that so
- 8:16:31if you want even more custom text
- 8:16:32definitely go ahead and watch those
- 8:16:33videos but anyways here we have our
- 8:16:35countdown text looking pretty nice now
- 8:16:37the number itself will be written
- 8:16:39through code so let's do that let's go
- 8:16:41into our scripts into our UI folder
- 8:16:42create a brand new C script for the game
- 8:16:45start countdown UI okay let's select the
- 8:16:48parent object and attach the script now
- 8:16:51here first thing we need is a reference
- 8:16:53to that text object so let's add a
- 8:16:55serialized field private and again
- 8:16:57remember what I mentioned a couple of
- 8:16:59lectures ago with regards to the types
- 8:17:01so we want text mesh Pro Yugi we want
- 8:17:03this one so it's going to be our
- 8:17:05countdown text and now for updating this
- 8:17:08text basically we just need to know the
- 8:17:10game state so we need to know when the
- 8:17:12countdown should show up and as usual
- 8:17:14let's use some nice events so over here
- 8:17:16on the kitchen game manager let's fire
- 8:17:18an event whenever the state changes so a
- 8:17:21public event event
- 8:17:24handler let's call it on State
- 8:17:27changed okay just like this no need for
- 8:17:30the arguments so let's go down here
- 8:17:32whenever the state changes let's just
- 8:17:33invoke this event so invoke this tars
- 8:17:37empty so we change in there change in
- 8:17:40there and change down there okay that's
- 8:17:42it so now over here on the game start
- 8:17:43countdown let's do a private void start
- 8:17:45and on start let's go into the kitchen
- 8:17:47game manager access the instance listen
- 8:17:49into the onate Chang event as usual
- 8:17:52write some nice clean codes let's rename
- 8:17:53this to the kitchen game manager so when
- 8:17:56the state changes we basically want to
- 8:17:58show this if we are on the countdown to
- 8:18:00start so let's go here to the kitchen
- 8:18:02game manager and let's make another
- 8:18:04function so public bow is countdown to
- 8:18:08start
- 8:18:11active and we just return if the
- 8:18:15state equals the state. countdown to
- 8:18:18start okay so that's a nice symol
- 8:18:20function and on the U script if the
- 8:18:22kitchen game
- 8:18:24manager if this one do is countown to
- 8:18:27start
- 8:18:28active if so then let's show if not then
- 8:18:31let's hide so else let's do a hide so
- 8:18:35let's make these functions so private
- 8:18:37void
- 8:18:38show and a private void hide and on this
- 8:18:41let's just do the usual thing so game
- 8:18:43object set active into true or over here
- 8:18:46set it into false and on start right
- 8:18:48after we subscribe to the event let's
- 8:18:50also hide it by default okay so that's
- 8:18:52the basic logic for showing or hiding it
- 8:18:54and now for the timer text technically
- 8:18:57over here once inside the countdown to
- 8:18:59start we could fire an event on every
- 8:19:01single update that would work but it
- 8:19:03would have some unnecessary overhead so
- 8:19:06instead another option is just make a
- 8:19:07function to expose it so let's go here
- 8:19:10make a public return a float get the
- 8:19:12countown to start
- 8:19:14timer and we just return the countdown
- 8:19:17to start timer very simple so then over
- 8:19:19here on the UI script we can just make a
- 8:19:22regular private void update and on
- 8:19:24update go into the countdown text in to
- 8:19:26set the text and let's go into the
- 8:19:29katchen game manager and let's get the
- 8:19:31countdown to start timer and just do
- 8:19:34ait2 string okay so that's it super
- 8:19:36simple so on update we're going to
- 8:19:38constantly update the timer so let's see
- 8:19:39if this works back here in the editor
- 8:19:42let's just make sure to drag the
- 8:19:43countdown text reference and let's set
- 8:19:44on play and okay waiting to start and
- 8:19:47after a bit yep there you go there's the
- 8:19:48number it's currently on countdown and
- 8:19:50now the game is playing so to showing
- 8:19:52High it did work although the numbers
- 8:19:53seemed quite a bit odd that's because
- 8:19:55over here on the we have wrapping enabl
- 8:19:57so let's just quickly disable this and
- 8:19:59let's test again so there we are waiting
- 8:20:02to start and there you go there's our
- 8:20:03countdown 3 2 1 zero and there you go
- 8:20:05game play okay so it did work now of
- 8:20:09course as it comes to the Visions it
- 8:20:10depends on what you want for example if
- 8:20:13you want to limit the decimals you can
- 8:20:15use over here the two string this one
- 8:20:17can include all kinds of string formats
- 8:20:20for example for displaying just two
- 8:20:21decimal places you can add the string
- 8:20:23format
- 8:20:24F2 let's see what this looks like
- 8:20:27waiting for the countdown and there you
- 8:20:28go now it does Show with two decimals
- 8:20:30okay so this is one approach
- 8:20:32alternatively another format you can use
- 8:20:34is number sign Point number number and
- 8:20:38let's see this
- 8:20:39one and yep there you go now it looks
- 8:20:42like this so as you can see there's lots
- 8:20:44of things you can play around with when
- 8:20:46it comes to the two string formats but
- 8:20:48in our case I don't really want any
- 8:20:50decimals I really just want to see whole
- 8:20:51numbers so for that let's just seal out
- 8:20:54this number so a methf do seal
- 8:20:57let's seal this one out and then just do
- 8:20:59a two string okay let's see so wait a
- 8:21:03bit and we got three two and one and
- 8:21:06there you go the game is playing all
- 8:21:08right awesome so here we have our
- 8:21:10waiting to start and the countdown to
- 8:21:12start all of that logic is working
- 8:21:14perfectly now the next thing we need is
- 8:21:16to handle the game end so let's do that
- 8:21:18in the next
- 8:21:20lecture hello and welcome I'm your code
- 8:21:22monkey in this lecture we're going to
- 8:21:24handle the game over State now for the
- 8:21:26game over State this is obviously a game
- 8:21:28design question for example you could
- 8:21:30make it so that each recipe had a timer
- 8:21:32attached to it and the player had to
- 8:21:33create that recipe within the time limit
- 8:21:36then if they failed enough recipes you
- 8:21:37could trigger some kind of game over or
- 8:21:39for something more simple let's just do
- 8:21:41exactly what we did for the game start
- 8:21:43let's just do a basic countdown timer
- 8:21:46after the game is over let's pop up a
- 8:21:48game over window and show how many
- 8:21:50recipes a player delivered so let's do
- 8:21:51that let's go into our canvas and inside
- 8:21:54make an empty game object call it the
- 8:21:56game over UI then over here let's
- 8:21:59stretch it to occupy the entire parent
- 8:22:01like this now inside let's begin by
- 8:22:04making a UI image this is going to be
- 8:22:06the background let's put it in black
- 8:22:09with just a little bit of transparency
- 8:22:11and let's also stretches to occupy the
- 8:22:13entire thing so just like this then
- 8:22:16let's make some text so let's make a new
- 8:22:18UI text call it the game over text and
- 8:22:22let's say just game over let's set the
- 8:22:25width and height both at zero then down
- 8:22:27here disable wrapping put it centered
- 8:22:31let's put it pretty big so maybe 135 put
- 8:22:34it a little bit higher then for some
- 8:22:36more text let's duplicate this let's
- 8:22:39call this the label recipes delivered
- 8:22:42text and over here we just say
- 8:22:45recipes
- 8:22:47delivered let's put this one a bit lower
- 8:22:49and quite a bit smaller say on 50 okay
- 8:22:53and also on this one let's put it in Bal
- 8:22:55then change the color a little bit okay
- 8:22:58next let's make yet another text this
- 8:23:00one is going to be for the final number
- 8:23:02so let's call this recipes deliver text
- 8:23:06and this one is just going to have
- 8:23:07whatever number of recipes we delivered
- 8:23:09and let's put it over here and quite a
- 8:23:10bit bigger okay so this is the game over
- 8:23:13window that we want also quick note like
- 8:23:15I mentioned previously the Sorting order
- 8:23:17over here on the UI is based on the
- 8:23:19ordering the hierarchy so for the game
- 8:23:21over we want this one to show up on top
- 8:23:23of everything else so make sure the game
- 8:23:25over is the last one over here on the UI
- 8:23:27make sure it is the bottommost child on
- 8:23:29the canvas okay now let's make a game
- 8:23:32object to run this so let's create a
- 8:23:34brand new script game over UI let's go
- 8:23:37into the object wait for the compilation
- 8:23:40and let's drag the script okay now here
- 8:23:42the only reference that we need is just
- 8:23:44for the text so let's just make a
- 8:23:45serialized field of type text mesh Pro
- 8:23:48UI for the recipes deliver text here in
- 8:23:52the editor let's just drag that
- 8:23:54reference okay now let's make some show
- 8:23:56and height functions and also show it
- 8:23:59just on the game over so really we're
- 8:24:00going to do the exact same thing that we
- 8:24:02did over here on the game start
- 8:24:03countdown so let's actually copy exactly
- 8:24:06this let's go into game over UI pass the
- 8:24:08exact same thing Okay so we've got the
- 8:24:10show and height functions we test and
- 8:24:12then over here on the state change
- 8:24:14instead of showing this one on the
- 8:24:15countdown we want to show it on the game
- 8:24:17over so let's go over here and just make
- 8:24:19another function so public bowl is game
- 8:24:22over and we just return if the state
- 8:24:26equals the state. game over okay that's
- 8:24:28the function so over here if we are is
- 8:24:31State game
- 8:24:33over if so then we show if not we hide
- 8:24:36okay the last thing we need is just for
- 8:24:37the text so this is going to be the
- 8:24:39recipes delivered text so we're going to
- 8:24:41set this to something which really means
- 8:24:44that we just need to keep track of all
- 8:24:46the recipes that have been delivered so
- 8:24:48let's go here onto the delivery manager
- 8:24:50script and let's just keep track so just
- 8:24:52a simple in so a private end for the
- 8:24:54successful recipe
- 8:24:57amount and then whenever we have a
- 8:25:00recipe success so let's go here into our
- 8:25:01delivery recipe function whenever we
- 8:25:04have a success let's just increase this
- 8:25:05by one okay so that's it now we just
- 8:25:08need a function to expose this so we pin
- 8:25:11for the get the successful recipes
- 8:25:13amount and just return the successful
- 8:25:15recipes amount okay so finally back here
- 8:25:18on the game over UI let's just printed
- 8:25:20so go into delivery manager access the
- 8:25:22static instance and get the successful
- 8:25:25recipes amount and and of course we need
- 8:25:27the string so two string except for this
- 8:25:29one this is never going to change after
- 8:25:30the game is already over so let's not do
- 8:25:32this on update that would be quite
- 8:25:34wasteful so let's just do it up here so
- 8:25:36as soon as we have the game over we show
- 8:25:38we print the recipes and that's it okay
- 8:25:41so let's test so here we are waiting for
- 8:25:43the timer and let's wait and just wait 5
- 8:25:47seconds for it to finish and we should
- 8:25:49see a zero so let's just make sure that
- 8:25:51works so after a little bit of time yep
- 8:25:54there you go we've got breast piece L
- 8:25:55zero okay
- 8:25:57now back here again let's try to deliver
- 8:25:59some recipes now so let's try and make a
- 8:26:00cheeseburger try to deliver that cut
- 8:26:04this one pick up this one pick it up put
- 8:26:07it in there and okay quickly all right
- 8:26:10good and there you go we've got a one
- 8:26:12all right Awesome everything worked
- 8:26:14perfectly let's just add one more final
- 8:26:17element right now we cannot see what is
- 8:26:19the time left in the game so let's add a
- 8:26:21nice lock element so over here on the
- 8:26:24canvas let's make another empty game
- 8:26:25object
- 8:26:26let's name this the game playing clock
- 8:26:30UI and let's also put it behind the game
- 8:26:33over UI so let's put it above on the
- 8:26:34Hier key so that it shows up behind in
- 8:26:36order to be able to see what we're doing
- 8:26:38let's also just hide the game over UI
- 8:26:40but only here on scene view so let's
- 8:26:41click on the I icon okay so here we have
- 8:26:44our window let's just anchor it on the
- 8:26:46upper right corner so let's put it
- 8:26:48somewhere in there then inside let's
- 8:26:51create a new UI image quality background
- 8:26:55for the Sprite
- 8:26:57let's go with the circle Sprite so let's
- 8:26:58click on the I icon to show all the
- 8:27:00default Sprites and let's use the one
- 8:27:02included with the circle so you have
- 8:27:04this one let's also add a nice little
- 8:27:06outline so let's put it on 2 two with
- 8:27:10full Alpha and let's also add a nice
- 8:27:12shadow just nice visual so on five - 5
- 8:27:15like that and for the color let's also
- 8:27:18put it some kind of dark ray okay so
- 8:27:20this is our background now let's
- 8:27:22duplicate this so contrl D and let's
- 8:27:24rename this one the timer image and for
- 8:27:27this one let's give it a different color
- 8:27:29so maybe something like a blue so
- 8:27:31something like this okay and now over
- 8:27:33here on the image type instead of simple
- 8:27:35let's go with fill let's choose radial
- 8:27:37360 okay great and now over here we can
- 8:27:40play around the fil amount and this will
- 8:27:42be our timer then you can set it up
- 8:27:44however you want for me I'm going to
- 8:27:45choose to start from the top so as it
- 8:27:48starts the timer is going to count down
- 8:27:49until the end okay so that's great now
- 8:27:52let's make the script to run this so
- 8:27:54let's create the Brand C script script
- 8:27:56same thing the game playing clock UI and
- 8:27:59over here let's just attach a script so
- 8:28:02now all we need is reference to our
- 8:28:04image so let's make a serialized
- 8:28:07field private image let's make sure to
- 8:28:09use this one the image inside Unity
- 8:28:11engine. UI this is going to be our timer
- 8:28:14image okay like this back here in the
- 8:28:17editor let's drag the reference all
- 8:28:19right now that we have this we need to
- 8:28:21ask the game manager to get the timer
- 8:28:23normalized so let's go over here onto
- 8:28:25the kitchen game manager and let's make
- 8:28:27a function to return just that so a
- 8:28:29public float let's call it get playe
- 8:28:32timer normalized or game playing timer
- 8:28:35actually just to match a
- 8:28:37state so get this one and up here we
- 8:28:40have the playing timer we just need to
- 8:28:42define a maximum in order to be able to
- 8:28:44calculate the normalized value so let's
- 8:28:46duplicate this call it the game timer
- 8:28:48Max and set this one to 10 and this one
- 8:28:51leave it like this and down here when we
- 8:28:53change the timer when we go into game
- 8:28:55play let's set this one equals this. Max
- 8:28:58that way we only Define the timer just
- 8:29:00up here okay so with that now down here
- 8:29:02we can do the compilation so we can
- 8:29:04return the game playing timer divide by
- 8:29:07the game playing timer Max except just
- 8:29:09like this going to be inverted because
- 8:29:11for the game playing timer we're
- 8:29:13counting down instead of counting up so
- 8:29:15all we need to do is very simple just
- 8:29:17reverse this so just one minus just like
- 8:29:19this okay great so we have this function
- 8:29:22and then over here on the clock just go
- 8:29:24private void update and on update let's
- 8:29:26go into the kitchen game manager the
- 8:29:28instance let's get that and we're going
- 8:29:30to use that on the timer image. fill
- 8:29:32amount okay that's it super simple let's
- 8:29:34see okay here we are on the waiting to
- 8:29:37start all right waiting and as soon as
- 8:29:38we start y there you go there's the
- 8:29:40timer going and we can see it constantly
- 8:29:42increasing so it's at the halfway
- 8:29:46point and just a little bit more and
- 8:29:49there you go yep we've got the time over
- 8:29:51and we have our game over all right
- 8:29:54awesome so over here we implemented a
- 8:29:56really nice game over State we have a
- 8:29:59playing timer with an icei element and
- 8:30:01when it ends we get a game over window
- 8:30:03showing a bunch of stats now with this
- 8:30:05working the next task is to have some
- 8:30:07kind of main menu so we can play again
- 8:30:09after the game is done so let's do that
- 8:30:11in the next
- 8:30:13lecture hello and welcome I'm your Cod
- 8:30:15monkey in this lecture we're going to
- 8:30:17make a super simple main menu and the
- 8:30:19loading system okay so every game needs
- 8:30:22a main menu so let's build one let's
- 8:30:24begin by making the scene so let's go
- 8:30:26into our scenes and create a brand new
- 8:30:28scene call this the main menu scene and
- 8:30:31okay here's our default scene now over
- 8:30:33here for the most part you really just
- 8:30:35want some basic buttons so nothing too
- 8:30:36special so let's create a brand new UI
- 8:30:39canvas and let's set up as usual so
- 8:30:41screen space overlay yep then let's go
- 8:30:43with scale with screen size 1920 by
- 8:30:471080 and let's match with the height
- 8:30:49okay so there's our canvas now inside
- 8:30:52let's make an empty gam object name this
- 8:30:54the main menu UI
- 8:30:56let's stretch it to occupy the entire
- 8:30:58thing so 0 0 on everything okay now
- 8:31:01inside let's create a brand new UI
- 8:31:03button let's name this the play button
- 8:31:07then inside for the text let's say play
- 8:31:10Let's size the button to be quite a bit
- 8:31:12bigger so let's say 450 by 150 and on
- 8:31:15the text itself let's put it in bold on
- 8:31:18a font size quite a bit bigger let's say
- 8:31:2070 then let's also change the color
- 8:31:22let's put the text in White and the play
- 8:31:24button over here the normal color for
- 8:31:26the image let's put it on a dark ray
- 8:31:28then also over here on the button
- 8:31:29background let's add a nice outline
- 8:31:32let's put it on full black say something
- 8:31:34like 3 three then let's make a Shadow
- 8:31:37and for this one 5 - 5 okay so that's
- 8:31:40our basic button let's just anchor the
- 8:31:42button so choose the play button let's
- 8:31:44anchor it on the lower left corner and
- 8:31:47let's push it just a bit like this okay
- 8:31:50pretty simple now let's duplicate this
- 8:31:52one push it a bit lower let's also make
- 8:31:54it just a tiny bit smaller so just 120
- 8:31:57this is going to be our quit button so
- 8:31:59let's rename this to the quit button and
- 8:32:01inside for the text just say quit and
- 8:32:04put a bit lower on the font size okay
- 8:32:06like this okay so we have the two basic
- 8:32:09buttons that we need now let's make the
- 8:32:10script random so let's make a script
- 8:32:12with the same name so main menu UI so
- 8:32:14let's go into our script UI folder
- 8:32:16create new script for the main menu UI
- 8:32:20let's attach the script and open okay so
- 8:32:22now here let's begin by making
- 8:32:23serialized fields for our buttons so aiz
- 8:32:26film private of type button inside
- 8:32:28unityengine.ui this is the play button
- 8:32:31and then we have another one for the
- 8:32:33quit button okay back in the editor
- 8:32:35let's drag the references so that's the
- 8:32:37play button and the quit button okay now
- 8:32:39here in the code let's add some
- 8:32:41listeners to these buttons so let's do a
- 8:32:43private void awake and on awake let's go
- 8:32:44into the play button and go into the
- 8:32:46onclick event so the event when the
- 8:32:49player clicks on the button and let's
- 8:32:51add listener and now we pass in The
- 8:32:53Listener now over here to do this we can
- 8:32:55add a function so we can make a private
- 8:32:57void Play Click we can define a function
- 8:33:00kind of like this and over here add it
- 8:33:02as a listener so that's one approach or
- 8:33:04another alternative that personally I
- 8:33:06like to use is to use what is called a
- 8:33:08Lambda expression so instead of defining
- 8:33:10an external function down here we just
- 8:33:12go up here and directly we Define a
- 8:33:14Lambda so we open parameters to display
- 8:33:17the parameters for the function which in
- 8:33:19this case we have none so just open and
- 8:33:20close then we do a nice little arrow and
- 8:33:23then we have whatever we want to be our
- 8:33:25click code so both the code that I have
- 8:33:28here and one that I have here both of
- 8:33:30these are exactly the same thing this
- 8:33:31one is called the lmda expression which
- 8:33:33is also a type of delegate definitely go
- 8:33:36ahead and watch my video on C delegates
- 8:33:38in detail it's yet another extremely
- 8:33:40powerful C feature I find them
- 8:33:42especially useful especially over here
- 8:33:44to setting the click listeners there's
- 8:33:46no need to make another function just
- 8:33:48use a Lambda expression and that's it so
- 8:33:50over here I'm going to use that instead
- 8:33:51of an external function Okay so we've
- 8:33:53got the play and then let's also listen
- 8:33:55to the quit so on the quit button the
- 8:33:57exact same thing okay now first on the
- 8:34:00quit button it's actually very simple we
- 8:34:01just go into application and we call the
- 8:34:04quit function this will quit the game
- 8:34:06that's it very simple although one note
- 8:34:08if we actually test it like this so here
- 8:34:10is game playing and if I click on quit
- 8:34:13and nope nothing happens now the logic
- 8:34:15is actually working we can see visually
- 8:34:17that the button is changing state so we
- 8:34:18are indeed capturing clicks however when
- 8:34:21the game is running inside the editor
- 8:34:22calling that function the application
- 8:34:24now quit doesn't do anything
- 8:34:26but if this were a full build then
- 8:34:27clicking on that would indeed close our
- 8:34:29game okay so now for the play button for
- 8:34:32this one it's also very simple we just
- 8:34:34need to go inside the scene manager
- 8:34:36which is inside Unity engine. scene
- 8:34:38management we just need to go inside of
- 8:34:40this one and we call load scene this
- 8:34:44function will load a certain scene and
- 8:34:46for loading we can either use the scene
- 8:34:48build index or we can use the scene name
- 8:34:50like I've mentioned several times string
- 8:34:52names are horrible although in this case
- 8:34:54the alternative using an INT is also not
- 8:34:56very good just the number is very hard
- 8:34:58to read the code and be able to know
- 8:35:00what scene this is loading so there's
- 8:35:02one better approach that I prefer to use
- 8:35:04but first over here let's just use the
- 8:35:06index just for testing so we're going to
- 8:35:08load the scene on index one so just like
- 8:35:11this and then here in the editor let's
- 8:35:13go into file and build settings and over
- 8:35:16here we see the scenes in our build
- 8:35:18right now we just have the game scene so
- 8:35:20let's just add our scene so let's drag
- 8:35:21the main men scene and drag it on there
- 8:35:23and also let's make sure it's on the top
- 8:35:25of the list basically the first scene is
- 8:35:26the one that will be loaded as soon as
- 8:35:28the game starts so let's drag it right
- 8:35:30up top just like that then over here on
- 8:35:32the right we see the index so by loading
- 8:35:34the scene on index one we're going to be
- 8:35:36loading the game scene okay so with this
- 8:35:38let's test so here we are and if I click
- 8:35:40on play and Y there you go it does load
- 8:35:43the main scene okay great everything is
- 8:35:45working so this is the simest way to do
- 8:35:48scene loading however this method does
- 8:35:50have one issue it's not super noticeable
- 8:35:52on a game of this scale because loads
- 8:35:54pretty quickly but like this note how
- 8:35:57when we click on play there you go
- 8:35:58everything freezes for a little bit
- 8:36:00while the game is loading like I
- 8:36:01mentioned in this case the freeze is so
- 8:36:03small so not necessarily an issue but if
- 8:36:05the game was much more complex then the
- 8:36:06player would be staring at a frozen main
- 8:36:08menu for perhaps 30 seconds that would
- 8:36:10not be good one way to avoid that is
- 8:36:12actually very simple basically it's what
- 8:36:13I already covered in detail in the scene
- 8:36:15loading video that video was made quite
- 8:36:17a while ago but it's still very much up
- 8:36:19to date here we're going to do pretty
- 8:36:20much the same thing so we first create
- 8:36:22the scene just empty just saying loading
- 8:36:25and then from that scene we load the
- 8:36:26final scene that way the game stays
- 8:36:28Frozen on a scene that says loading
- 8:36:30which is much more clear to the player
- 8:36:31so let's do that first let's make our
- 8:36:33scene so inside our scenes folder let's
- 8:36:35create a brand new scene call this the
- 8:36:38loading scene okay let's go inside and
- 8:36:41now in this one we want this one to be
- 8:36:42fully black so let's go into the main
- 8:36:44camera and scroll down over here under
- 8:36:46environment and instead of rendering the
- 8:36:47Skybox for the background let's go with
- 8:36:49a solid color and let's go with full
- 8:36:51black okay there's our black main camera
- 8:36:55now let's make a canvas so a new UI
- 8:36:57canvas let's set it up as usual so scale
- 8:37:00with screen size 1920 by 1080 and match
- 8:37:04with the height okay then inside let's
- 8:37:06just make a simple text object so just
- 8:37:08say text then over here let's say just
- 8:37:12loading let's put the text width and
- 8:37:14height on zero put it on Bold let's make
- 8:37:17sure to disable
- 8:37:19wrapping and push it over there on the
- 8:37:21side and maybe increase the font size by
- 8:37:23a little bit okay there you go we have
- 8:37:25our very basic loading screen now we're
- 8:37:27going to load this scene and then whil
- 8:37:29on this scene we're going to load the
- 8:37:30final scene although also one very
- 8:37:32important thing related to loading
- 8:37:33scenes is you need to remember the
- 8:37:36lifetime of the objects regular game
- 8:37:38objects like for example the ones that
- 8:37:39we see here in the hierarchy these get
- 8:37:41destroyed when you do a scene change so
- 8:37:43for the goal that we're trying to
- 8:37:44achieve we need to load this loading
- 8:37:46scene but then also somehow transfer
- 8:37:49data so that the loading scene here
- 8:37:51knows which one is the final scene now
- 8:37:53you might think that over here on the
- 8:37:54main menu we could create a game object
- 8:37:56attach a script that would hold the
- 8:37:57reference to the final scene but like I
- 8:37:59said game objects get destroyed as soon
- 8:38:01as we load the loading scene so for
- 8:38:03transferring data between scenes we
- 8:38:04can't really use a regular script on a
- 8:38:06regular game object now one approach is
- 8:38:09to use the don't destroy on load this is
- 8:38:11a Unity function that helps you stop a
- 8:38:13particular script or game object from
- 8:38:15being destroyed that way the object
- 8:38:17won't purist through scene changes so
- 8:38:19that's one option but another option
- 8:38:21that I prefer is very simple let's just
- 8:38:23make it loader class so let's create a
- 8:38:26new C script call this loader and over
- 8:38:29here let's go ahead and make this class
- 8:38:31a static class and we are not going to
- 8:38:33extend mod Behavior so just like this
- 8:38:36basically by making it static it means
- 8:38:38that this one is not attached to any
- 8:38:40specific instance of an object this
- 8:38:42class cannot be attached to any object
- 8:38:44and cannot have any instances
- 8:38:45constructed then inside we can add
- 8:38:47static functions in fields like for
- 8:38:49example a static in for the Target scene
- 8:38:52index so now this field we could set
- 8:38:55this field from over here on the main
- 8:38:56menu UI and when we would load we would
- 8:38:59not be resetting this field also here I
- 8:39:01should point out one quick thing you can
- 8:39:04make field static without making the
- 8:39:05entire class itself static making the
- 8:39:08class static is just a good approach if
- 8:39:10the entire thing if everything in this
- 8:39:12class is also meant to be static if you
- 8:39:14don't make it static then you can have
- 8:39:15regular Fields
- 8:39:17here you can have both static and
- 8:39:19non-static whereas if you make this
- 8:39:22static then you're going to have an
- 8:39:24error because you cannot have have
- 8:39:25non-static Fields so this is another
- 8:39:27clean code thing if it's only meant to
- 8:39:29contain static logic then make the class
- 8:39:32itself static okay so we have a static
- 8:39:34field for our Target scene but as usual
- 8:39:37we don't want this to be a public field
- 8:39:39we don't want the main menu to directly
- 8:39:41write to this field so let's make this
- 8:39:43class the only one responsible for
- 8:39:44anything related with scene loading
- 8:39:46soste let's make a function so a public
- 8:39:49static void call it load and for a
- 8:39:52parameter let's receive a string for the
- 8:39:54Target scene name
- 8:39:56then over here we load the actual scene
- 8:39:57so let's go into the scene manager and
- 8:39:59load the
- 8:40:00scene and let's pass in the Target scene
- 8:40:03name okay that's it and then over here
- 8:40:06on the main menu UI instead of directly
- 8:40:08loading a scene let's go into the loader
- 8:40:10and call load and pass in the scene name
- 8:40:12so that's the game
- 8:40:13scene okay so this is what we're going
- 8:40:15to do that's good except it's obviously
- 8:40:18not good over here we're using string
- 8:40:20names that's horrible we should never
- 8:40:22use this so let's avoid using strings as
- 8:40:24much as possible and and one simple way
- 8:40:26is to just Define an inum for all of our
- 8:40:27scenes so let's go here on the loader
- 8:40:30and let's define that so a public inum
- 8:40:33let's call it scene and for all of our
- 8:40:35scenes so we have the main menu scene
- 8:40:38then we have the game scene and the
- 8:40:40loading
- 8:40:41scene okay so then down here on this
- 8:40:44function instead of receiving a string
- 8:40:46we just receive a scene for the Target
- 8:40:48scene and we use the target scene
- 8:40:51although of course un API does not
- 8:40:52support loading our custom enum it has
- 8:40:55to be an index or string so the simple
- 8:40:57approach is just to convert this one
- 8:40:58into a string that's it so the only
- 8:41:00thing you need to make sure is that the
- 8:41:02inum values over here match the actual
- 8:41:04name on the actual scenes perfectly so
- 8:41:07don't make any mistakes keep it case
- 8:41:09sensitive so don't do this make sure
- 8:41:10everything matches perfectly okay so
- 8:41:13just like this everything should already
- 8:41:14be working the same as previously so the
- 8:41:16main menu calls that let's actually just
- 8:41:18use that so let's use scene. game scene
- 8:41:22so on the main menu we do this and on
- 8:41:24loader we load the scene okay let's test
- 8:41:26here is the main menu and if we click
- 8:41:28and wait a bit and Y there you go it
- 8:41:30didn't load the game scene okay great so
- 8:41:32everything still works the same as
- 8:41:33previously except now all of the loading
- 8:41:34logic is inside of this class and over
- 8:41:37here let's Lo a loading scene in the
- 8:41:39middle basically when we have this
- 8:41:41function to load a final scene let's
- 8:41:43first off set this field so this one
- 8:41:44instead of being type in let's make it
- 8:41:46of type scene and this is going to be
- 8:41:48the target scene and let's make it
- 8:41:50private okay so when we have this
- 8:41:53function let's set that field although
- 8:41:55here remember how this is a static class
- 8:41:57so in order to access this field we need
- 8:41:59to access it through the class name
- 8:42:00because over here we also have a local
- 8:42:02variable with the exact same name so
- 8:42:04let's access the loader. target scene
- 8:42:06and set it to the Target scene so again
- 8:42:09don't be confused here you can even use
- 8:42:11Visual studiio and put the cursor on top
- 8:42:13to see what object represents what so
- 8:42:15you can see the loader. target scene is
- 8:42:16referencing this field whereas this one
- 8:42:18over here is referencing the local field
- 8:42:20so we want to assign the member field to
- 8:42:22the one that we received as a parameter
- 8:42:24okay so we store that and then let's
- 8:42:26immediately load the loading scene so
- 8:42:28scene manager let's load the scene and
- 8:42:31we're going to
- 8:42:33load the scene. loading scene. two
- 8:42:36string okay so we're going to load that
- 8:42:38and now here comes the tricky part if we
- 8:42:40do this so if we load the loading scene
- 8:42:43and then immediately load the target
- 8:42:44scene if we do it like this it won't
- 8:42:46actually show the loading scene we're
- 8:42:49calling these functions one right after
- 8:42:50the other so it will load one and
- 8:42:53immediately the other basically we need
- 8:42:54to wait at least one frame to render so
- 8:42:56that the loading scene is visible and
- 8:42:58then we can load the final scene so
- 8:43:00let's make a script to do a very simple
- 8:43:02job let's create a brand new C script
- 8:43:05for the UN loader callback and now let's
- 8:43:08go inside the unloading scene so this is
- 8:43:10important let's make this on the loading
- 8:43:11scene not the main menu or the game
- 8:43:13scene so over here let's create an mty
- 8:43:15game object for the loader call back
- 8:43:17let's reset transform just keep things
- 8:43:19nice and clean and let's attach the
- 8:43:20script so the loaded comb back okay and
- 8:43:23on this script we want to basically just
- 8:43:25wait for the very first update so let's
- 8:43:27say a private ball is first update and
- 8:43:31we start off as true actually so is the
- 8:43:34first update is true then we do a
- 8:43:36private void update so if it is the
- 8:43:38first update if so then let's set is
- 8:43:41first update to
- 8:43:42false and we have the first update
- 8:43:45although technically I should point out
- 8:43:46that we don't really need this we're
- 8:43:48going to load right away so either way
- 8:43:50it will only run One update but still I
- 8:43:52like to add this just to make the logic
- 8:43:54perfectly clear
- 8:43:55basically if it is the first update then
- 8:43:57let's call a function on the loader so
- 8:43:59on the loader over here let's make a
- 8:44:00function public static void call it
- 8:44:03loader
- 8:44:05callback okay we have this function so
- 8:44:07over here on the loader comback let's
- 8:44:08just go into the loader and call the
- 8:44:10loader comback function all right so
- 8:44:13basically now here we have this function
- 8:44:14that is going to be triggered on the
- 8:44:16first update so we know for certain the
- 8:44:18unloading scene has been rendered so
- 8:44:20it's over here that we want to load the
- 8:44:21actual final scene okay that's it here
- 8:44:24we have a super super simple loading
- 8:44:25system just make perfectly sure that the
- 8:44:28loader call back with the script this
- 8:44:29one only exists on loading scene it
- 8:44:31should not be on any of the other ones
- 8:44:33so let's test and for that let's go
- 8:44:35inside the main menu scene okay and now
- 8:44:37let's head on play okay so here we are
- 8:44:39on the main menu now if I click on play
- 8:44:41and actually here's the thing that I
- 8:44:42forgot so make sure you don't forget
- 8:44:44this we need to add the loading scene to
- 8:44:46the builds in order to be able to load
- 8:44:48so let's go up here into the build
- 8:44:50settings let's go into the project drag
- 8:44:51the loading scene like that okay so now
- 8:44:54let's test so here we are on the main
- 8:44:56menu let's head on play and there's the
- 8:44:58loading scene after a bit yep here we
- 8:44:59have our game scene all right awesome so
- 8:45:02with that everything is working
- 8:45:03perfectly all of the logic is working
- 8:45:05great now that it all works great let's
- 8:45:07just make a nice proper visual for our
- 8:45:09main menu so for that let's go inside
- 8:45:12the game scene and over here let's copy
- 8:45:14a few things so let's pick up the floor
- 8:45:16object and let's also pick up the global
- 8:45:19volume with the post pressing so let's
- 8:45:21copy both of these let's go into the
- 8:45:23main menu scene and over here let's
- 8:45:25paste both objects okay now let's also
- 8:45:28drag some player visuals so let's put
- 8:45:30this in 3D go back down to the floor and
- 8:45:33let's pick up some visuals so let's go
- 8:45:34inside our assets on the prefabs visuals
- 8:45:37let's find over here the player visual
- 8:45:40again make sure you drag the visual only
- 8:45:42we don't want any logic components and
- 8:45:44by the way this is yet another great
- 8:45:46benefit of separating the logic from the
- 8:45:47visuals right now it's super simple for
- 8:45:50us to play some players here because we
- 8:45:52have just the visuals completely
- 8:45:53separated from the logic okay so on the
- 8:45:55visual let's just make it look at the
- 8:45:57camera let's position a bunch more
- 8:45:59players so let's duplicate this and put
- 8:46:02one to the side we're going to move the
- 8:46:04camera in a bit but now let's just place
- 8:46:05them and in included assets there are a
- 8:46:08bunch of materials so over here we see
- 8:46:10the player body then we've got a blue a
- 8:46:11green and a red like I said this first
- 8:46:14course is on making this game in single
- 8:46:15player but the goal is to then make a
- 8:46:17second course after this one on
- 8:46:19converting this game into multiplayer so
- 8:46:20that's why I included multiple colors so
- 8:46:23let's just drag these let's let's go
- 8:46:25into this player Visual and on this one
- 8:46:27make it blue so on the head and on the
- 8:46:30body then on this one on the side here
- 8:46:33let's make this one green so green there
- 8:46:35and green on the head and for the one
- 8:46:38behind let's make this one the red one
- 8:46:40so put it in red and in red Okay so
- 8:46:43we've got our nice four players now
- 8:46:45let's also add a camera so we're going
- 8:46:46to have the camera kind of like this
- 8:46:48kind of From Below looking upwards I
- 8:46:50think that looks pretty good for that
- 8:46:52let's use S machine so let's go into
- 8:46:53game object go into cin machine and
- 8:46:56let's create a brand new virtual camera
- 8:46:58okay like this let's just push it up a
- 8:47:00little bit okay so this is our nice
- 8:47:02composition now on the virtual camera
- 8:47:05let's just go ahead and add some noise
- 8:47:06so let's add basic multi channel pein so
- 8:47:09let's do it just like we did when we
- 8:47:10first added C machine so let's use a
- 8:47:12handheld normal mild and now let's just
- 8:47:15play around these fields which by the
- 8:47:16way you can do that while the game is
- 8:47:17playing so let's head on play and over
- 8:47:19here you can play around all the fields
- 8:47:22although actually defaults already look
- 8:47:23pretty good but let's put the free
- 8:47:24frequency maybe a little bit less and
- 8:47:26the amplitude maybe a little bit bigger
- 8:47:29so just some nice little Sway and by the
- 8:47:31way if you make any changes to the C
- 8:47:33Machine virtual camera and if now you
- 8:47:35stop playing it will actually lose those
- 8:47:36changes but over here on the virtual
- 8:47:38camera there's this nice toggle save
- 8:47:40during play so if you tick this and now
- 8:47:42you exit play mode and there you go
- 8:47:45those changes were saved okay great now
- 8:47:46let's just make sure to untick this so
- 8:47:48we don't accidentally modified okay so
- 8:47:50here we have the basic Vision that we
- 8:47:52want finally there's also a game logo in
- 8:47:54the included assets so let's just go
- 8:47:56into our canvas into our main menu let's
- 8:47:58create a brand new UI image let's assign
- 8:48:01the logo Sprite then let's just position
- 8:48:05it on that corner so let's move it all
- 8:48:07the way up there we can anchor it to the
- 8:48:09top left corner and let's make it a bit
- 8:48:11bigger and by the way on something like
- 8:48:13this if you play around this it might
- 8:48:14get a bit stretched so if so over here
- 8:48:17on the options on the image you can tell
- 8:48:18on this one to preserve the aspect ratio
- 8:48:20so that way even if you stretch it won't
- 8:48:22actually be stretch it will always be
- 8:48:23perfect okay just like this okay so here
- 8:48:26we have our basic main menu it's a basic
- 8:48:28setup but it looks pretty good and with
- 8:48:30that we have built a nice main menu
- 8:48:32along side with a loading system so I
- 8:48:34can click on play it goes into the
- 8:48:36loading scene and then into the game
- 8:48:37scene so that's great the next thing
- 8:48:40that we need is some kind of pause
- 8:48:41button so let's do that in the next
- 8:48:43lecture hello and welcome I'm your Cod
- 8:48:46monkey in this lecture we're going to
- 8:48:48add a pause button with a p window that
- 8:48:50also has the ability to quit back to the
- 8:48:52main menu and in doing so we're also
- 8:48:53going to solve some sneaky issues with
- 8:48:55loading okay so here in the main menu we
- 8:48:57can click the play button in order to
- 8:48:59load the game and yep everything works
- 8:49:01now I'm in the game but now let's say I
- 8:49:02want to pause the game for a bit or quit
- 8:49:04back to the main menu right now there's
- 8:49:06no way so let's do that let's go here
- 8:49:08onto the game scene and first let's send
- 8:49:10on the pause and for that we're actually
- 8:49:12going to need some input so let's first
- 8:49:14go inside our player input actions let's
- 8:49:16open this and then over here let's make
- 8:49:18a brand new action let's name it the
- 8:49:21pause for the action TP let's go with
- 8:49:23button okay and for the the bindings
- 8:49:25over here let's go with escape and
- 8:49:27actually if we use the same method that
- 8:49:28we've been using if we listen and press
- 8:49:30on Escape nope doesn't work because
- 8:49:32Escape just cancels it so instead we
- 8:49:34need to use a search bar here Search for
- 8:49:36escape keyboard just like this okay
- 8:49:38great now again as always let's make
- 8:49:40sure to save the asset and wait for the
- 8:49:42compilation to happen there it is so now
- 8:49:45here on the game input class let's
- 8:49:47listen to it and far the event as usual
- 8:49:50so go into the player input actions the
- 8:49:51player action map let's go into the
- 8:49:53pause action and listen to the performed
- 8:49:57event and when this happens let's fire
- 8:49:59off an event so a public event event
- 8:50:03handler let's go on pause
- 8:50:06action and then down here we're simply
- 8:50:08going to invoke this
- 8:50:14event okay just like this now for
- 8:50:17listening to it here's a question where
- 8:50:19does that make more sense should we do
- 8:50:21it over here on the player script or
- 8:50:23perhaps over here on the kitchen game
- 8:50:24game manager I think over here on the
- 8:50:26game manager makes more sense since a
- 8:50:28pause is more related to the game itself
- 8:50:30rather than a specific action by the
- 8:50:31player so let's head it over here let's
- 8:50:34first of all listen to the event so
- 8:50:35let's do a private void start and on
- 8:50:37start let's listen to it so let's go
- 8:50:39into the game input and we didn't
- 8:50:41actually make it a Singleton yet so
- 8:50:42let's do that over here let's make a
- 8:50:44public static game input for the
- 8:50:48instance with a public yet and a private
- 8:50:51set then down here on a wake let's set
- 8:50:54instance equals this okay there's our
- 8:50:56Singleton so now back in the kitchen
- 8:50:57game manager let's go into the instance
- 8:50:59and listen to the on pause action
- 8:51:02event and again let's rename this to
- 8:51:05give it a proper name so this the game
- 8:51:08input on pause action okay so here we
- 8:51:10have it when we have this let's call
- 8:51:12some kind of pause game function so
- 8:51:15let's define this let's go to the end
- 8:51:16the file here and over here let's make
- 8:51:18that function so a private void pause
- 8:51:21game and over here we're going to pause
- 8:51:23the game now for pausing doing this is
- 8:51:25actually surprisingly easy basically all
- 8:51:27of our logic is using time. time for
- 8:51:30example over here on the player script
- 8:51:32we have our movement speed yep then we
- 8:51:34get the inputs and over here on the
- 8:51:36handle movement function yep for the
- 8:51:38movement distance we have move speed
- 8:51:40multiplied by time. time for another use
- 8:51:42case over here on the stove counter
- 8:51:44we've got a frying timer and how we
- 8:51:46count it down again is the same thing
- 8:51:48time. the time well it turns out that
- 8:51:50behind the scenes time. the time
- 8:51:52actually already has a multiplier when
- 8:51:54you you access this it is after that
- 8:51:56multiplier calculation so over here on
- 8:51:58the pause game function we can just go
- 8:51:59into time and we can modify the time
- 8:52:01scale this one is the multiplier so if
- 8:52:04we just put this at Zer F then that's it
- 8:52:06this is going to pause all of the other
- 8:52:08Delta times so let's test so here we are
- 8:52:11pay attention to that and the countdown
- 8:52:12timer and I press on escape and there
- 8:52:14you go everything pauses the countdown
- 8:52:16timer pauses over here the script pauses
- 8:52:18and I can no longer move nothing works
- 8:52:20everything is perfectly paused all right
- 8:52:22Awesome everything works except when one
- 8:52:24problem obviously right now we cannot
- 8:52:26unpause if I press Escape it's not
- 8:52:28unpausing so let's do that over here on
- 8:52:30the kitchen game maner let's add a
- 8:52:32simple ball so a private ball let's call
- 8:52:34it is game paused and let's defold it to
- 8:52:37false okay so is game paused and then
- 8:52:39down here on the pause game function
- 8:52:41let's simply flip this one so we set
- 8:52:43this one equals not this one so that is
- 8:52:44going to flip that buum and then we
- 8:52:46check if the game is paused if so set it
- 8:52:48to zerf and if not then we're going to
- 8:52:51set the time. time scale back into 1 f
- 8:52:55okay so now this should pause and
- 8:52:56unpause so let's actually rename this
- 8:52:58function since this is no longer just
- 8:53:00going to pause let's rename this to
- 8:53:03toggle pause game this going to pause
- 8:53:05and unpause okay so let's test okay so
- 8:53:09here we are everything is running now I
- 8:53:10pause and there you go everything freeze
- 8:53:12I cannot move the arrow is stop the
- 8:53:13countdown is stop now I press again and
- 8:53:15there you go nice and resume all right
- 8:53:18great so all of the logic is working
- 8:53:20perfectly the only thing we need is
- 8:53:21really just see Visual and as usual
- 8:53:23let's separate the logic from the
- 8:53:25visuals so let's go inside the canvas
- 8:53:28let's go into the scene View and inside
- 8:53:30the canvas let's create an empty game
- 8:53:31object call it the game pause UI then
- 8:53:35let's stretch to occupy the entire
- 8:53:37screen so zero on everything okay great
- 8:53:40now inside let's first of all add a
- 8:53:42background so a new image name this the
- 8:53:45background let's once again stretch to
- 8:53:47occupy
- 8:53:48everything and on the color let's put it
- 8:53:51in black with just a little bit of alpha
- 8:53:53okay just like that then let's set some
- 8:53:55text so let's create a brand new UI text
- 8:53:58let's name it pause text and in here
- 8:54:01let's just say paused let's just make it
- 8:54:03big so the width and height both on zero
- 8:54:06let's disable wrapping Put It Center
- 8:54:09down the middle and let's increase the
- 8:54:10font size by quite a bit and put it in
- 8:54:12bold and let's also change the color
- 8:54:15maybe a nice yellow something like this
- 8:54:18okay that looks pretty good let's just
- 8:54:20lift it up by a little bit now let's
- 8:54:22make a script to show this
- 8:54:24so on the UI folder let's create a brand
- 8:54:26new C script call this the game pause UI
- 8:54:30let's attach it and open now here let's
- 8:54:33do the usual thing so let's make two
- 8:54:34show and hide functions so private void
- 8:54:37show and then a private void
- 8:54:39hide so on the show game object set
- 8:54:42active into true and on the hide set it
- 8:54:45into
- 8:54:46false okay that's it pretty simple now
- 8:54:49we need to know when to show our high
- 8:54:50these functions so over here on the
- 8:54:52catch and game manager let's make two
- 8:54:54events to do that so let's go up here
- 8:54:56make a public event event
- 8:54:59handler and let's name this on game
- 8:55:01paused and another one for oname
- 8:55:04unpaused okay we have both events then
- 8:55:08down here on the togg on pause game if
- 8:55:10we have this one time scale zero that
- 8:55:11means we have pause so let's invoke the
- 8:55:13oname pause this event ours. empty okay
- 8:55:16and on this one let's trigger the other
- 8:55:18one so on game
- 8:55:20unpaused okay we've got the two basic
- 8:55:22events now back here on the game pause
- 8:55:25UI let's listen to it and as usual let's
- 8:55:26do it on start so private void start
- 8:55:29let's go into the kitchen game manager
- 8:55:30access the static incense and let's
- 8:55:32listen to the on game paused and then
- 8:55:35going to listen to the other one so the
- 8:55:37instance on game unpaused so listen to
- 8:55:39both of them and as usual let's write
- 8:55:41good clean codes and let's rename this
- 8:55:44so kitchen game manager and on this one
- 8:55:47the same thing so also the kitchen game
- 8:55:50manager okay we have both and when the
- 8:55:53game is unpause then we want to hide the
- 8:55:55pause window and when the game is paused
- 8:55:58then we want to show the pause window
- 8:55:59and finally of course we want to hide it
- 8:56:01by default so over here on start after
- 8:56:03we had listeners let's just hide it okay
- 8:56:06so that's it that should work so let's
- 8:56:07test so here we are everything is
- 8:56:09running now press the pause and there
- 8:56:11you go got a nice paused window press
- 8:56:13again and there you go everything
- 8:56:14resumes okay great so the last thing
- 8:56:17that we want is just a button over here
- 8:56:18to go back to the main menu and let's
- 8:56:20also add a button to resume without
- 8:56:22having to press the hotkey so over here
- 8:56:25let's create a new UI let's make it a
- 8:56:27button this is going to be the main menu
- 8:56:29button now let's make it quite a bit
- 8:56:32bigger okay width and height of 30 and
- 8:56:3480 let's put this one quite a bit down
- 8:56:37there and inside for the text this one
- 8:56:39is the main menu let's put the color in
- 8:56:43White and the background for the button
- 8:56:45let's put this one in a dark ray and
- 8:56:48let's also just for fun add a nice
- 8:56:50outline and let's also add a shadow for
- 8:56:53the outline let's put it on full Alpha
- 8:56:55and let's put it on about 3 three and
- 8:56:58for the effect on the shadow 5 - 5 okay
- 8:57:01so that add a nice outline and nice
- 8:57:02shadow and then for the text itself
- 8:57:05let's put it in bold and raise it by
- 8:57:07just a little bit okay just like that
- 8:57:09looks pretty good so this is the main
- 8:57:11menu button and then let's also make so
- 8:57:14duplicate this let's make this one
- 8:57:15rename it this is the resume button and
- 8:57:19inside on the text let's say resume okay
- 8:57:21we have our two basic buttons so let's
- 8:57:24hand them in the script so over here
- 8:57:26let's add as usual a serialized field
- 8:57:28private of type button so that's inside
- 8:57:30unityengine.ui
- 8:57:32so it's for the resume button and then
- 8:57:35we're going to have the main menu button
- 8:57:39okay let's save the script and back in
- 8:57:41the editor let's drag those references
- 8:57:43so that's the main menu button and the
- 8:57:45resume button okay so now for these
- 8:57:48let's add the click action so let's do a
- 8:57:50private void awake and on awake go into
- 8:57:51the resume button the on click and let's
- 8:57:53add a a listener so this going to be our
- 8:57:56listener and same thing for a main menu
- 8:57:59button so main menu now for the main
- 8:58:01menu this one is super simple let's just
- 8:58:03go into the loader and call the load
- 8:58:05function and we're going to load the
- 8:58:07main menu scene okay that's the main
- 8:58:09menu very simple and for the resume this
- 8:58:12one is only going to be clickable when
- 8:58:13the game is paused so we can just
- 8:58:15trigger the same function on the kitchen
- 8:58:17game manager to toggle the pause so
- 8:58:19kitchen game manager the instance and
- 8:58:22toggle the pause game this one is
- 8:58:24actually private so let's go to it and
- 8:58:27let's make this public so we can call
- 8:58:28from there okay that's it super simple
- 8:58:30let's test okay so here we are and let's
- 8:58:33pause the game and now if I click on
- 8:58:34resume yep there you go it does work
- 8:58:36everything resumes and now pause again
- 8:58:38and now let's go back to the main menu
- 8:58:40loading and yep there you go back in
- 8:58:42main menu all right awesome so
- 8:58:44everything works perfectly however
- 8:58:46there's one sneaky issue here you can
- 8:58:49already see the issue by seeing that all
- 8:58:50of these animations are still but let's
- 8:58:52click on play and look that issue
- 8:58:54everything is still frozen I cannot move
- 8:58:57the character and over there the Shader
- 8:58:59that one is completely Frozen so the
- 8:59:01time scale is still set to zero
- 8:59:03basically we need to manually reset it
- 8:59:05and the simplest way to do this is
- 8:59:07really just in the main menu so we can
- 8:59:09go here on the main menu Y and we can
- 8:59:11just use this as our reset function so
- 8:59:14let's just go into time. time scale and
- 8:59:17let's set this one back into 1f that's
- 8:59:19it that's the only change let's test so
- 8:59:21here we are let's pause let's go back
- 8:59:23into the main menu
- 8:59:24and we can see the animations are indeed
- 8:59:26playing and if we go back into play and
- 8:59:28if there you go everything works
- 8:59:29perfectly we can pause and yep here we
- 8:59:32do see one of the other two sneaky
- 8:59:34issues left basically it has to do with
- 8:59:36scene loading and cleanup so the first
- 8:59:39one is on input over here on the game
- 8:59:42input class we are constructing our
- 8:59:44player input actions and we are
- 8:59:46listening to these events and
- 8:59:48technically this object the one where
- 8:59:49the game input is attached this object
- 8:59:51is going to be destroyed when the scene
- 8:59:53changes
- 8:59:54however this object that we're creating
- 8:59:56this instance of player input actions
- 8:59:59this one does not get destroyed
- 9:00:00automatically so that is why when I went
- 9:00:02into the pause menu again for the second
- 9:00:04time over here we've got a missing
- 9:00:06reference exception basically the player
- 9:00:09input actions of the previous game is
- 9:00:10trying to show the pause window also of
- 9:00:12the previous game which has since been
- 9:00:14destroyed so obviously we have a missing
- 9:00:16reference exception because that object
- 9:00:18no longer exists so in this case we have
- 9:00:21two options to solve this one option is
- 9:00:23we can just unsubscribe to these events
- 9:00:26Unity mono behaviors have a really nice
- 9:00:27comback called on Destroy so over here
- 9:00:30private void on Destroy so this is the
- 9:00:32default one this one is called when the
- 9:00:33mono behavior is
- 9:00:35destroyed so we can go into this one and
- 9:00:37we can manually unsubscribe and the way
- 9:00:40that you unsubscribe is you just do
- 9:00:41minus
- 9:00:44equals so this would solve that problem
- 9:00:46because when this object is destroyed
- 9:00:48it's going to unsubscribe from those
- 9:00:49events so the next time it will no
- 9:00:51longer trigger so that would fix it
- 9:00:54however on the game input class we are
- 9:00:55still creating a new object of this type
- 9:00:58I'm not 100% sure how the input system
- 9:01:01works in the background so perhaps this
- 9:01:03object might stay in memory which is not
- 9:01:05good so another approach we can do or
- 9:01:07perhaps in combination with this is we
- 9:01:09can unsubscribe and then we can properly
- 9:01:11dispose of this object how we do that is
- 9:01:14very simple let's just go into the
- 9:01:16player input actions and we just call
- 9:01:18the dispose function that's it this
- 9:01:21should clean up that object and free up
- 9:01:23any memory so let's test so here in the
- 9:01:25game view let's pause let's go back into
- 9:01:27the main menu now let's go back into the
- 9:01:30main game and if I hit pause and Y there
- 9:01:32you go we no longer have any errors okay
- 9:01:34so that's good however now we still have
- 9:01:37one more potential issue and this one
- 9:01:39has to do with Statics like I mentioned
- 9:01:42before Statics belong to the class and
- 9:01:44not any instance of that class so that
- 9:01:46means that static Fields will not be
- 9:01:48destroyed or reset when the scene
- 9:01:49changes in the case of our loader here
- 9:01:52where we have a private static field
- 9:01:54this one the fact that this one doesn't
- 9:01:55reset automatically that was a good
- 9:01:57thing that's what allowed this to make
- 9:01:58the unloading system but in the case of
- 9:02:00maybe static events that might not be as
- 9:02:02good it might mean that we might be
- 9:02:04keeping some saate from the previous
- 9:02:06game which might cause everything to
- 9:02:08break so basically we have a similar
- 9:02:10problem to what we had in the input
- 9:02:12where some logic from the previous game
- 9:02:14might be affecting the next game in all
- 9:02:16the code that we wrote the main place
- 9:02:17where we use Statics were in the
- 9:02:19Singleton and these are going to be
- 9:02:21cleared automatically when the
- 9:02:22underlying instance object when that one
- 9:02:24is destroyed so these do not cause any
- 9:02:27problems however for example over here
- 9:02:29on the cutting counter we've got a
- 9:02:31static event when the scene changes this
- 9:02:34will not be cleared so this will still
- 9:02:36have the same number of listeners we can
- 9:02:38actually see how many listeners there
- 9:02:39are by printing it so let's go down here
- 9:02:41before we're invoking the event let's do
- 9:02:44a debug. log let's go inside the on any
- 9:02:47cut event and over here we can get the
- 9:02:49invocation list this one is a list of
- 9:02:52all the functions that are listening to
- 9:02:53the this event and we can just print out
- 9:02:56the link to see how many listeners are
- 9:02:57listening to this event so let's see
- 9:02:59what this returns okay so over here
- 9:03:02let's pick up some cheese and slice it
- 9:03:04and if I look in the log yep there you
- 9:03:05go one there's only one listener okay
- 9:03:07that's correct however now if I go back
- 9:03:10into the main menu and now I go back and
- 9:03:13I play again okay so let's play let's
- 9:03:16just wait for the countdown and once it
- 9:03:18countown ends pick up some cheese go
- 9:03:20there slice it and there you go there's
- 9:03:21the problem now we have two listeners in
- 9:03:23this case doesn't really cause an error
- 9:03:25because the tun listeners they're just
- 9:03:27over here on The Sound Manager so we are
- 9:03:29subscribing to this event and we're
- 9:03:31doing the cut and playing the cut object
- 9:03:33however if here we do something with
- 9:03:35this transform like for example let's
- 9:03:37just do a debug. log on this transform.
- 9:03:39position if we do this here let's go
- 9:03:43ahead on the first one let's slice and
- 9:03:44okay that works let's go back into the
- 9:03:46main menu now play again now wait for
- 9:03:49the timer pick up some cheese go there
- 9:03:51slice and if there you go there we have
- 9:03:53our error that is because we are now
- 9:03:55accessing The Sound Manager transform
- 9:03:56and that one has since been destroyed so
- 9:03:58if you do use static events like this
- 9:04:00one here if you do that always remember
- 9:04:03you need to manually reset that state it
- 9:04:05won't happen automatically on the scene
- 9:04:07load and one way that I normally do it
- 9:04:09is just make a class responsible for
- 9:04:11doing that so let's go ahead let's
- 9:04:13create a brand new C Class let's call
- 9:04:15this the reset static data manager and
- 9:04:19for this one we want this one to run
- 9:04:20only on the main menu That's only where
- 9:04:22we're going to reset the things so let's
- 9:04:25go inside the main menu scene let's go
- 9:04:27there let's create a brand new mty game
- 9:04:29object for the reset static data manager
- 9:04:33let's reset transform just keep things
- 9:04:35clean and let's attach that script again
- 9:04:38it's very important that this object
- 9:04:39only exists on the main menu then over
- 9:04:41here we're basically just going to go
- 9:04:43into any script and reset any data so
- 9:04:45for that on all those scripts let's make
- 9:04:47a function so over here on the cutting
- 9:04:49counter let's make a public static
- 9:04:51function let's call this reset Set
- 9:04:54static data and in order to reset any
- 9:04:56listeners let's just go into the on any
- 9:04:58cut and set it to null that won't clear
- 9:05:00all the listeners so we just do this and
- 9:05:03then on this script let's do a private
- 9:05:05void awake and on awake let's go into
- 9:05:07the cutting counter under the class so
- 9:05:09not any instance so we're going to
- 9:05:11access the static and we're going to
- 9:05:13reset the static data that will clear
- 9:05:15all the listeners on The Cutting counter
- 9:05:17all we need to do is make sure to do
- 9:05:19this on every single static event that
- 9:05:20we have so on The Sound Manager and by
- 9:05:23the way here we can get rid of the
- 9:05:24testing code here we can see all of the
- 9:05:27static events that we're using so we've
- 9:05:29got the cutting counter then we've got
- 9:05:30the base counter and trash counter so
- 9:05:32let's go here on the base counter and
- 9:05:33paste the exact same thing and reset
- 9:05:36this event okay and now let's go into
- 9:05:38the trash counter so here on trash
- 9:05:40counter same thing reset this event set
- 9:05:43them all into null and by the way here
- 9:05:45we have a warning that's because trash
- 9:05:47counter extends base counter so
- 9:05:48basically this is telling us that we are
- 9:05:50hiding another function with the exact
- 9:05:51same name in this case we do want to
- 9:05:53hide it so let's actually make this new
- 9:05:55to make sure that this one is a
- 9:05:56different one just to avoid that warning
- 9:05:59and same thing over here on the cutting
- 9:06:01counter we also need to make a new okay
- 9:06:03so that's it and now we just need to go
- 9:06:05over here onto the reset static data
- 9:06:07manager let's go into the base counter
- 9:06:09and reset the static data go into the
- 9:06:11trash counter and reset the static data
- 9:06:14okay that should do it let's see so here
- 9:06:16we are in the game let's pick it up and
- 9:06:17slice it and yep we've got just one
- 9:06:19listener that's good let's go back
- 9:06:21outside back into the main menu let's
- 9:06:23play once more and over here let's pick
- 9:06:26it up again go there drop it and there
- 9:06:27you go still just one listener because
- 9:06:29we are now correctly eliminating all of
- 9:06:31the previous listeners so this is the
- 9:06:33one sneaky issue that you must be
- 9:06:35careful with when it comes to object
- 9:06:36Lifetime and Statics for static Fields
- 9:06:39you need to remember that they don't
- 9:06:40manually get cleaned up that's up to you
- 9:06:43so that's something you have to keep in
- 9:06:44mind but you can also see how easy it is
- 9:06:46to solve now that this is solved let's
- 9:06:48just go into the cutting counter and
- 9:06:49just get rid of our testing log all
- 9:06:51right so with all of that all of our
- 9:06:52scenes are working so we can start from
- 9:06:54here from the main menu and go straight
- 9:06:56into the game then here we are in the
- 9:06:58game playing normally we can pause the
- 9:07:00game at any point from the pause screen
- 9:07:02we can either resume or we can go back
- 9:07:04into the main menu and from back into
- 9:07:06the main menu we can once again play the
- 9:07:08game from scratch and you there you go
- 9:07:10everything works all right awesome now
- 9:07:13the next thing that every game requires
- 9:07:15is some options so let's do that in the
- 9:07:17next
- 9:07:18lecture hello and welcome I'm your Cod
- 9:07:21monkey in this lecture we're going to
- 9:07:23create a simple options menu where we
- 9:07:24can modify the audio levels okay so here
- 9:07:27let's make the options menu so on our
- 9:07:29game scene let's go into the canvas and
- 9:07:31create a new MTM object let's make this
- 9:07:34the options UI let's stretch out this
- 9:07:36one to occupy the entire screen then
- 9:07:39inside let's make a UI image once again
- 9:07:42let's stretch out
- 9:07:44everything let's put this one in black
- 9:07:47and just almost full Alpha okay now
- 9:07:50let's make some text so let's create a
- 9:07:52brand new UI text
- 9:07:54call it the options text then for text
- 9:07:57let's say just options let's put the
- 9:08:00width and height at zero let's disable
- 9:08:03wrapping Put It Center down the middle
- 9:08:05and put it quite a lot
- 9:08:07bigger okay that's the options now just
- 9:08:09move it slightly upwards all right now
- 9:08:12let's make some simple buttons to handle
- 9:08:14our audio controls we're going to make
- 9:08:15it super simple literally just a button
- 9:08:17we can click so inside the options UI
- 9:08:20let's create a brand new button call
- 9:08:22this the sound sound effects button then
- 9:08:26let's make the button a bit bigger
- 9:08:28something like this
- 9:08:31okay and inside for the text let's say
- 9:08:34sound effects and then we're going to
- 9:08:36have a number for the sound effects
- 9:08:38let's just quickly change the color so
- 9:08:40put the text in White and the button
- 9:08:43over here the button image let's put it
- 9:08:45in a dark ray okay let's also make it
- 9:08:48just a tiny bit thinner just like that
- 9:08:50okay so this is the sound effects button
- 9:08:52now let's duplicate this this one this
- 9:08:53one is going to be the music button so
- 9:08:55let's name this the music
- 9:08:57button then inside for the text music
- 9:09:00and then a number and that's pretty much
- 9:09:02it so by clicking on either of these
- 9:09:05buttons we're going to increase and then
- 9:09:06Loop the volume so let's make a simple
- 9:09:09script to handle our options window so
- 9:09:11in our scripts inside the UI let's
- 9:09:13create a brand new C script for the
- 9:09:15options UI let's go ahead and attach a
- 9:09:18script and open so here as usual let's
- 9:09:21get some fields for our button so
- 9:09:23serialized film private of type button
- 9:09:26for the sound effects button and then
- 9:09:29there's another one for the music
- 9:09:34button okay both buttons now let's add
- 9:09:37the click events so on private board
- 9:09:38awake let's go into the sound effects
- 9:09:40button and on the onclick let's add a
- 9:09:44listener and we're going to do the same
- 9:09:46thing on the music
- 9:09:47button okay so now when we click we want
- 9:09:51to change the volume so let's go go here
- 9:09:53onto The Sound Manager and make a
- 9:09:55function to modify the volume let's make
- 9:09:58a private void change
- 9:10:02volume and here we're going to increase
- 9:10:04the volume by .1% so constantly increase
- 9:10:06in 10% increments so that means we need
- 9:10:09to keep track of the volume so up here
- 9:10:11let's find find a simple private float
- 9:10:13for the
- 9:10:18volume let's default it to onef okay so
- 9:10:21now down here we take the volume and we
- 9:10:24increase it by 0.1f and now let's Loop
- 9:10:27it back to zero now for looping usually
- 9:10:29you do it using the modular operator so
- 9:10:32here you could do volume equals volume
- 9:10:34modu of 1.1 F that way when it gets to
- 9:10:381.1 f it would reset back to zero but
- 9:10:41here since we're working with floats
- 9:10:43which can have a bit of odd Precision
- 9:10:45with this let's just do a simple if to
- 9:10:47make sure that always works so if the
- 9:10:49volume is above
- 9:10:511f if so then let's just reset it to
- 9:10:54zero okay so here we modified the volume
- 9:10:57and let's just make sure to use it over
- 9:10:59here when we actually call the audio
- 9:11:00source. playay clip at Point here we've
- 9:11:03got a volume but this is the one that we
- 9:11:04received as a parameter so let's
- 9:11:06actually receive this one rename this to
- 9:11:09volume
- 9:11:10multiplier and we're going to basically
- 9:11:12multiply the one that we receive in the
- 9:11:14parameter by the one that we actually
- 9:11:16store so this way on these functions
- 9:11:18when we play a certain sound we can
- 9:11:20still give an optional volume if we want
- 9:11:22to make it louder or quieter than the
- 9:11:24regular sound effects okay so we have
- 9:11:27our change volume function now we just
- 9:11:29need to call this from the options UI so
- 9:11:31that means this one actually needs to be
- 9:11:32public okay so now here on the options
- 9:11:34UI we go into the sound manager access
- 9:11:37the instance and call change volume okay
- 9:11:39so that is going to change the volume
- 9:11:41then we just need to update the values
- 9:11:43on the options UI so let's make a
- 9:11:45private void update
- 9:11:48Visual and this one we need to update
- 9:11:50the text so up here let's add once again
- 9:11:52some more generaliz Fields so text mesh
- 9:11:55Pro UI one for the sound effects text
- 9:11:59and another one for the music
- 9:12:01text okay we have both these then here
- 9:12:04the sound effects text. text equals and
- 9:12:08we go into The Sound Manager the
- 9:12:12instance and then we need to get the
- 9:12:14volume so over here on the sound menion
- 9:12:16let's make a function to get it so we
- 9:12:18public float return get volume and we
- 9:12:22just return volume okay so then here
- 9:12:25let's get volume except volume is going
- 9:12:27to be a normalized value so rather than
- 9:12:29showing .1 2.3 on the UI let's just
- 9:12:34multiply the volume by 10f that way we
- 9:12:36show between 1 and 10 okay then let's
- 9:12:39just round out this
- 9:12:41number and then add the text so here
- 9:12:45sound effects and then we have the
- 9:12:48volume okay so that's pretty much it and
- 9:12:51up here when we change the volume let's
- 9:12:52just just update the visual and let's
- 9:12:55also make a priv void start and on start
- 9:12:58let's also update the visual okay that's
- 9:13:00it pretty simple now let's do the exact
- 9:13:02same thing on the music except on the
- 9:13:04Music Manager we named it music manager
- 9:13:06but over here we just have an audio
- 9:13:08Source there's no actual manager so
- 9:13:09let's actually make one let's create new
- 9:13:11C script for the Music Manager let's go
- 9:13:15into the Music Manager object let's
- 9:13:18attach a script and let's open so here
- 9:13:21we really just need pretty much Exel the
- 9:13:23same thing that we had so let's just go
- 9:13:25here into The Sound Manager and just
- 9:13:26copy these so on the Music Manager let's
- 9:13:29paste them we need a volume so a private
- 9:13:32FL for the volume just like this okay so
- 9:13:34that changes the volume except again the
- 9:13:36Music Manager this one the music is
- 9:13:38constantly going to be looping so after
- 9:13:40we modify the volume we need to update
- 9:13:42the actual audio source so let's first
- 9:13:44begin by grabbing the audio source audio
- 9:13:47source and we just do a private boid
- 9:13:49awake and on awake let's grab the audio
- 9:13:52source get the component of type audio
- 9:13:54Source okay so we have this and when we
- 9:13:57change the volume let's go here and
- 9:13:59update this volume okay that's it and
- 9:14:01let's also default it to something like
- 9:14:033F okay good then in order to be able to
- 9:14:06call this from the options UI we just
- 9:14:07need to make it a s ton so as usual
- 9:14:09public static Music Manager for the
- 9:14:12instance and we have a public get and a
- 9:14:14private
- 9:14:15set and then awake just set instance
- 9:14:18equals this okay so then here on the
- 9:14:21options UI we can go into the music
- 9:14:23manager the instance and change the
- 9:14:25volume and afterwards let's update the
- 9:14:27visual and down here on the update
- 9:14:29visual let's do pretty much the same
- 9:14:30thing so on the music text modify the
- 9:14:33text to say music then we go into the
- 9:14:36music manager and get the volume all
- 9:14:39right that's it all this should be
- 9:14:41working let's just drag our references
- 9:14:43so back in the editor let's drag first
- 9:14:44the button so the sound effects button
- 9:14:46that's this one then the music button
- 9:14:49that's this one then we have the music
- 9:14:51text that's this one and the sound
- 9:14:53effects test like that okay let's test
- 9:14:56okay so here we are the music is playing
- 9:14:58and as I click the music is currently
- 9:14:59getting louder and louder and there you
- 9:15:02go music is at max volume and if I click
- 9:15:04again now the music is completely muted
- 9:15:06all right awesome and the sound effects
- 9:15:08also work so like this they should be
- 9:15:10less louder than usual okay great so
- 9:15:12everything works perfectly except
- 9:15:14obviously we have one big issue the
- 9:15:16options window is on top of everything
- 9:15:19the goal is for the options window to be
- 9:15:21kind of a submenu of the pause window
- 9:15:23we want to have an options button on the
- 9:15:25pause window that will bring up the
- 9:15:27options window so let's do that let's
- 9:15:29first hide the options window let's go
- 9:15:31into the game pause UI and over here we
- 9:15:33have these buttons let's just make one
- 9:15:35more let's put it down the middle this
- 9:15:37is going to be the options button and
- 9:15:40inside let's modify the text to options
- 9:15:43okay now let's setedit this script so
- 9:15:45we're going to have another button so
- 9:15:47this is the options button and down here
- 9:15:50we're going to have another click so the
- 9:15:51options button okay okay and when this
- 9:15:54happens we want to just show the options
- 9:15:56window so in order to access it let's
- 9:15:59make this a single T So public static
- 9:16:01for the options
- 9:16:03UI a static
- 9:16:08instance with a get a private set and
- 9:16:11onw as usual instance equals this so
- 9:16:15over here on the game posi y we go into
- 9:16:17the options UI access the instance and
- 9:16:19then call a show function so we need to
- 9:16:21make this
- 9:16:23so here on the options UI let's make
- 9:16:25those so a public void
- 9:16:28show and this one as usual just game
- 9:16:30object set active into
- 9:16:38true and then we have a private void
- 9:16:41hide and this set active into false okay
- 9:16:46we have both these on the other side we
- 9:16:48show it and over here on start let's
- 9:16:50also hide it okay
- 9:16:53then let's also hide it manually so
- 9:16:55let's add a button to close the options
- 9:16:56UI so over here let's show the options
- 9:16:59UI and let's make another button let's
- 9:17:02put it on the bottom this one is a close
- 9:17:05button and over here let's just say
- 9:17:07close so then here on the options UI
- 9:17:09just make another button the close
- 9:17:11button and down here for the click
- 9:17:15event we go into the close button and we
- 9:17:18just call
- 9:17:19hide okay so that will hide the window
- 9:17:22how however remember that the pause
- 9:17:24window can also be closed by just
- 9:17:25pressing escape if we resume with a
- 9:17:28hotkey it won't hide the pause window so
- 9:17:31let's also make sure this one hides on
- 9:17:32the same thing so we can do pretty much
- 9:17:34going to the kitchen game manager the
- 9:17:35instance and let's listen when the game
- 9:17:37is unpaused so when that happens let's
- 9:17:40hide this window so once again let's do
- 9:17:43things nice and clean let's rename this
- 9:17:45so the kitchen game manager and when
- 9:17:49this happens let's just hide okay this
- 9:17:51should work let's just drag all the
- 9:17:53references so first here on the options
- 9:17:55UI let's drag the close button and then
- 9:17:58on the game pause UI let's drag the
- 9:18:01options button okay so let's test and
- 9:18:04yep right away the options window is not
- 9:18:05showing that's great and if I press an
- 9:18:07escape there you go there's the pause
- 9:18:08window and if I click on options yep
- 9:18:10there's the options window now if I
- 9:18:11click on close back here back into
- 9:18:13resume okay works now if I pause options
- 9:18:16and now press on the Escape key and
- 9:18:19there go it closes everything all right
- 9:18:21great so everything is working fine
- 9:18:23however we have one slight
- 9:18:26issue the option does work so I can
- 9:18:29modify this to change the sound effects
- 9:18:31in the music volume so for example let's
- 9:18:33mute the music and put the sound effects
- 9:18:35on five so I put it like this but now if
- 9:18:38I stop playing and I hit play again and
- 9:18:42look in the options and nope there's the
- 9:18:44issue basically the data is back to the
- 9:18:46defaults obviously that is resetting
- 9:18:48since we didn't actually save anything
- 9:18:50so let's save it now in unity the
- 9:18:53easiest way to save some data is using
- 9:18:54player prefs so let's go over here on
- 9:18:57The Sound Manager and when we modify the
- 9:18:59volume over here when we do that let's
- 9:19:02access the Unity Player prefs and over
- 9:19:05here we've got a bunch of set functions
- 9:19:07so we can save a float and int or a
- 9:19:09string this one as you can see takes a
- 9:19:11string and a value so this is pretty
- 9:19:13much essentially just a dictionary now
- 9:19:16for the key as you can see it's a type
- 9:19:18string but again we should not be using
- 9:19:19strings directly so let's go up here in
- 9:19:22our to make a proper constant so a
- 9:19:24private con string let's call it player
- 9:19:28prefs sound effects
- 9:19:31volume and let's go sound effects volume
- 9:19:36okay we have our nice Cent constant and
- 9:19:39down here when we set the float let's
- 9:19:41use this string and save the volume okay
- 9:19:43so that is going to set the float and
- 9:19:46now technically Unity is going to
- 9:19:48automatically save the player PRS
- 9:19:50basically there are only problems if
- 9:19:51Unity somehow crashes in between when
- 9:19:54you call set float and when it actually
- 9:19:56saves but if you want to prevent that
- 9:19:59from happening you can just go and tell
- 9:20:00it to save manually just like that that
- 9:20:03will definitely save it and now we just
- 9:20:05need to handle loading so here on a wake
- 9:20:08when we have this let's go into the play
- 9:20:09prefs and let's use get float let's pass
- 9:20:12in the same key so this one takes a key
- 9:20:15and default value so let's defa it to 1f
- 9:20:18basically the default value is used if
- 9:20:20there's no save data on displayer press
- 9:20:22on this key so the first time we run
- 9:20:24it's actually going to use this default
- 9:20:27and this one is going to return the
- 9:20:28saved value so let's just set it on the
- 9:20:30volume okay so that's it that's all it
- 9:20:32takes to save some basic data now let's
- 9:20:34do the exact same thing on music so over
- 9:20:36here on the Music Manager let's first
- 9:20:39Define our private con string for the
- 9:20:43player prefs music volume and this is
- 9:20:47going to be the Music
- 9:20:49Volume okay we have our string and then
- 9:20:52down here when to change the volume
- 9:20:53player
- 9:20:57presss and let's set the float on this
- 9:21:00key and let's pass in the Music Volume
- 9:21:03okay and then let's go into player preps
- 9:21:05and actually save it and now appear on
- 9:21:08awake let's grab the
- 9:21:10volume and it's going to be going to the
- 9:21:12player preface in order to get the float
- 9:21:15on this
- 9:21:16key and default value is 3F however over
- 9:21:20here on the music again we are not
- 9:21:21spawning the sound afterwards the sound
- 9:21:24starts playing right away so let's make
- 9:21:26sure to set the audio Source volume to
- 9:21:28the one we grab from there okay that's
- 9:21:31it so like this it should be working so
- 9:21:33let's test so here we are and the music
- 9:21:35is playing let's pause going to the
- 9:21:37options let's bring the music completely
- 9:21:40down so let's mute the music okay the
- 9:21:42music is gone and sound effects let's
- 9:21:43put it on five now let's stop playing
- 9:21:46and now play again and go into the menu
- 9:21:49options and Y there you go the data was
- 9:21:51indeed saved and the music music is
- 9:21:52indeed muted all right awesome so here
- 9:21:56we have some basic data being saved and
- 9:21:58also just quick note related to saving
- 9:22:00for this simple game the sessions are
- 9:22:02pretty quick so I didn't include any
- 9:22:03kind of save system for the actual game
- 9:22:05data but if you want to know how to do
- 9:22:07that I also have video covering that
- 9:22:09topic okay so with that we have our
- 9:22:11options window working the volume
- 9:22:13sliders work perfectly the next thing we
- 9:22:15need to add to our options is some key
- 9:22:17rebinding so let's do that in the next
- 9:22:20lecture hello and welcome I'm your Cod
- 9:22:22mon in this lecture we're going to add
- 9:22:25key rebinding to our options menu so
- 9:22:27here we already have this nice options
- 9:22:29menu we can modify the volume of the
- 9:22:31sound effects or the music next let's
- 9:22:33handle key rebinding okay so first let's
- 9:22:35build the elements over here on the UI
- 9:22:37so let's create a bunch more buttons but
- 9:22:40before that let's actually make some
- 9:22:41text on the side and buttons in the
- 9:22:42middle so let's create a brand new UI
- 9:22:45text call this move up text let's put it
- 9:22:49on the same size as the other one so
- 9:22:51these got a font of 24 let's put it the
- 9:22:53same thing font of 24 width and height
- 9:22:55let's put both of these on zero and down
- 9:22:58here anchor it to the left okay down the
- 9:22:59middle and with no wrapping okay so then
- 9:23:02over here this is going to be the move
- 9:23:04up action so we have move up then we
- 9:23:07have the move down move left move right
- 9:23:10then we have the interact the interact
- 9:23:12alternate and finally the pause so these
- 9:23:14are all of our actions so let's just
- 9:23:16make all of these so rename this so this
- 9:23:19one is the move down then this one over
- 9:23:21here is the move left this one is the
- 9:23:25move right this one is the interact text
- 9:23:28then the interact alternate text and
- 9:23:32finally the pause text now let's just
- 9:23:34modify the text on these so that's the
- 9:23:36pause that one is the interact
- 9:23:39alt then this one is the interact then
- 9:23:43we've got the move right then over here
- 9:23:47the move left and finally we have the
- 9:23:50move down okay so those are our labels
- 9:23:53for our controls now let's just make
- 9:23:55buttons over here on the right side so
- 9:23:57let's duplicate one of these buttons
- 9:23:58let's put it over here and put it on
- 9:24:00some like 50 by 50 so this is going to
- 9:24:03be the move up button and inside on the
- 9:24:07text this is going to be pretty much
- 9:24:09just a w okay so we have the move up
- 9:24:13then we're going to have the move down
- 9:24:15move left move right the interact the
- 9:24:19interact alternate and the pause so we
- 9:24:21just need a a bit more space so let's
- 9:24:23move all of these up by quite a bit
- 9:24:25let's also move the music and the sound
- 9:24:28effects so move all of these like that
- 9:24:31okay let's just name all these buttons
- 9:24:34so this one is the second one so this
- 9:24:37move
- 9:24:38down then over here the move left then
- 9:24:42the move right then the interact button
- 9:24:47the interact alternate button and
- 9:24:50finally the pause button
- 9:24:53okay those are all the buttons let's
- 9:24:54just position all the en labels exactly
- 9:24:57where they should
- 9:25:01be okay so here we have all of the
- 9:25:04options all of our bindings now in code
- 9:25:06let's grab references to all the buttons
- 9:25:08and all the text inside the buttons so
- 9:25:10over here inside the options U let's add
- 9:25:12all of those so first of all for the
- 9:25:14text we're going to have the move up
- 9:25:16text then the down left right and so on
- 9:25:18so let's just do all of these so down
- 9:25:21then over here the left then the right
- 9:25:24then the interact text the interact
- 9:25:26alternate text and finally we have the
- 9:25:30pause text and for the buttons let's go
- 9:25:33up here make all the buttons so they
- 9:25:34move up button then the move down
- 9:25:39button then we have the move left button
- 9:25:43then the move right button then we have
- 9:25:45the interact button the interact
- 9:25:47alternate button and finally the pause
- 9:25:50button
- 9:25:52okay so we have all of these references
- 9:25:55over here in the editor let's just drag
- 9:25:56them so let's make sure we drag them all
- 9:25:58correctly so let's do it one by one so
- 9:26:01the move up this is the text and
- 9:26:03actually it's not that one so that's
- 9:26:04already a mistake right there we want
- 9:26:05the text from inside buttons so let's
- 9:26:08pick up all of these text objects so
- 9:26:10let's go into the options so text inside
- 9:26:12the move up let's grab that one then
- 9:26:14inside the move down let's grab that one
- 9:26:16and the left and so on so definitely
- 9:26:18make sure you grab the right ones okay
- 9:26:21that's on text now for the button so
- 9:26:22that you move up button then the move
- 9:26:25down then the move left the move right
- 9:26:29the interact interact alternate and
- 9:26:32finally the pause button okay great and
- 9:26:35just to verify that everything is
- 9:26:36working let's give proper names to these
- 9:26:39objects so the move up button
- 9:26:47text okay so I've renamed all the
- 9:26:49buttons so now over here it's much
- 9:26:51easier to verify that we have the
- 9:26:52correct references so the sound sound
- 9:26:54music music and so on so definitely make
- 9:26:56sure all of these are correct otherwise
- 9:26:58you might go crazy when things start to
- 9:26:59go a bit weird so make sure these are
- 9:27:01all correct all right now let's begin by
- 9:27:04updating the text inside over here so
- 9:27:06let's go into our update visual so we go
- 9:27:08into this set the text and now we need
- 9:27:10to get the binding text for this binding
- 9:27:12so for that let's make that function on
- 9:27:14the game input over here let's just
- 9:27:16comment this out then over here on the
- 9:27:18game input script let's make a function
- 9:27:20to get the bindings so technically we
- 9:27:22could make something just to grab this
- 9:27:24player input actions but again we don't
- 9:27:26want the options UI to know what input
- 9:27:28system we're using it should work
- 9:27:30regardless of what input system so we
- 9:27:33don't want the game input to return
- 9:27:34anything of this type instead we want to
- 9:27:36make a nice layer of abstraction so for
- 9:27:39that let's make an enum to Define all of
- 9:27:40our bindings so let's make a public
- 9:27:43since we're going to access it enum call
- 9:27:45it binding and over here let's add all
- 9:27:48the bindings so we've got the move up
- 9:27:50then we have the move down down the move
- 9:27:53left the move right then we have the
- 9:27:57interact the interact
- 9:27:59alternate and finally dep pause so these
- 9:28:02are all of the bindings now let's make a
- 9:28:04function to return the binding text so
- 9:28:07over here let's make a public we're
- 9:28:09going to return a string let's just name
- 9:28:11it get binding text and as a parameter
- 9:28:14let's receive a
- 9:28:16binding okay so now here let's just do a
- 9:28:19switch switch on this binding and
- 9:28:21basically just match up the enome to
- 9:28:23whatever action we have so for example
- 9:28:26let's begin with the interact since
- 9:28:28these are the simplest ones so for this
- 9:28:30one to get the bindings we first go
- 9:28:33inside the player input actions then
- 9:28:35let's go inside the player action map
- 9:28:37then for the action so in this case the
- 9:28:39interact and then inside we've got the
- 9:28:42bindings this is an array of all the
- 9:28:44bindings in our input map we defined all
- 9:28:47of the keyboard bindings on index zero
- 9:28:49later on we're going to add Gamepad
- 9:28:50bindings but for now we're going to have
- 9:28:52the keyboard always on index zero so
- 9:28:55over here going to bindings access on
- 9:28:57zero and let's just do a two string okay
- 9:29:00so let's just return this and let's do a
- 9:29:02default to return always this one just
- 9:29:04like this okay so let's do a quick log
- 9:29:06to see what this returns so let's do it
- 9:29:08over here on the game input just a
- 9:29:10debug.log go into there get the binding
- 9:29:12text for the
- 9:29:14interact okay so let's test and right
- 9:29:16away yep we do see it working so the
- 9:29:18interact and The Binding is on keyboard
- 9:29:21SL e but we don't want all this text we
- 9:29:23really just want to see the E thankfully
- 9:29:26the input system has a really great
- 9:29:27function for just that so instead of
- 9:29:29calling the general two string let's
- 9:29:31call two display string let's see and Y
- 9:29:34this one does return just e key okay
- 9:29:36great so this is the one that we want
- 9:29:38let's do the same thing for all of the
- 9:29:40other simple actions so we've got the
- 9:29:42interact then we have the interact
- 9:29:45alternate and we have the pause so these
- 9:29:48are all the super symol ones so just
- 9:29:50going to interact alternate grab the
- 9:29:52binding on zero and for the pause
- 9:29:54binding on zero okay so these are all
- 9:29:56super simple now the more complex one is
- 9:29:58the move it's more complex because you
- 9:30:00can see all the others just have one
- 9:30:02binding except for the move over here we
- 9:30:04have a composite binding so that's
- 9:30:07basically a binding which inside has
- 9:30:08four separate bindings basically the way
- 9:30:10that this works is that when you use a
- 9:30:12composite binding all of these are added
- 9:30:13to the array so this 2D Vector is going
- 9:30:16to be on binding zero then the up is
- 9:30:18going to be on binding 1 2 3 four and so
- 9:30:20on then the arrow key this one is going
- 9:30:22to be on five then we have 6 7 8 9 and
- 9:30:2610 let's do a log just to verify so here
- 9:30:30if we do one for the move up action for
- 9:30:34this one let's go into the move and
- 9:30:35let's print out just the binding zero
- 9:30:37let's a regular two string let's see
- 9:30:40what this returns so up here let's just
- 9:30:42modify our log to say the move up okay
- 9:30:45so let's see and yep index zero does
- 9:30:47have the move to the vector and now if
- 9:30:49we print the one on binding of one y yep
- 9:30:52now this one does have the move on the
- 9:30:53dou so like I said we can see that all
- 9:30:56of these composits These are technically
- 9:30:58inside that one but in terms of that
- 9:31:00array it's just a flat array so this one
- 9:31:02index zero 1 2 3 and four so that makes
- 9:31:05it super simple to add over here so they
- 9:31:08move up down left right and let's just
- 9:31:10do all
- 9:31:12these so we have all the bindings and
- 9:31:15over here just one two 3 and
- 9:31:18four and instead of two string let's
- 9:31:20call the display string okay so the
- 9:31:23binding text this is all set up so let's
- 9:31:25go up here and get rid of our testing
- 9:31:27code we can now call this from the
- 9:31:29options so over here let's do exactly
- 9:31:31that so when we update the visual let's
- 9:31:34go into the game input let's access the
- 9:31:36static instance let's get the binding
- 9:31:38text and this one is going to be the
- 9:31:40move up so that's it this one is going
- 9:31:43to return a string let's write all of
- 9:31:45them
- 9:31:53okay here are all of them so let's see
- 9:31:55and yep there they are all perfect WSC
- 9:31:57EF Escape okay great so the visual is
- 9:32:00working now let's handle the rebinding
- 9:32:02so let's add a click event let's go into
- 9:32:05the move up
- 9:32:07button let's go into the on click let's
- 9:32:09add a listener and for the listener over
- 9:32:12here let's make a function on the game
- 9:32:14input to rebind this binding so over
- 9:32:17here on the game input let's say public
- 9:32:19void rebind binding and and we receive a
- 9:32:24binding now for rebinding I covered this
- 9:32:27in detail in the dedicated input system
- 9:32:29video first basically we need to disable
- 9:32:31the action map so let's go into the
- 9:32:33player input actions let's access the
- 9:32:35player and disable it so we need to do
- 9:32:37this first then we're going to need to
- 9:32:39find the actions so player input actions
- 9:32:42and for now let's go into the player and
- 9:32:44let's just modify the move up action so
- 9:32:47we're going to call the function perform
- 9:32:49interactive
- 9:32:50rebinding this one as you can see it
- 9:32:52takes a binding index and if we remember
- 9:32:54up here we saw that in order to modify
- 9:32:56the move up it's on bindings index one
- 9:32:59so let's modify the one on index one
- 9:33:01okay so this is the function this
- 9:33:04returns an object of this type a
- 9:33:05rebinding operation this is a pretty
- 9:33:08complex object where you can modify all
- 9:33:10kinds of things add a bunch of
- 9:33:11limitations and so on like for example
- 9:33:14make a key not be able to be bound to
- 9:33:15the mouse or something so there's tons
- 9:33:17and tons of options you can play with
- 9:33:19over here for the simple thing let's
- 9:33:22just add an oncomplete listener so this
- 9:33:24one takes in a callback and this will
- 9:33:26will be called whenever the interactive
- 9:33:28rebinding
- 9:33:29completes so over here let's define a
- 9:33:32Lambda so a call back and inside we have
- 9:33:34this by the way over here this is the
- 9:33:36same Lambda expression that we saw
- 9:33:38previously so exactly the same thing as
- 9:33:40this except when we have just one
- 9:33:42parentheses we don't need to add them
- 9:33:44okay so like this so then on this
- 9:33:46callback we can see all kinds of things
- 9:33:48like for example we can see the action
- 9:33:49that we just rebound this is going going
- 9:33:51to contain all the data on the rebind
- 9:33:53operation so for example let's print out
- 9:33:55the path so let's go into the action
- 9:33:58let's go into the bindings on index one
- 9:34:01and let's print out the path so let's do
- 9:34:04a debug.log
- 9:34:08and there's actually another one so
- 9:34:11let's log the path and also the override
- 9:34:14path these are two different things
- 9:34:16let's see why in a bit we do this and
- 9:34:18after we log we also need to reenable
- 9:34:20the player action map so let's go into
- 9:34:21the player input actions the player and
- 9:34:24back enable this okay so we're only
- 9:34:26going to need these settings on the
- 9:34:28rebind action then we can just call
- 9:34:30start in order to start the rebinding
- 9:34:32process okay so this should work let's
- 9:34:34just call this from the options UI so
- 9:34:36over here we have the click let's go
- 9:34:38into game input instance and let's
- 9:34:41rebind The Binding and for this one is
- 9:34:43the move
- 9:34:45up okay with this let's test okay so
- 9:34:49here if I click on the button and I
- 9:34:50click on the T e and if there go it did
- 9:34:53work so you can see that it print out
- 9:34:55the regular path that is w and the
- 9:34:57override path which is T so now if I
- 9:35:00exit out of the options go back into the
- 9:35:02game if I press W nope it does not move
- 9:35:04but if I press T yep it does move
- 9:35:07upwards okay great so we have
- 9:35:09successfully rebound this one key now
- 9:35:12here just one thing in previous versions
- 9:35:14of the input system when doing a rebind
- 9:35:17operation you need to manually dispose
- 9:35:19of this call back otherwise it would
- 9:35:20throw a memory error in the recent
- 9:35:22version that I'm using here there's no
- 9:35:24error so it seems perhaps it's no longer
- 9:35:26needed to dispose of the comback
- 9:35:27manually but still there's no harm doing
- 9:35:29it just in case over here comb back.
- 9:35:32dispose okay so with that the key
- 9:35:34rebinding is working except we have two
- 9:35:36issues the first one is that it's not
- 9:35:38very clear that it's listening for an
- 9:35:39input and the second one is that the
- 9:35:41text options also does not update so
- 9:35:44let's solve both those first let's set a
- 9:35:46visual when waiting for a key press so
- 9:35:49inside the game options UI let's create
- 9:35:50an empty game object call this the press
- 9:35:53to rebind
- 9:35:55key let's stretch it out so put it on
- 9:35:58zero on everything okay then inside
- 9:36:01let's add a UI image let's put it in
- 9:36:04black and once again let's stretch it
- 9:36:06out okay now let's also add a simple
- 9:36:10text and for text let's say press a key
- 9:36:14to rebind as usual let's put the width
- 9:36:17and height on zero put it in bold Center
- 9:36:20down the middle with no wrapping
- 9:36:22and increase the size by quite a bit
- 9:36:24okay so that's our super basic window
- 9:36:26now in the code we just want to show and
- 9:36:28hide this so let's do that and let's
- 9:36:30actually begin with this hidden by
- 9:36:31default so let's disable this object so
- 9:36:34here on the options UI let's add another
- 9:36:36serialized field it's going to be a
- 9:36:38transform for the press to rebind key
- 9:36:44transform so you have this let's make
- 9:36:46two show and hide
- 9:36:48functions so we show press to rebind
- 9:36:52key we just go into that one game object
- 9:36:55set active this one into true and
- 9:36:58another one where we set it to false so
- 9:37:00just hide and set it to false okay
- 9:37:03pretty simple let's make sure to hide
- 9:37:05this over here on our start okay just
- 9:37:08like that and for showing let's show it
- 9:37:11when we actually rebind an action so
- 9:37:13right in here but since we're going to
- 9:37:15have tons of listeners to these events
- 9:37:17let's actually make a nice separate
- 9:37:18function to handle all the rebinding
- 9:37:20logic so down here let's make a function
- 9:37:23rebind
- 9:37:25binding we receive a game input.
- 9:37:30binding and then first we show The Press
- 9:37:32rebind key and then let's go into game
- 9:37:35input access the instance and tell them
- 9:37:37to rebind the binding and pass in the
- 9:37:39same binding okay so we have this and
- 9:37:41now up here on the button event let's
- 9:37:43just call in this function okay very
- 9:37:46simple so this will work for actually
- 9:37:48showing the window but now we need to
- 9:37:50know when to hide it and for that let's
- 9:37:53use something that we've used a few
- 9:37:54times in this course but never directly
- 9:37:56let's use a c delegate as usual I have a
- 9:37:59dedicated video on them this is
- 9:38:01basically how you can define a field or
- 9:38:02a parameter of a type which can hold a
- 9:38:05function it's another Super useful C
- 9:38:07feature definitely watch that video to
- 9:38:09learn all about it let's go here on the
- 9:38:11game input and down here when we have
- 9:38:14our rebind binding over here let's
- 9:38:17receive a second parameter this one is
- 9:38:18going to be of type action this is one
- 9:38:20of the built in delegates it takes no
- 9:38:23parameters and returns void so this one
- 9:38:25is perfect for a simple callback just
- 9:38:26like this one let's call it on action
- 9:38:29rebound and we're going to trigger this
- 9:38:31right here after we achieve the comback
- 9:38:33so we get the comback let's trigger this
- 9:38:35just like that and let's also get rid of
- 9:38:37these testing logs we no longer need
- 9:38:39them so just like this now back here on
- 9:38:41the options UI so we've got that and for
- 9:38:44the second parameter let's just pass in
- 9:38:46the function to hide that window so hide
- 9:38:49the Press rebind key that's it
- 9:38:51again remember we're passing in the
- 9:38:53function itself we're not calling it so
- 9:38:55there's no parenthesis we're just
- 9:38:57passing in the function itself okay so
- 9:38:59with this let's test so here on the
- 9:39:01options let's rebind the move W and
- 9:39:03there you go it does show up the window
- 9:39:05and now if I press the key y there you
- 9:39:06go that one hides okay great so this is
- 9:39:08working but over here the text is still
- 9:39:10not updating so over here on the second
- 9:39:12callback instead of just calling this
- 9:39:14function we need to call this and then
- 9:39:16also call the update visual function so
- 9:39:19as usual let's use a simple Lambda
- 9:39:20expression to do exactly both so let's
- 9:39:23open and close the
- 9:39:24parenthesis and we do exactly
- 9:39:27this so we hide the press rebind and
- 9:39:30then we update the visual okay that's it
- 9:39:32let's test so here we are let's rebind
- 9:39:34the move W press on the T key and there
- 9:39:36you go it did rebind and it did update
- 9:39:39all right great now let's just apply
- 9:39:41this to all of the other bindings so
- 9:39:43first up here on the buttons let's set
- 9:39:45listeners to all the buttons so that's
- 9:39:47the move left actually the move down
- 9:39:51then the move left move right the
- 9:39:55interact button the interact alternate
- 9:39:58button and finally the pause button and
- 9:40:01for the bindings this one is the pause
- 9:40:03binding the interact alternate then the
- 9:40:06interact then the move this one is the
- 9:40:09right again make sure you don't make
- 9:40:11mistakes here you call in the exact same
- 9:40:13one so they move down okay so all of it
- 9:40:16is correct here and now over here on the
- 9:40:18player input let's do a switch on our
- 9:40:20bind
- 9:40:30so case move up we do something and now
- 9:40:32we could write this code directly up
- 9:40:34here and then make a move down and write
- 9:40:37a bunch more code that would work but
- 9:40:38that would be way too worthy so let's
- 9:40:41write our code in a nice clean way
- 9:40:43basically the only thing we need down
- 9:40:44here is we need to know the actual
- 9:40:46action we're going to rebind and we need
- 9:40:48to know the action index so let's just
- 9:40:50find up here exactly that so an input
- 9:40:52action for the input action and then an
- 9:40:55in for The Binding index okay and then
- 9:40:58over here when we have the switch for
- 9:40:59all of our bindings we just set those so
- 9:41:01the input action in this case it's going
- 9:41:04to be the player input actions player
- 9:41:07and it's the move action and for The
- 9:41:09Binding Index this one is on index one
- 9:41:13then we're going to have the other moves
- 9:41:15so the move down is going to be on index
- 9:41:18two then left and right
- 9:41:25these are on index three and four okay
- 9:41:28so we have all these and now for the
- 9:41:29other ones so for the interact this is
- 9:41:32the interact action on binding zero then
- 9:41:35we've got the interact alternate and the
- 9:41:37pause so interact alternate and the
- 9:41:41pause and this one is the pause action
- 9:41:43and the interact alternate action and
- 9:41:45all of them are in binding index of zero
- 9:41:47okay so that's good so over here we are
- 9:41:49assigning the input action in The
- 9:41:50Binding index and also one thing we need
- 9:41:52to make sure to always assign these
- 9:41:54values so let's make sure to add a
- 9:41:56default here just make sure it always
- 9:41:58works okay great so now down here
- 9:42:00instead of always accessing the move
- 9:42:02let's access whatever is stored on the
- 9:42:03input
- 9:42:04action and for The Binding whatever it
- 9:42:06is on The Binding index okay so now this
- 9:42:09will work with all of our bindings so
- 9:42:11here we are and let's try rebinding all
- 9:42:13of them so let's put them over here on
- 9:42:14the side so before the move up let's put
- 9:42:16it on T down on G A on F then D on H for
- 9:42:21the interact on y interact out on J and
- 9:42:26for the Escape let's put it on E okay so
- 9:42:28all these Keys have been rebound let's
- 9:42:30just make sure they work so here I am
- 9:42:32moving with these keys and yep it does
- 9:42:33work go up here to interact and do the
- 9:42:35alt interact and now the pause and Y
- 9:42:38there you go everything works perfectly
- 9:42:40all right awesome so everything worked
- 9:42:42perfectly although again we have the
- 9:42:44same issue as previously so all the keys
- 9:42:46have been rebound so it's all correct
- 9:42:48great however now if I stop playing and
- 9:42:50now now if I play again and nope there's
- 9:42:53the issue the rebinding was lost so just
- 9:42:56like with the sound we also need to save
- 9:42:58the new state now thankfully the new
- 9:43:00input system has a function that makes
- 9:43:02that super easy let's go down to where
- 9:43:04we are rebinding things and when we
- 9:43:06finish rebinding let's just go into the
- 9:43:08player input actions and let's call this
- 9:43:11function the save bindings overrides as
- 9:43:14Json this one is going to return return
- 9:43:16a Json string now if you don't know what
- 9:43:19is Json go watch my quick video on it
- 9:43:21basically it's a super easy to
- 9:43:23understand and widely used file format
- 9:43:25it's very easy to read and modify it's a
- 9:43:28format where it sort of as just text so
- 9:43:30let's look at what this says let's do a
- 9:43:32debug. log over here after rebinding
- 9:43:34something let's see so here if I rebind
- 9:43:37one of these and if there you go there
- 9:43:39we have our Json so the override
- 9:43:41Bindings that overload the move on this
- 9:43:43ID on this new path so basically we just
- 9:43:46need to store this string somewhere and
- 9:43:48just like we did with the sound let's
- 9:43:49just store it in the player press
- 9:43:51so first let's define our constant so
- 9:43:54private constraint for the player preps
- 9:43:59bindings and let's call this the input
- 9:44:03bindings okay just like
- 9:44:06this so then down here after we rebind
- 9:44:09the key let's go into player prefs and
- 9:44:12let's set a string on the player
- 9:44:16preps bindings and we're going to save
- 9:44:19the overrides as Json
- 9:44:23and after we do let's just make sure the
- 9:44:24player preps is correctly saved okay so
- 9:44:26that saves it then let's go on awake to
- 9:44:29load it so over here on awake let's load
- 9:44:32that let's first do a quick test to see
- 9:44:34if there's a save so if the player preps
- 9:44:38if it has a key and if it has this
- 9:44:41key if so then let's get it so the
- 9:44:44player preps let's get the string on
- 9:44:47this key that Returns the string and
- 9:44:49we're going to use the string let's just
- 9:44:50go to the player input actions and let's
- 9:44:53call the function load binding overrides
- 9:44:55from Json just like this and also let's
- 9:44:58make sure we do this right after we
- 9:45:00construct the object and before we
- 9:45:01enable the action map okay so that's
- 9:45:04really it let's test so here we are
- 9:45:06let's rebind the move up to T okay it
- 9:45:08rebound now stop playing now play again
- 9:45:12and Y here it is still rebound to T all
- 9:45:14right awesome okay so here we created a
- 9:45:17really nice options menu where we can
- 9:45:19modify the volume and rebind
- 9:45:21the only issue that we still have is
- 9:45:23that we can only navigate the menus with
- 9:45:24the mouse so let's add support for menu
- 9:45:27navigation with a controller in the next
- 9:45:29lecture hello and welcome I'm your Cod
- 9:45:32monkey in this lecture we're going to
- 9:45:33set up full controller support for our
- 9:45:35game including regular actions and menu
- 9:45:38navigation okay so first let's just set
- 9:45:40up the controller inputs I have an Xbox
- 9:45:42Gamepad controller connected so let's
- 9:45:45open up our player input actions and
- 9:45:47over here we have all of our actions and
- 9:45:49we already made the move one long time
- 9:45:51ago so let's just add the bindings for
- 9:45:53the other ones for example over here on
- 9:45:54the interact let's add a brand new
- 9:45:56binding let's go into the path and
- 9:45:58listen and for interact I'm going to
- 9:46:00press the a button and again here you
- 9:46:03can specify just the a button on Xbox
- 9:46:05controller or you can use the generic
- 9:46:06South button which will mean a on an
- 9:46:08Xbox or cross on a PlayStation or B on a
- 9:46:11switch or anything else so let's go with
- 9:46:14the generic one for the internal
- 9:46:16alternate let's add a binding and for
- 9:46:18this one I'm going to put it on the X on
- 9:46:19the Xbox so the button West and for the
- 9:46:22pause let's add let's listen and I'm
- 9:46:24going to press the menu which is the
- 9:46:26start button okay so these are the basic
- 9:46:29inputs let's make sure they work and
- 9:46:31thanks to this new input system we
- 9:46:33really don't need to modify any code
- 9:46:35let's just save this asset let's wait
- 9:46:37for the compilation and then we can do a
- 9:46:39test so here we are and yep I'm using my
- 9:46:42controller to move now let's just wait
- 9:46:43for the countdown and go up there and
- 9:46:46pick up a cheese put it and slice some
- 9:46:48cheese yep I can do that pick up a plate
- 9:46:50and so on all right so everything works
- 9:46:52let's also pause and yep that also works
- 9:46:54okay great so everything works except
- 9:46:57there are two issues with the game pad
- 9:46:59especially one with the movement that I
- 9:47:01only noticed just now the first issue
- 9:47:03that we have is the dead zone right now
- 9:47:05we don't have one so if I just slly
- 9:47:07touch my Gamepad joystick there you go
- 9:47:09it starts moving automatically in game
- 9:47:11pad games you should always have some
- 9:47:12kind of dead zone to prevent any kind of
- 9:47:14joycon drift thankfully that is super
- 9:47:16easy to solve let's just go into the
- 9:47:17player input actions let's go into the
- 9:47:19move find the left stick bind finding
- 9:47:21and over here for the processors let's
- 9:47:23add one and let's add a stake dead zone
- 9:47:26so that's it pretty simple this
- 9:47:28basically considers that inputs under
- 9:47:29this minimum to be zero and above this
- 9:47:32maximum to be one so if you have
- 9:47:34joystick drift where when the joystick
- 9:47:36is Idle it's always moving by say 01
- 9:47:38then Direction this helps solve that
- 9:47:40problem except in our case for our game
- 9:47:42we're only using normalized inputs so
- 9:47:45actually for our use case let's increase
- 9:47:46the minimum by quite a bit I did some
- 9:47:48testing and 05 Works quite great and the
- 9:47:51max at default that is just fine okay so
- 9:47:54that's it one problem solved let's just
- 9:47:56go ahead save this ENT now the other
- 9:47:58bigger issue that we have is if I
- 9:48:00approach a counter and I try to look at
- 9:48:01it it's really difficult it tries moving
- 9:48:04left and right instead of actually
- 9:48:05facing the counter that's because the
- 9:48:07logic that we added a long time ago that
- 9:48:09logic to help the character controller
- 9:48:11feel better when moving on diagonals
- 9:48:12against the counter that works great for
- 9:48:15keyboard because it's digital so it's
- 9:48:17either moving fully left fully right or
- 9:48:19on the diagonals but it messes up the
- 9:48:21controller which is analog on the player
- 9:48:23movement if we are not moving perfectly
- 9:48:25up or perfectly down then it's
- 9:48:26considered a diagonal and on the game
- 9:48:28pad it's really difficult to get a
- 9:48:30perfect just up or just down input we're
- 9:48:32always going to have a tiny bit of
- 9:48:34either left or right so that's the issue
- 9:48:36that we have here and thankfully the
- 9:48:37solution is actually pretty simple let's
- 9:48:39go over here onto our player script and
- 9:48:42let's scroll down into the handle
- 9:48:43movement function okay so we're doing a
- 9:48:45can move using the regular move
- 9:48:47Direction and if it doesn't work then
- 9:48:48it's over here that we are attempting
- 9:48:50only the X movement or only The Zed
- 9:48:52movement and for doing that we made it
- 9:48:54so we can move if there's nothing only
- 9:48:56on the X and if we have any movement at
- 9:48:59all on the X so if it is different from
- 9:49:01zero basically the issue here is if the
- 9:49:03move de. X is let's say 0.1 that is
- 9:49:06still different from zero so it is still
- 9:49:07going to trigger this logic so basically
- 9:49:10let's just widen this Gap instead of
- 9:49:11testing literally just different from
- 9:49:13zero let's test if they move here. X if
- 9:49:16it is under say minus5 F or if move thex
- 9:49:22if it is bigger than plus5 F so instead
- 9:49:25of being exactly just on zero we're only
- 9:49:27going to consider diagonals if we are at
- 9:49:29least moving 05 either left or right so
- 9:49:32we just do this and same thing over here
- 9:49:33except we just test for the Zed so the
- 9:49:35move the. Z and the move the. Z okay so
- 9:49:39like this it should feel much better on
- 9:49:41the GamePad and still work exactly the
- 9:49:42same on the keyboard so let's test so
- 9:49:45here I am moving around and yep now it
- 9:49:47is much easier to just stay around and
- 9:49:49look straight at a counter
- 9:49:51okay so that's great so I can pick up
- 9:49:52and this is all much much easier and the
- 9:49:54character is no longer just sliding left
- 9:49:56and right non-stop okay that's great so
- 9:49:59now that this is working let's set
- 9:50:01support for rebinding our controller
- 9:50:03bindings so over here on the game input
- 9:50:05let's do it just like we did for the
- 9:50:07keyboard so let's add a bunch more
- 9:50:08bindings over here on the enum let's add
- 9:50:10the GamePad interact then the GamePad
- 9:50:13interact alternate and then the GamePad
- 9:50:17pause okay so we have our bindings then
- 9:50:20let's let's go down and add them to both
- 9:50:21our functions so first the text and then
- 9:50:23the bindings so over here on the text
- 9:50:25let's copy pretty much this we're going
- 9:50:27to have the GamePad interact then we're
- 9:50:30going to have the other two so the
- 9:50:32GamePad interact alternate and the
- 9:50:34GamePad pa okay now for these bindings
- 9:50:37we're going to use the same actions so
- 9:50:39this one is the interact alternate and
- 9:50:41over here we have the interact and over
- 9:50:43here on the input actions we saw that we
- 9:50:45added for all of them on index zero we
- 9:50:47have the keyboard and on index one we
- 9:50:49have all the game pads so over here
- 9:50:51that's literally the only change for the
- 9:50:53game pad let's go into bindings and
- 9:50:54access the array on index one okay and
- 9:50:58then over here on the rebind binding
- 9:50:59it's going to be pretty much the exact
- 9:51:01same thing so let's copy all these
- 9:51:03change this to the game pad interact
- 9:51:06then the GamePad interact alternate and
- 9:51:08then the GamePad pause so all these all
- 9:51:12we need to change is just buy an index
- 9:51:13put them all on one okay so with that
- 9:51:16all the code over here on the game input
- 9:51:18is working perfectly now let's go over
- 9:51:20here into options UI so we've got all of
- 9:51:22our buttons so let's duplicate our
- 9:51:24buttons let's just go into the interact
- 9:51:26the pause and so on let's duplicate push
- 9:51:28them to the right side okay and just
- 9:51:31change the name so let's go into all of
- 9:51:33them so this one is the game pad
- 9:51:35interact button then the game pad
- 9:51:38interact alternate and finally the
- 9:51:40GamePad pass okay also inside let's also
- 9:51:44rename these buttons just to make sure
- 9:51:45the text works
- 9:51:48great and let's also make sure that
- 9:51:50these show up behind the press the
- 9:51:52rebind key so let's drag them put them
- 9:51:54above okay so that's our setup over here
- 9:51:57on the options UI now let's go over here
- 9:51:59on the options UI script and let's add
- 9:52:01references to our buttons and to our
- 9:52:02text objects so let's copy all of these
- 9:52:06the game pad and add all these this is
- 9:52:08the pause the interact and the interact
- 9:52:11alternate and then down here the exact
- 9:52:13same thing let's add all of
- 9:52:17these okay like this now over here let's
- 9:52:20drag all of our references so on the
- 9:52:22options UI let's make sure to always
- 9:52:24drag the correct things so the game pad
- 9:52:27interact text the interact alternate
- 9:52:30text and the pause button text and then
- 9:52:33the buttons themselves so the pause
- 9:52:34button interact alt and the interact
- 9:52:37button again make sure you always drag
- 9:52:39the correct references so check and
- 9:52:41double check make sure everything is
- 9:52:42correct okay then over here for our code
- 9:52:45let's first handle the text over here so
- 9:52:49the text for all of these
- 9:52:51so the GamePad interact text then the
- 9:52:54GamePad interact alternate text and
- 9:52:56finally the GamePad pause text and we
- 9:52:58just go the GamePad pause the GamePad
- 9:53:01interact alternate and the GamePad
- 9:53:03interact finally over here on the
- 9:53:05buttons let's do the exact same thing so
- 9:53:08game pad interact interact alternate and
- 9:53:11the
- 9:53:14pause okay so we added everything let's
- 9:53:17do a test and see if everything is
- 9:53:18working so over here let's pause pause
- 9:53:20the game go into the options and for the
- 9:53:22interact let's modify this one instead
- 9:53:24of a let's put it on B and Y there you
- 9:53:26go it did go so let's close let's resume
- 9:53:29and now let's see so if I approach and I
- 9:53:30press a nothing happens Press B and
- 9:53:32there you go it doesn't interact okay
- 9:53:34awesome so the rebinding is all working
- 9:53:37perfectly except we have another obvious
- 9:53:40issue I can pause with the GamePad
- 9:53:42however now with this pause I cannot
- 9:53:44click on any of those buttons and if I
- 9:53:46go back to the main menu over here I
- 9:53:49also cannot do anything with a
- 9:53:50controller so let's solve that the first
- 9:53:52step is on the event system object look
- 9:53:55at how it shows us this warning
- 9:53:57basically if we're using the new input
- 9:53:58system we should be using a different
- 9:54:00input Handler here thankfully this is
- 9:54:02super easy we just need to click on this
- 9:54:03button and yep that's it it
- 9:54:05automatically sets it up now the way
- 9:54:07that this works is by pre-selecting
- 9:54:09buttons and in order to better see which
- 9:54:11button is selected we should probably
- 9:54:12add a more visible color let's go into
- 9:54:15our pause window so for now let's hide
- 9:54:17over here the options UI show the pause
- 9:54:19window and we have these three buttons
- 9:54:21let's select all of them and over here
- 9:54:24on the right side on the button we can
- 9:54:26see one option for the selected color so
- 9:54:29instead of being white which is going to
- 9:54:30be really difficult to see let's put
- 9:54:32something really visible so let's say
- 9:54:34like a bright green okay like this let's
- 9:54:37do the same thing for all the buttons on
- 9:54:39the options UI so let's show this one
- 9:54:41and find all the buttons so we've got
- 9:54:44all of these ones down here and these
- 9:54:47three ones up here and let's do the same
- 9:54:49thing so on the select Ed let's put it
- 9:54:51all on a nice screen okay so all the
- 9:54:53buttons have a nice selected color and
- 9:54:55just like this if we test and if I pause
- 9:54:58the game and right now nothing is
- 9:55:00selected so right now I cannot do
- 9:55:02anything with the controller however if
- 9:55:04I press over here with the mouse on this
- 9:55:06button and that let go whilst outside
- 9:55:08the button yep look at that now that
- 9:55:10button is selected so now as long as
- 9:55:12that one is selected now if I move with
- 9:55:14the mouse pad yep now I can navigate
- 9:55:16through this menu and if I press on a
- 9:55:18yep I can essentially click that button
- 9:55:20so that's great basically all we need is
- 9:55:22to make sure that we select a button as
- 9:55:24soon as the pause menu shows up so let's
- 9:55:26go over here on the game pause UI script
- 9:55:28and then over here let's go into the
- 9:55:30show function so when we show this
- 9:55:31window when we do let's go into the
- 9:55:33resume button and just call the select
- 9:55:35function this will make it selected so
- 9:55:37that's it and with this if we test and
- 9:55:39now here with the game playing if I
- 9:55:41pause whilst pressing the button on the
- 9:55:43game pad and if there you go that one is
- 9:55:45selected and now I can select any option
- 9:55:47okay that's great so now it works fully
- 9:55:49with just the game pad except now if I
- 9:55:52go into options yep now you can see that
- 9:55:54the button that is selected is still the
- 9:55:56options one over there on the background
- 9:55:57so let's also make sure to select a
- 9:55:59button on the options as soon as the
- 9:56:00options window shows up so over here on
- 9:56:02the options UI let's go into our show
- 9:56:05function and let's just select the sound
- 9:56:07effects button and just call Select okay
- 9:56:10let's test so here let's pause go into
- 9:56:13options select any of there go that did
- 9:56:14work okay great except we have another
- 9:56:17issue as I move upward down over over
- 9:56:20here on these buttons yep look that some
- 9:56:22of them are a bit strange like for
- 9:56:24example over here on a I'm moving up and
- 9:56:27look at that it actually selected the
- 9:56:29resume button behind it so as we are
- 9:56:31moving upward and down we are actually
- 9:56:33selecting buttons on both menus that's
- 9:56:36very strange basically what is going on
- 9:56:38is that since both windows are visible
- 9:56:40the game is trying to guess which button
- 9:56:42we want to select basically what is
- 9:56:44happening is Unity is trying to use
- 9:56:46automatic navigation if we select a
- 9:56:48button so let's go for for example let's
- 9:56:50hide the options and show just the game
- 9:56:54pause okay let's select one of these
- 9:56:55buttons and over there on the button
- 9:56:57component we can see navigation is set
- 9:56:59to automatic and we have a button to
- 9:57:01visualize and if we click on that yep
- 9:57:03over here we can see all kinds of arrows
- 9:57:05for example we can see one over here on
- 9:57:07the options that seems to be going to
- 9:57:09some button in there that is going to be
- 9:57:11the button that is showing over there so
- 9:57:13if we move down from the options we're
- 9:57:15going to end up over here on the
- 9:57:16interact alt button now usually the
- 9:57:19automatic navigation actually works very
- 9:57:21well the only reason why we're having
- 9:57:23problems is because we have both windows
- 9:57:25active at once one solution to this is
- 9:57:27to make the navigation explicit so let's
- 9:57:29hide the options here and over here on
- 9:57:31the resume on the navigation instead of
- 9:57:33automatic let's put none and then let's
- 9:57:35select explicit and if now we have all
- 9:57:38four Fields so we can decide which
- 9:57:40object get selected when we are here and
- 9:57:42we move up down left or right so for
- 9:57:44example here we would drag for the up
- 9:57:47going up we could go into the main menu
- 9:57:48so we would drag that button button and
- 9:57:50going down we could drag the options
- 9:57:52button so that's one solution just add
- 9:57:54the explicit navigation to every single
- 9:57:56button or another simpler solution is
- 9:57:59let's leave this one on automatic and in
- 9:58:02said we're just going to hide the pause
- 9:58:03window whilst we are in the options
- 9:58:05window so over here on the game pause UI
- 9:58:08let's see over here we are showing the
- 9:58:10options UI and when we do let's just
- 9:58:12call hide on this so we are going to
- 9:58:14hide this window when we show the
- 9:58:15options and then on the options we want
- 9:58:18to know when the options load so that we
- 9:58:20can show this one again so over here on
- 9:58:22the show function let's receive an
- 9:58:25action this is what we're going to do
- 9:58:27when we close the options let's call it
- 9:58:29on close button
- 9:58:31action and let's store it up here so
- 9:58:34let's store a simple private action for
- 9:58:37this okay so we have this and then down
- 9:58:40here when we have our show function when
- 9:58:43we have let's set this equals this we
- 9:58:44store this and then we're just going to
- 9:58:46run this action whenever we click on the
- 9:58:48close button so let's go over here the
- 9:58:50close button we've got that one let's
- 9:58:52hide the options window and Trigger this
- 9:58:54action so now we need is over here on
- 9:58:56the game pause y let's pass in and
- 9:58:58basically when we close the options UI
- 9:59:01we want to show the pause UI okay so
- 9:59:04let's test so here we are let's pause
- 9:59:06the game okay let's go into options and
- 9:59:07open it and if there you go it only
- 9:59:09shows the options and over here moving
- 9:59:11up or down works perfectly and moving
- 9:59:13left and right also works perfectly and
- 9:59:15now if I want to go back let's go into
- 9:59:17close press it and there you go back
- 9:59:19into the pause menu
- 9:59:20all right awesome so everything is
- 9:59:22working perfectly now the last thing we
- 9:59:24need is over here on the main menu so
- 9:59:26let's do the same thing first let's open
- 9:59:28up the main menu scene let's save the
- 9:59:31changes okay and over here let's begin
- 9:59:33by doing the same thing on the event
- 9:59:34system so let's replace it okay great
- 9:59:37then let's go inside our canvas inside
- 9:59:39main menu y let's select our buttons and
- 9:59:43once again let's modify the select color
- 9:59:45put it on nice green all right and since
- 9:59:47over here we only have one menu we could
- 9:59:50set it as selected over here on the main
- 9:59:52menu y script that's one option or we
- 9:59:55can just go into the event system and
- 9:59:57over here on the event system there's a
- 9:59:58field for the first selected so we can
- 10:00:01just drag the play button and that will
- 10:00:03automatically make it the selected one
- 10:00:04so let's test and yep the play button
- 10:00:07starts off as selected and I can move up
- 10:00:09or down and if I press a button yep
- 10:00:12there you go here I am playing the game
- 10:00:13I can pause I can resume go back to the
- 10:00:15main menu and so on all right awesome so
- 10:00:18here we have the final thing we needed
- 10:00:19to make our game fully playable with the
- 10:00:21game pad thanks to how the input system
- 10:00:23works and the menu automatic navigation
- 10:00:25this was a pretty simple task with this
- 10:00:28our game is pretty much completely done
- 10:00:30however the next lecture is also one of
- 10:00:31the most important lectures it's all
- 10:00:33about polish so let's do that in the
- 10:00:35next
- 10:00:36lecture hello and welcome I'm your code
- 10:00:38Mak in this lecture we're going to add
- 10:00:41all kinds of small things to polish up
- 10:00:43our game if you're a regular on this
- 10:00:45channel then you've certainly heard me
- 10:00:46say that polish is what separates good
- 10:00:48games from great games so as you build
- 10:00:50your own games make sure you don't
- 10:00:51neglect polish here let's add a bunch of
- 10:00:54small tiny things that will make a big
- 10:00:56difference in the final game let's begin
- 10:00:58with a very simple very visual one let's
- 10:01:01just add some walls to our map and first
- 10:01:03let's just hide our canvas so that it's
- 10:01:05not blocking our view so again over here
- 10:01:07we can use the buttons on the hierar key
- 10:01:09to hide it okay great so let's add some
- 10:01:11walls and for that let's create a brand
- 10:01:14new 3D cube let's name this a wall let's
- 10:01:18put it quite a bit thin so over here on
- 10:01:19the scale for the X let's put it 0 25
- 10:01:22then on the Y let's put three so
- 10:01:24something like this then we modify the Z
- 10:01:26so let's put it over here on the side
- 10:01:29right next to the counters okay so
- 10:01:30that's the wall let's just stretch it
- 10:01:32out One Direction and the other one okay
- 10:01:36so that's our basic wall now in included
- 10:01:39project files there's a nice wall
- 10:01:40material so let's go over here into
- 10:01:41assets under materials and Y here does a
- 10:01:44wall material so let's just drag it and
- 10:01:46use this one and there you go it's just
- 10:01:47a nice simple gradient this is also an
- 10:01:50example of how you can take something
- 10:01:51simple and make it a bit more
- 10:01:53interesting if you look at this material
- 10:01:55the base texture is really just this it
- 10:01:57is literally just a simple vertical
- 10:02:00gradient texture and then with a color
- 10:02:02apply to it and looks pretty good okay
- 10:02:04so this Dall let's put the wall on all
- 10:02:06three sides so let's duplicate this so
- 10:02:08just select and press control D
- 10:02:10duplicate let's put one on the other
- 10:02:12side so right there right next to the
- 10:02:15counters okay and finally the one there
- 10:02:17so contrl D to duplicate it let's push
- 10:02:19it over there on the side and rotate at
- 10:02:2290° and let's put it just like that
- 10:02:25let's just scale it to get to that end
- 10:02:28and to get to that end okay so we have
- 10:02:30our nice walls but over here if we're
- 10:02:33playing the game we can still see the
- 10:02:34floor on the outside that looks a bit
- 10:02:36ugly so let's fix that let's create
- 10:02:39another object and let's create a 3D
- 10:02:41object another Cube and for this Cube
- 10:02:43let's put it over here on the side and
- 10:02:45this one let's use the black material so
- 10:02:47again in the included assets there's
- 10:02:49this nice black material there you go
- 10:02:51it's completely black nothing to it so
- 10:02:53let's just use this as kind of a Hider
- 10:02:55so let's just scale it quite a bit and
- 10:02:58lift it
- 10:03:01up okay so there it is a black material
- 10:03:04right next to the wall and let's put
- 10:03:06another one over here on the left side
- 10:03:09and just like that can also put another
- 10:03:11one on the back there even though I
- 10:03:13don't think the camera can see that part
- 10:03:14but still let's put it so just put it
- 10:03:17like that and stretch it out okay that's
- 10:03:20good by the way over here on the outside
- 10:03:22it doesn't have to be perfect doesn't
- 10:03:24have to perfectly match the camera is
- 10:03:25never going to see that position so it
- 10:03:27doesn't matter it only matters what the
- 10:03:29camera can see and if we play like this
- 10:03:32and if there you go now that looks quite
- 10:03:34nice if we want over there we can get it
- 10:03:36together just a little bit and we can
- 10:03:38also move the camera forward a tiny bit
- 10:03:41so over here on this one let's push it
- 10:03:44just a little bit to the left okay and
- 10:03:46now in the virtual camera let's play the
- 10:03:48game and now here if we want we can push
- 10:03:51it up a little bit something like this
- 10:03:53so let's put it on this Zed so let's
- 10:03:55copy it stop playing the game and let's
- 10:03:58space it just like that okay so here's
- 10:04:01our game and as you can see with just
- 10:04:03this one tiny change just adding some
- 10:04:04walls and a nice black outside just with
- 10:04:07that it already looks so much better
- 10:04:08than having some counters in wide open
- 10:04:10space now for another simple one let's
- 10:04:13add some nice particles while the player
- 10:04:14is moving so in the included assets if
- 10:04:17we go inside the prefab visuals over
- 10:04:19here is a nice one for player moving
- 10:04:21particles this one as you can see is a
- 10:04:23particle system so let's drag it over
- 10:04:25here into the world to see what it looks
- 10:04:27like and as you can see by default it's
- 10:04:29actually not spawning anything so I can
- 10:04:31make sure that this one is running and
- 10:04:32nope nothing is spawning so this is
- 10:04:34actually set up in a really interesting
- 10:04:36way is that instead of spawning
- 10:04:37particles all the time it only emits
- 10:04:39while moving so if I click to move this
- 10:04:41object there you go the particles start
- 10:04:43emitting and if I stop they stop so this
- 10:04:46one is definitely perfect for a player
- 10:04:48particle system do this set up is over
- 10:04:50here on the emission on rate over time
- 10:04:53it is set to zero so it doesn't spawn
- 10:04:55anything automatically and it only has
- 10:04:57over here the rate over distance so as
- 10:04:59it moves it's going to spawn that number
- 10:05:00of particles then the other settings
- 10:05:02they're all pretty basic so there's some
- 10:05:05gravity so they fall down just like the
- 10:05:07stove counter particles the simulation
- 10:05:10is over here on space so that as I move
- 10:05:11the particles stay behind this is
- 10:05:13important if I were to put that in local
- 10:05:15and I move it around look at that this
- 10:05:17is not what we want we want the
- 10:05:19particles to essentially stay behind
- 10:05:20instead of following this transform so
- 10:05:22that is why this change is super
- 10:05:24important if that one is set to whirl
- 10:05:26and as I move yep the particle stay
- 10:05:27behind okay great and the other
- 10:05:30properties are all pretty basic for the
- 10:05:32shape it's a cone pointing upwards then
- 10:05:34for the size of our lifetime again just
- 10:05:36a basic curve constantly becoming
- 10:05:38smaller and smaller and down here on the
- 10:05:40renderer instead of rendering a quad
- 10:05:42it's actually rendering a mesh and it's
- 10:05:44rendering a sphere mesh so that is just
- 10:05:46so that it looks a little bit better I
- 10:05:48think than just having a Sprite particle
- 10:05:50okay so that's it so in order to make
- 10:05:52this work really all we need is just
- 10:05:53attach it to the player so let's find
- 10:05:56the player make this object a child of
- 10:05:58the player game object and again let's
- 10:06:00also make sure to set all of this to
- 10:06:02zero so the position on z0 and
- 10:06:05zero and there you go just with this
- 10:06:07that's all we need if we test here we
- 10:06:09are sto and there are no particles and
- 10:06:11as I start moving y there you go some
- 10:06:12nice particles around the player okay
- 10:06:15great next let's set a pretty obvious
- 10:06:17one some kind of mini tutorial
- 10:06:20we want a window to show the controls
- 10:06:22and the goal of the game and wait for
- 10:06:23the player input before we start the
- 10:06:25countdown so for that let's go into our
- 10:06:27canvas so let's show our canvas and
- 10:06:31inside let's create an empty game object
- 10:06:33call the tutorial UI let's drag this one
- 10:06:36above the game pause window so that it
- 10:06:38shows up behind it let's double click to
- 10:06:40center it and let's press on the 2D
- 10:06:42button to go into Tod mode okay let's
- 10:06:45also hide those two windows so we can
- 10:06:47actually see what we're doing so let's
- 10:06:48hide all of these okay okay great now
- 10:06:50this one first of all let's stretch it
- 10:06:52to occupy everything so put zero on
- 10:06:54everything okay then inside let's make a
- 10:06:57UI image for our background once again
- 10:07:01let's stretch it put it like this and
- 10:07:04for this one instead of black like we've
- 10:07:06used for all of our Windows let's
- 10:07:07actually leave it on white put it on an
- 10:07:09alpha something like half so something
- 10:07:11like this just to be a bit different
- 10:07:13then on top of this let's make another
- 10:07:14image so let's make another UI image and
- 10:07:17for this one instead of stretching let's
- 10:07:18give it a size so let's put it on 1280
- 10:07:20by 800 and for the image I created a
- 10:07:24nice image for the tutorial if we go
- 10:07:26inside the assets and then inside
- 10:07:28textures yep here is a really nice
- 10:07:30tutorial image so let's just go ahead
- 10:07:33and use it so on the image let's drag it
- 10:07:35all right there's our nice tutorial
- 10:07:37image so this has a pretty basic
- 10:07:39tutorial so the recipes come in from the
- 10:07:41customers then the player has to prepare
- 10:07:42the correct recipes and deliver them on
- 10:07:44a plate on the delivery counter so just
- 10:07:46a very basic tutorial and also over here
- 10:07:49it's very important for the player to
- 10:07:51know how to actually play the game so
- 10:07:53there's some labels for the controls and
- 10:07:55now we're going to dynamically add some
- 10:07:56keys on top so let's do that let's
- 10:07:58create an empty game object call this
- 10:08:01the key let's put it on a size of 40x 40
- 10:08:05okay now let's go inside and inside
- 10:08:08let's make an image let's name this the
- 10:08:12background and for the Sprite let's go
- 10:08:15with the included Circle so default
- 10:08:17Circle and for the size let's stretch it
- 10:08:20to occupy everything put it on 0 0 0
- 10:08:23okay there's our nice key so we have the
- 10:08:26background and for the background let's
- 10:08:28actually make it just a little bit
- 10:08:30darker and let's also add just a nice
- 10:08:32shadow so maybe 3 minus 3 and let's also
- 10:08:36make a nice outline let's put it on 2x
- 10:08:40two full Alpha so something like this
- 10:08:42just to be a nice one maybe one by one
- 10:08:45okay so that's just the visual and then
- 10:08:47on top of it let's add a text
- 10:08:49and this one essentially going to be the
- 10:08:51key so let's put a key for the width and
- 10:08:53height let's stretch it to match the
- 10:08:56parent size okay then for the font here
- 10:08:59let's go with maybe just say 20 let's
- 10:09:01put it Center down the middle and also
- 10:09:03let's put it on Bold okay so that's our
- 10:09:05nice key indicator so this is our key
- 10:09:09and we're going to have the movement so
- 10:09:11the movement on the keyboard is going to
- 10:09:12have four keys so let's just duplicate
- 10:09:14so one two three and four Keys okay then
- 10:09:19on the game pad that one is actually not
- 10:09:21rebindable so let's put this one as
- 10:09:23static so let's just go inside inside
- 10:09:27the text and just say left stick and
- 10:09:30let's lower the font size so that it
- 10:09:32fits in there okay great then for some
- 10:09:34more keys we're going to have the
- 10:09:37interact action then the interact
- 10:09:40alternate and finally the pause action
- 10:09:43then let's just duplicate these to be on
- 10:09:45the other side
- 10:09:52okay so these are all of our keys now
- 10:09:55instead of having key 1 two three this
- 10:09:56is very difficult to understand so let's
- 10:09:58give it some proper names so this is the
- 10:10:00key move up then we have the key move
- 10:10:04down then the key move left then the key
- 10:10:08move right then this one is going to be
- 10:10:11the key Gamepad move then we have the
- 10:10:15key
- 10:10:16interact the key interact
- 10:10:20alternate the key pause this one is the
- 10:10:23key Gamepad interact
- 10:10:27alternate this one is the key Gamepad
- 10:10:30interact and finally the key Gamepad
- 10:10:35pause okay all of these and since we're
- 10:10:37going to drag references to the text
- 10:10:39objects let's also give those a name so
- 10:10:42just copy drop it with text just like
- 10:10:46this
- 10:10:51okay so those are all the names so
- 10:10:53everything is nice and organized okay
- 10:10:55great now let's make the script to run
- 10:10:57this so our tutorial UI let's go down
- 10:10:59into our UI scripts create a brand new C
- 10:11:02script for the tutorial UI and let's
- 10:11:05attach the script okay so first let's
- 10:11:08drag references to all of our keys we
- 10:11:10only need the text so let's do a
- 10:11:12serialized field of type text mesh Pro
- 10:11:15yugui again never make the mistake
- 10:11:17always use the Yugi one if for working
- 10:11:19in the UI so the key move of text so
- 10:11:23let's add all of
- 10:11:27these okay these are all the references
- 10:11:30then over here let's drag all and make
- 10:11:32sure to drag the correct
- 10:11:37ones okay let's double check to make
- 10:11:39sure all the references are correct okay
- 10:11:41they all seem correct all right great
- 10:11:43and then over here let to pretty much
- 10:11:45exactly the same thing that we did over
- 10:11:46here on the options so we need EX only
- 10:11:49this so let's copy this and over here
- 10:11:52let's do just that let's do a private
- 10:11:55void update
- 10:11:56Visual and on this one let's do pretty
- 10:11:59much this so the key move up text and on
- 10:12:02this one you get binding text of move up
- 10:12:04yep let's just do all the
- 10:12:15others okay so those are all the
- 10:12:17bindings that's great now let's let's go
- 10:12:19over here on a private void start and on
- 10:12:22start let's update our visual all right
- 10:12:25and also let's make sure this update
- 10:12:27just in case the player rebinds
- 10:12:28something from the pause menu once the
- 10:12:30tutorial is still visible so we just
- 10:12:33need to know when that happen so let's
- 10:12:34go over here onto the game input and
- 10:12:36make a nice event so public event event
- 10:12:38handler let's call it on binding
- 10:12:42rebind okay we have this event and down
- 10:12:45here when we have our rebind binding
- 10:12:47function we do this we rebind and over
- 10:12:49here let's invoke this
- 10:12:56event okay just like this so then on Tut
- 10:13:00y let's go into the game input the
- 10:13:03instance on binding rebind let's listen
- 10:13:06to this event and as always let's rename
- 10:13:09this so let's put it game input okay
- 10:13:12when this happens let's simply update
- 10:13:13the visual okay that's it pretty simple
- 10:13:16so let's test and see if the inputs are
- 10:13:18correct
- 10:13:19and if there it is we do see it correct
- 10:13:21so we've got was we've got e to interact
- 10:13:24F and over there we've got the game pad
- 10:13:26okay great so all the buttons are
- 10:13:28correct all that's left is the show and
- 10:13:30hide so over here let's make the usual
- 10:13:32two function so PR void show and a
- 10:13:35private void hide and for these game
- 10:13:38object set active and this one is going
- 10:13:41to be into false and this one is going
- 10:13:43to be true okay so for show up here on
- 10:13:46start let's actually show it by default
- 10:13:49even though it's actually already going
- 10:13:50to be shown but still okay then for the
- 10:13:53hide this one we want to hide when we
- 10:13:55press the interact action however when
- 10:13:58that happens we don't want just this
- 10:14:00window to hide we want the kitchen game
- 10:14:03manager to change the state so over here
- 10:14:05on the kitchen game manager we currently
- 10:14:07have the waiting to start and that one
- 10:14:09actually has a timer so we count on a
- 10:14:11timer and then we start whereas right
- 10:14:13now we want it to be based on player
- 10:14:14input so let's modify this to not be
- 10:14:17based on timer so let's just get rid of
- 10:14:18this time timer and now let's see all
- 10:14:21these errors so I'm waiting to start we
- 10:14:23are not going to count down any timers
- 10:14:25instead let's listen to the game input
- 10:14:28so game input let's listen to the on
- 10:14:31interact action event and rename this to
- 10:14:34the game input okay so when we have this
- 10:14:38event when the player press the interact
- 10:14:40action let's check if the state if this
- 10:14:43one is on waiting to start if so then
- 10:14:46let's modify the state so let's go into
- 10:14:47State and we're going to go to the
- 10:14:49countdown to start and let's trigger the
- 10:14:51on state changed
- 10:14:57event okay so that's it so we're only
- 10:14:59going to change it on the player input
- 10:15:01and nothing over here on the update then
- 10:15:04for hiding the tutorial over here one
- 10:15:06approach would be to listen to the
- 10:15:08interact action and hide it but I think
- 10:15:10it makes more sense for this to only
- 10:15:12listen to the kitchen game manager state
- 10:15:15that way if we wanted we could also
- 10:15:16modify how this one changes the waiting
- 10:15:18to start so let's listen to the state
- 10:15:21over here on Tut one let's go into the
- 10:15:23kitchen game manager the instance and
- 10:15:25let's listen when the state
- 10:15:30changes so here we are going to check if
- 10:15:32the kitchen game manager instense if it
- 10:15:35is on the countdown to start active so
- 10:15:37if the countdown is active then we're
- 10:15:38going to hide this okay so that should
- 10:15:41do it now let's just do one more small
- 10:15:43thing the delivery manager is currently
- 10:15:46spawning a whilst we're still reading
- 10:15:47the tutorial that's not not quite right
- 10:15:50so let's go over here on the delivery
- 10:15:52manager and right now this one starts
- 10:15:54off at 0f and starts counting it down
- 10:15:56right away instead of always doing it
- 10:15:58like this let's just make sure that we
- 10:16:00only spawn a recipe if the game is
- 10:16:01playing so that's super simple over here
- 10:16:04kitchen game manager instance is game
- 10:16:06playing if so then we are going to spawn
- 10:16:09a recipe and let's do the same thing on
- 10:16:11the plates counter so let's go in the
- 10:16:14plates counter so here we are on the
- 10:16:16plates counter so we count on time
- 10:16:18respon of PL but let's also make sure we
- 10:16:20only spawn plates if the game is play
- 10:16:22okay so with all of this let's test and
- 10:16:25right away here we are we can see our
- 10:16:27nice tutorial teaching the player how to
- 10:16:28play okay great here we've got the
- 10:16:30controls everything and we're currently
- 10:16:32waiting for an interaction we can see
- 10:16:34over there plates are not being spawned
- 10:16:35and recipes are also not being spawned
- 10:16:38but as soon as I press the E key and yep
- 10:16:40there you go the countdown starts
- 10:16:41playing and we've got everything else
- 10:16:43and yep there you go the game starts and
- 10:16:45after a while yep we've got plates and
- 10:16:47we've got recipes all right awesome so
- 10:16:50next let's polish the countdown visual
- 10:16:53right now it's pretty basic it's just a
- 10:16:54static number so let's add a nice
- 10:16:56animation to it let's go inside the
- 10:16:58canvas let's find the countdown UI so
- 10:17:00the game start countdown okay so here it
- 10:17:03is we just have some basic text now
- 10:17:05let's go into the main game object and
- 10:17:07let's add an animator
- 10:17:09component then let's create a brand new
- 10:17:11animator controller so let's create a
- 10:17:13new down here an animated controller for
- 10:17:16the countdown UI over there let's assign
- 10:17:19this controller okay now let's open up
- 10:17:21the animation window so window animation
- 10:17:23open up the animation window okay let's
- 10:17:24create an animation clip and over here
- 10:17:26let's name this e countdown UI number
- 10:17:29popup okay that's great now for making
- 10:17:31the animation we want to basically make
- 10:17:33it shake and also make it fade away so
- 10:17:36one very useful component is the canvas
- 10:17:38group so over here whil on the parent
- 10:17:40let's attach a canvas group component
- 10:17:43this one is a really useful component in
- 10:17:45this case the main benefit is it lets us
- 10:17:47easily animate the alpha so let's go
- 10:17:49ahead enter on recording let's go into
- 10:17:52the frame just before 1 second so let's
- 10:17:54go into 60 frames because we are on 60
- 10:17:56frames per second over here let's record
- 10:17:58the normal key frame so let's modify the
- 10:18:01scale a tiny bit just to record it and
- 10:18:02let's reset it back to one okay just to
- 10:18:04record the key frame then for rotation
- 10:18:07let's rotate on Zed then put it on zero
- 10:18:09again just to record the key frame okay
- 10:18:11great so now we can go back into the
- 10:18:13first frame and over here let's first
- 10:18:15make it smaller so for the size let's
- 10:18:17put it on 6 then let's rotate it to the
- 10:18:20left so let's put 17 over here on this Z
- 10:18:22rotation okay like that now let's move
- 10:18:24up by just three frames so on frame
- 10:18:26three over here let's make it quite a
- 10:18:28lot bigger so let's put it on 1.3 and
- 10:18:31let's rotate it to the opposite position
- 10:18:33so minus 17 okay that's great that's a
- 10:18:36nice start now let's put it on frame 10
- 10:18:39and over here let's set the rotation to
- 10:18:41zero and for the scale put it on 1.1
- 10:18:44okay so now finally over here on frame
- 10:18:4650 let's set the alpha on 2 one and then
- 10:18:50on 1 second let's put the alpha on zero
- 10:18:52okay so let's preview and Y there you go
- 10:18:54a nice simple animation okay so that
- 10:18:57looks great now we just need to play
- 10:18:59this when the countdown happens so let's
- 10:19:01stop recording let's go inside the
- 10:19:03animator controller so here it is we've
- 10:19:05got our number pop up and we basically
- 10:19:07just want to play this animation
- 10:19:09whenever we want so let's put it and
- 10:19:11make a transition from the any state
- 10:19:13onto the number popup on this transition
- 10:19:16let's make sure we have no exit time and
- 10:19:17for the settings over here for duration
- 10:19:19let's put it on zero so that it's
- 10:19:20instant okay great now obviously we need
- 10:19:23a condition so on the parameters let's
- 10:19:25create a brand new trigger call this the
- 10:19:27number popup let's select that one and
- 10:19:30Trigger it on this trigger okay great so
- 10:19:33now for handling this logic here we have
- 10:19:36the usual question so do we put this
- 10:19:38visual Logic on the same UI script or do
- 10:19:40we separate the animations from the UI
- 10:19:43for me I find that the UI is usually
- 10:19:44part of the visual so sometimes I like
- 10:19:47to mix the two and sometimes I keep them
- 10:19:49separate it really depends on a Case by
- 10:19:51casee basis this visual is so simple and
- 10:19:53so connected to the actual UI Logics
- 10:19:55over here let's put them together so
- 10:19:57let's open up the game start countdown
- 10:19:59script and over here let's first grab
- 10:20:01the animator so private animator for the
- 10:20:03animator and on private void awake let's
- 10:20:05just get the animator and just get
- 10:20:07component of type animator okay so we
- 10:20:09have the animator now we basically just
- 10:20:12need to keep track down here where we're
- 10:20:14modifying the text we're doing this on
- 10:20:15every update but now we need to know
- 10:20:17when this number changes so let's
- 10:20:19basically just keep track of the current
- 10:20:21number and the previous number so first
- 10:20:23of all over here an in for the countdown
- 10:20:26number and we're going to get this so
- 10:20:29this is our countdown number and over
- 10:20:30here we set it to string okay and we
- 10:20:34just need to use a different function so
- 10:20:35instead of Cl let's use cl2 n just to
- 10:20:37convert the output into an integer okay
- 10:20:39great so we have the countdown number
- 10:20:42now we just need to know if this one is
- 10:20:43different from the previous one so let's
- 10:20:45go up here let's define a private ttin
- 10:20:48for the previous countdown number then
- 10:20:51when we go down here we've got the
- 10:20:53current countdown number okay then just
- 10:20:55check if it's
- 10:20:57different if it is different from the
- 10:20:59current countdown number if so then
- 10:21:01let's update it so the previous one
- 10:21:03becomes this one and now let's fire off
- 10:21:05the animation so let's go into the
- 10:21:06animator and set the trigger and again
- 10:21:08we don't want to use strings so let's go
- 10:21:10up to the top of the file make a private
- 10:21:13con string let's call this the number
- 10:21:16popup and number
- 10:21:20popup okay so we have this and down here
- 10:21:22we just set this trailer okay so that's
- 10:21:25it pretty simple and just for fun let's
- 10:21:27also add a nice sound effect so let's go
- 10:21:29over here onto The Sound Manager and
- 10:21:31let's make a function to play sound so
- 10:21:33just like we did over here for the play
- 10:21:34footstep sound let's make another one
- 10:21:37for this one let's call it play
- 10:21:39countdown sound and for this one let's
- 10:21:42not receive a volume or position and we
- 10:21:44just play let's say just the warning
- 10:21:46sound so just that one on vector 3.0 and
- 10:21:50with the current
- 10:21:51volume okay so we have this function and
- 10:21:54then down here just going to sound
- 10:21:55manager instance and play the countdown
- 10:21:57sound again we could refactor this code
- 10:22:00to separate the uan logic from the
- 10:22:02animation from the sound that is one
- 10:22:04approach and it's actually one thing
- 10:22:05that we're going to do in the next po
- 10:22:07stage but this one is also a possible
- 10:22:09thing since the UI is always so directly
- 10:22:12connect to visuals okay so with this
- 10:22:14let's test so here in the options let's
- 10:22:16just make sure that we have our sound
- 10:22:18effect effect so let's make sure they
- 10:22:19are playing okay great now let's go
- 10:22:21ahead and play and there you go we have
- 10:22:23our nice countdown number and there you
- 10:22:25go it looks great so it looks great and
- 10:22:27sounds great all right awesome as you
- 10:22:30can see just by adding a simple
- 10:22:31animation and some simple sounds that
- 10:22:32already look so much better now the next
- 10:22:35thing we want to polish is on the stove
- 10:22:37so let's go into our stove back into our
- 10:22:39counters back into 3D and zoom in over
- 10:22:42here okay let's also make sure that we
- 10:22:44hide the canvas just so we can play
- 10:22:46around this all right great so there's
- 10:22:48our stove and for this we want to add
- 10:22:51basically a warning icon and a nice
- 10:22:53sound when the meat is about to burn so
- 10:22:55let's go inside the stove counter pream
- 10:22:57okay so now inside of this we already
- 10:22:59have a nice generic progress bar UI like
- 10:23:02I mentioned if you want to get some more
- 10:23:04custom Behavior you can combine a
- 10:23:06generic bar like this one with some
- 10:23:08specific component so that's exactly
- 10:23:09what we're going to do right now so over
- 10:23:11here let's create a brand new canvas as
- 10:23:14usual let's make it an World space
- 10:23:16canvas for position let's put all of
- 10:23:18this on zero let's just lift it up by a
- 10:23:21bit so set it on a y of three okay great
- 10:23:24then let's add our super useful look at
- 10:23:26camera component and make it camera for
- 10:23:29okay now inside let's go ahead create a
- 10:23:31new image let's put it on a size of 0.5
- 10:23:34by 0.5 okay just a nice square and for
- 10:23:37the Sprite there's a nice warning image
- 10:23:39in the assets so it's this one here we
- 10:23:41have the warning okay great basically we
- 10:23:44want to show this when the meter is
- 10:23:45about to burn so let's make a scrim to
- 10:23:47run this and on the canvas let's give it
- 10:23:49a proper name so let's call this the
- 10:23:51stove burn warning UI okay so let's make
- 10:23:54the script to run this so we new C
- 10:23:56script with the exact same name and over
- 10:23:58here let's attach a script okay great so
- 10:24:01now the first thing that we need is
- 10:24:02obviously a reference to the stove so
- 10:24:04let's make a seriz field private for the
- 10:24:06stove counter for the stove
- 10:24:09counter okay here in the editor let's
- 10:24:12drag the reference of the so counter
- 10:24:13okay great so now we basically just need
- 10:24:16to know when the food is about to burn
- 10:24:18and for that we can actually listen to
- 10:24:20the on progress event so let's do a
- 10:24:23private void start and on start let's go
- 10:24:25into the stove counter and let's listen
- 10:24:27into the on progress change event okay
- 10:24:30so we have this one and basally we're
- 10:24:33going to want to show this element so
- 10:24:34let's find a b show we're going to want
- 10:24:36to show this when the progress
- 10:24:38normalized is above a certain amount so
- 10:24:41let's define a float for the burn show
- 10:24:43progress amount and let's say on .5 so
- 10:24:47on this one we show it
- 10:24:48except obviously we don't want it to be
- 10:24:50shown when the food is just cooking we
- 10:24:52only want it to show when it's about to
- 10:24:54burn so that means we also need to check
- 10:24:56the state on the stove counter so let's
- 10:24:58make a function to check if we are in
- 10:24:59the state that we want so we're here on
- 10:25:01the stove counter let's go down to the
- 10:25:03bottom and let's make a public bowl is
- 10:25:06fried and over here we just return if
- 10:25:09the state equals state. fried okay
- 10:25:12that's great so now here we're going to
- 10:25:14show if the progress is above 0.5 and
- 10:25:17the stove counter is on the Fright State
- 10:25:20all right so that's the logic that we
- 10:25:21want then we just want to show our
- 10:25:23height so let's make the usual functions
- 10:25:25private void show any a private void
- 10:25:27hide and just do game object set active
- 10:25:30into either true or
- 10:25:36false and over here if show then let's
- 10:25:39call the show function and if not let's
- 10:25:41call the Hide function and of course on
- 10:25:44start let's start off as hidden okay
- 10:25:47that's it let's test
- 10:25:49just over here in the editor make sure
- 10:25:50the reference is dragged and let's save
- 10:25:52the prefab go outside head on play and
- 10:25:54yep right away there's no element okay
- 10:25:56great now I place it and yep while it's
- 10:25:58cooking there's no element and now once
- 10:26:00it's on the halfway point for burning
- 10:26:02and if there you go we've got the nice
- 10:26:03warning okay awesome so now that this is
- 10:26:06working let's just add a nice animation
- 10:26:08so once again let's go inside the stove
- 10:26:10counter and on the burn warning UI let's
- 10:26:13add an animated
- 10:26:15controller then let's actually create
- 10:26:17the animated controller let's create a
- 10:26:18brand new animated controller for the
- 10:26:21stove burn warning
- 10:26:22UI then let's assign it okay and over
- 10:26:26here on the animation window let's
- 10:26:27create an
- 10:26:28animation let's put it on the same
- 10:26:30folder and call it for this one let's
- 10:26:33say flash we're going to make it Flash
- 10:26:35and then again for making it flash let's
- 10:26:36use the same component that we used a
- 10:26:38while ago so let's add a canvas group so
- 10:26:41here it is now we can play around the
- 10:26:42alpha so super useful although I should
- 10:26:44say that at this point since we just
- 10:26:46have a single image we could just record
- 10:26:49a change over here on the alpha for the
- 10:26:50image itself however one place where
- 10:26:52this component is super useful is if you
- 10:26:54have multiple images so if over here I
- 10:26:56duplicate this one and I put it off to
- 10:26:58the side if I change the alpha on one of
- 10:27:00them then obviously it only affects that
- 10:27:02one but if I go over here and I modify
- 10:27:04the canvas group that changes the AL for
- 10:27:06both them so if you have a group of
- 10:27:08images then using the canvas group makes
- 10:27:10it super simple so anyway so here we
- 10:27:12have just our image let's go ahead and
- 10:27:15record and let's say we start off on an
- 10:27:17alpha of zero then after 10 frames go
- 10:27:19into Alpha of one and after 20 frames
- 10:27:22back into an alpha of zero okay so
- 10:27:24that's it a super simple very basic
- 10:27:26animation we don't even need analogic
- 10:27:28since we just want this animation to
- 10:27:30play non-stop so that's great that
- 10:27:32should be working now let's add some
- 10:27:34sound so for that we could make another
- 10:27:36script but already on the stove counter
- 10:27:38we already have a nice sound component
- 10:27:40so let's open up this script the stove
- 10:27:42counter sound so this is basically where
- 10:27:44we're playing or stopping the sizzling
- 10:27:46sound so over here we can just have had
- 10:27:48the warning sound we're going to play
- 10:27:50the sound just like we have over here
- 10:27:52for the burning UI so let's actually
- 10:27:54copy these same components and over here
- 10:27:57let's paste it so for this one instead
- 10:27:59of show let's give it a proper name so
- 10:28:01play warning sound except it's not on
- 10:28:04state change so let's actually listen to
- 10:28:06the other one so stove counter on
- 10:28:07progress changed let's listen to that
- 10:28:09one and it's on that one that we use
- 10:28:12this Okay so we've got that one and then
- 10:28:15for playing the warning sound we're
- 10:28:16going to want to basically play it every
- 10:28:18certain amount of time so let's make
- 10:28:20over here a private void update and on
- 10:28:23update let's just Define a private float
- 10:28:26for the warning sound
- 10:28:29timer and so down here we just count it
- 10:28:31down as usual time. Delta time and if
- 10:28:35this one is under
- 10:28:37zero if so then let's reset it so Define
- 10:28:41a certain
- 10:28:42maximum let's say 10 times or maybe just
- 10:28:45five times per second that should be
- 10:28:46good so we have this but obviously we
- 10:28:48only want this to run if we should be
- 10:28:50playing the warning sound so let's
- 10:28:51actually save this one up here so
- 10:28:53private ball for the play the warning
- 10:28:55sound and then we set it on this one and
- 10:28:58down here let's just go and we're only
- 10:29:00going to run this if play the warning
- 10:29:03sound then we're going to run our timer
- 10:29:04logic all right and then over here all
- 10:29:06we need is to play that warning sound so
- 10:29:08let's actually go into The Sound Manager
- 10:29:11and just like we had the countdown sound
- 10:29:13let's add another one so let's say the
- 10:29:15play warning sound and for this one
- 10:29:17let's receive a vector 3 three for the
- 10:29:18position and we're going to play the
- 10:29:20warning sound on this position so now
- 10:29:22over here on the stove counter let's go
- 10:29:23into The Sound Manager the instense and
- 10:29:26let's play the warning sound and pass in
- 10:29:29the stove. transform. position okay that
- 10:29:32should do it so we now should have a
- 10:29:34nice warning sound and over here we
- 10:29:36should have a nice animation on the burn
- 10:29:37warning UI so let's see both those okay
- 10:29:40so let's pick up some meat and drop it
- 10:29:43and right now it's cooking okay great
- 10:29:45and once it gets the halfway point give
- 10:29:47the there we go now we have a nice
- 10:29:49warning sound all right awesome let's
- 10:29:51just add one more tiny thing let's make
- 10:29:54the bar itself also flesh red when we're
- 10:29:56about to burn so once again let's go
- 10:29:58inside the stove counter and on the
- 10:30:01progress bar UI let's add a nice
- 10:30:03animator and let's go ahead and make one
- 10:30:06so let's create a new animator
- 10:30:07controller for the stove burn flashing
- 10:30:10bar let's go ahead and assign so it's
- 10:30:13the one on the progress bar let's add
- 10:30:15the stove burn flashing bar then on this
- 10:30:18one let's create new animation let's go
- 10:30:20inside the assets animations let's make
- 10:30:21one and just call it idle for this one
- 10:30:24we're going to want the exact same color
- 10:30:26as the normal color so let's go into the
- 10:30:28bar and set the color just save a key
- 10:30:30frame over there okay so that's what we
- 10:30:32want now let's make another animation so
- 10:30:34let's stop recording and let's actually
- 10:30:36duplicate this one so duplicate it and
- 10:30:38for this one name it flash now of course
- 10:30:41we need to add it to the animated
- 10:30:42controller so let's go over here and
- 10:30:44drag it on top okay now for the
- 10:30:46animation let's select the FL Flash and
- 10:30:48for this one let's go ahead click on
- 10:30:50record let's start off on this one and
- 10:30:52after a few frames so let's say maybe
- 10:30:54after 10 frames let's Flash in red and
- 10:30:57after 20 frames let's copy paste the
- 10:30:59same frame okay so that's our nice
- 10:31:01flashing bar now let's just set it up so
- 10:31:03let's go into the animator and over here
- 10:31:05we're going to have a transition from
- 10:31:06that to flash and from flash back now
- 10:31:09all we need of course is an animator to
- 10:31:11control this so let's make a new
- 10:31:12animator parameter let's make it a
- 10:31:14bullan and call it is flashing and again
- 10:31:17make sure to be careful with can't
- 10:31:19sensitive okay so from idle into flash
- 10:31:23let's go ahead remove the exit time for
- 10:31:25duration make it instant so zero and for
- 10:31:27the conditions when that one is true
- 10:31:29okay great and for going back once again
- 10:31:31same thing so instant and let's make the
- 10:31:34condition when it's false okay that's it
- 10:31:36super simple now let's make a script to
- 10:31:38run this so let's go ahead create a
- 10:31:40brandy sharp script for the stove burn
- 10:31:43flashing bar UI let's go ahead and add
- 10:31:45it to the bar so that's see flashing
- 10:31:47baru okay over here let's do pretty much
- 10:31:50the same thing that we did on the other
- 10:31:51one so let's go over here onto the stove
- 10:31:54burn warning UI let's actually copy
- 10:31:56exactly this so let's go on this one and
- 10:31:58paste this one then back here in the
- 10:32:00editor let's drag the reference to the
- 10:32:02self counter and over here logic is
- 10:32:04going to be very very similar so the
- 10:32:06only difference is we have an anator so
- 10:32:08the animator and we're going to grab it
- 10:32:11on private void awake animator get
- 10:32:13component of type
- 10:32:15animator so we have the animator then
- 10:32:17let's let's define the parameter so
- 10:32:20private con string for the is
- 10:32:23flashing and let's set it is flashing
- 10:32:26okay we have our parameter and now down
- 10:32:29here instead of showing and hiding let's
- 10:32:31just go into the animator in order to
- 10:32:32set a bow and the bow will be the is
- 10:32:36flashing and let's set it based on show
- 10:32:39so either we show or hide and we
- 10:32:40actually don't need these functions and
- 10:32:42by default of course let's leave it on
- 10:32:44false okay so that's it super simple
- 10:32:47let's test
- 10:32:48just make sure to save the prefab and
- 10:32:50hit on play okay let's go ahead and cook
- 10:32:52so let's pick it up and drop it all
- 10:32:54right so it's cooking let's wait for it
- 10:32:55to be burning and as soon as it gets
- 10:32:58there yep there you go we've got a nice
- 10:33:00warning a nice flashing bar and a nice
- 10:33:02sound effect so all three warnings
- 10:33:04making ourselves much more polished all
- 10:33:06right awesome now just for balancing
- 10:33:08let's play around the timers so let's go
- 10:33:11into our script M objects on the frying
- 10:33:13recipe so let's make this one Take 5
- 10:33:16seconds then then on the burning recipe
- 10:33:18for this one let's make it take six and
- 10:33:21finally let's also add another stove so
- 10:33:24let's take our stove counter duplicate
- 10:33:25the prefab let's put it over here so
- 10:33:28rotate it to the side let's get rid of
- 10:33:29this one and put this one right in there
- 10:33:32so on 7.5 0 and minus one all right so
- 10:33:36we now have two stoves I can put one
- 10:33:38cooking put another one and I can start
- 10:33:41cutting down some cheese start cutting
- 10:33:44and before they start to burn let's
- 10:33:45actually here there you go that one is
- 10:33:47about to burn burn so let's pick it up
- 10:33:48quickly and that one is actually going
- 10:33:50to burn but I got it okay great all
- 10:33:52right awesome everything's working great
- 10:33:54now for one more polish element let's
- 10:33:56make a nice visual when we deliver
- 10:33:58either a correct or incorrect recipe I
- 10:34:01think it would look good as a world
- 10:34:02canvas on top of the delivery counter so
- 10:34:04let's do that let's over here find
- 10:34:06delivery counter let's go inside the
- 10:34:07prefab and now in here let's create a
- 10:34:10new UI canvas let's name this the
- 10:34:12delivery result UI and as usual let's
- 10:34:15make this a world space canvas so put it
- 10:34:18on world space and for the position
- 10:34:21let's actually lift it up and then we're
- 10:34:23going to make it look at the camera but
- 10:34:25just like this it might actually go
- 10:34:26inside the wall so let's put it over
- 10:34:28here to the side a little bit so let's
- 10:34:30put it on this position so on the X of
- 10:34:31minus 1.6 on a y of three and on a zed
- 10:34:35of 1.2 okay that's the position so right
- 10:34:38there that is going to be looking at the
- 10:34:40camera now inside let's create a new UI
- 10:34:43image it's going to be our background
- 10:34:46and for the size the width and height
- 10:34:48let's put it on 2.2
- 10:34:50x.9 okay that's our background for the
- 10:34:53color let's tint it in a nice green so
- 10:34:55let's put it something like this then
- 10:34:58let's also add a nice outline let's put
- 10:35:01it on full Alpha and for the size let's
- 10:35:04put it on
- 10:35:050.1.1 then let's also add a nice shadow
- 10:35:08component for this one leave it on half
- 10:35:10Alpha and let's put it on0 2 and minus
- 10:35:13point2 okay so that's a nice visual now
- 10:35:16on top of it let's create create a new
- 10:35:18UI text let's call it the message text
- 10:35:21and for the message we're going to say
- 10:35:22something like delivery and then
- 10:35:24underneath success let's put it on a
- 10:35:27width and height of zero let's put it on
- 10:35:29a super tiny font so let's say just 0 25
- 10:35:32let's put it in bold and put it down
- 10:35:34Center and get rid of wrapping okay
- 10:35:36that's it let's just push it a little
- 10:35:38bit on the left side so on minus. 32 on
- 10:35:40the X okay and now next to it let's make
- 10:35:43another UI image for this one call it
- 10:35:46the icon image let's put it with a size
- 10:35:48of 0.5 by .5 and put it over to the
- 10:35:51right side so an X of 7 okay and now for
- 10:35:54the spres including in the asset are two
- 10:35:56Nice Sprites so there's a nice cross for
- 10:35:58when we get it wrong and there's a nice
- 10:36:00tick okay so that's the setup that we
- 10:36:02want now on the delivery result UI let's
- 10:36:05go ahead add our look at camera
- 10:36:06component and for this one let's go
- 10:36:08different so instead of the camera
- 10:36:09forward let's go ahead with the look at
- 10:36:12inverting so there it is this is our
- 10:36:13setup now let's make the script run this
- 10:36:16so let's go ahead create a new UI new C
- 10:36:19script for delivery result UI let's
- 10:36:22attach the script and open okay so now
- 10:36:25here let's make serialized fields for
- 10:36:26our elements so a serialized field first
- 10:36:30of all for the background image and this
- 10:36:32is actually going to be of Type image
- 10:36:34image inside Unity engine dii okay our
- 10:36:36background image then we're going to
- 10:36:38have another one for the icon image and
- 10:36:40we're going to have another one this one
- 10:36:42is a text mesh Pro yugui for the message
- 10:36:45text okay let's save okay so let's drag
- 10:36:48the references to the background the
- 10:36:50message text and the icon image okay
- 10:36:52great now over here let's listen when a
- 10:36:55delivery is delivered so let's make a
- 10:36:57private vo start let's go into the
- 10:36:59delivery manager the instance and we
- 10:37:02have all of our nice events so you've
- 10:37:04got a success and a fail so let's listen
- 10:37:06into both them so both the success and
- 10:37:09on the recipe failed let's listen to all
- 10:37:11these and as always let's write goodl
- 10:37:14code and rename this so delivery manager
- 10:37:16on recipe success and for this one is
- 10:37:19the on recipe
- 10:37:21failed okay we have both of our events
- 10:37:25so over here it's actually going to be
- 10:37:26very simple we just want to play around
- 10:37:28the text the icon and the background
- 10:37:30color so for example when we fail let's
- 10:37:33go and we want to set the background
- 10:37:35image to about a red so for defining the
- 10:37:38color let's actually go up here and
- 10:37:40Define a color for the success color and
- 10:37:43we're going to have another one for the
- 10:37:45fail color and then for the Sprites
- 10:37:48let's also have that so a Sprite for the
- 10:37:49success Sprite and another one for the
- 10:37:52fail Sprite okay those are all the
- 10:37:55elements so over here in the editor
- 10:37:57let's just set them so for the success
- 10:37:58color let's actually use the exact same
- 10:38:00color by the way here's a quick tip if
- 10:38:02you go up to a field for example like
- 10:38:04this one on the color you can right
- 10:38:06click and copy and then go into delivery
- 10:38:08results and over here right click and
- 10:38:10paste there you go the perfect color
- 10:38:12then for the failed color let's go with
- 10:38:13the red maybe a bit darker and also
- 10:38:16importantly make sure you set the the
- 10:38:17alpha to fall okay so we have a red nice
- 10:38:20like that okay then the success Sprite
- 10:38:22this one is going to be the tech and for
- 10:38:24the fail this one is going to be the
- 10:38:26cross okay those are all of our elements
- 10:38:28so now over here when we fail let's go
- 10:38:30into the background image and set the
- 10:38:32color and let's put the fail color then
- 10:38:35for the icon image let's set the Sprite
- 10:38:37to the fail
- 10:38:38Sprite and for the message text let's
- 10:38:42set this one for delivery and then
- 10:38:45failed by the way this backwards sln
- 10:38:48this means a new line so we're here to
- 10:38:49let's just set the text on this one so
- 10:38:51it essentially means that it will write
- 10:38:53delivery then new line and then fail
- 10:38:55thenne just make sure you're using the
- 10:38:57backwards slash and not the forward
- 10:38:58slash so use the backwards one there you
- 10:39:01go there's a new line okay so that's the
- 10:39:02on recipe failed and now on the recipe
- 10:39:04success let's use the success color the
- 10:39:07success Sprite and over here delivery
- 10:39:11success okay so that's great that should
- 10:39:13be working now just one more visual
- 10:39:15thing let's add a nice animation
- 10:39:18so just like we did previously let's go
- 10:39:19over here over here let's add an
- 10:39:21animator
- 10:39:22component let's create an animation for
- 10:39:24this one for delivery result UI so let's
- 10:39:26go up here create a brand new animated
- 10:39:29controller for this and let's go ahead
- 10:39:31and assign it so delivery result UI all
- 10:39:34right now let's make an animation so
- 10:39:36this delivery result UI let's call just
- 10:39:38popup and for this one let's do just
- 10:39:40like we did for the numbers so let's
- 10:39:42scale and rotate it however if we rotate
- 10:39:45that's actually not going to work that
- 10:39:46is because because we have the unlooked
- 10:39:48camera and this one is already going to
- 10:39:49be setting the rotation so we would end
- 10:39:51up with this script fting the animator
- 10:39:53for the rotation so that would mess
- 10:39:55things up however one nice and simple
- 10:39:57solution to this basically we just put
- 10:40:00this inside another game object so let's
- 10:40:02create a new game object and let's put
- 10:40:04it inside let's an mty game object for
- 10:40:06delivery result you want then look at
- 10:40:08camera so we have this one now the
- 10:40:11reason why I created it inside is that
- 10:40:13so over here we can set everything to
- 10:40:15zero and now with that one all on zero
- 10:40:17we can go ahead and drag this outside of
- 10:40:19this object and there you go that one
- 10:40:20keeps the exact same settings and now on
- 10:40:22this one we can add the unlock at camera
- 10:40:24component and set it up just like we had
- 10:40:26so the UN look at inverting and now on
- 10:40:28this one we're going to make a child of
- 10:40:30that one and there you go now everything
- 10:40:31is on zero exactly as it should be and
- 10:40:33on this one we can get rid of the UNL at
- 10:40:35camera and now we can indeed play around
- 10:40:37the rotation so for the animation let's
- 10:40:39just go ahead and set it so for this one
- 10:40:41let's go up to 1 second and let's record
- 10:40:44a key frame on a scale of one and on a
- 10:40:47rotation of zero then let's go back into
- 10:40:50the beginning and for this one let's
- 10:40:51scale it backwards so maybe something
- 10:40:54like this maybe a 15 let's put it quite
- 10:40:57a bit smaller then let's go up by three
- 10:40:59frames let's put that one on minus5 so
- 10:41:02rotation on the other side and put it
- 10:41:04quite a bit bigger and then on frame 10
- 10:41:06put it on say
- 10:41:081.1 with a rotation of zero just like
- 10:41:11that so there you go there's a nice
- 10:41:13popup and for the alpha let's also go
- 10:41:16over here into the 50 and let's just add
- 10:41:19the canvas group let's set this one over
- 10:41:21here is on one and then we scroll it
- 10:41:24down to zero okay so that's our nice
- 10:41:26animation let's stop recording let's
- 10:41:29open up the animated controller and over
- 10:41:31here let's make our nice animations
- 10:41:33transition so transition from any state
- 10:41:35to that one let's make it based on a
- 10:41:37trigger let's call it just popup and for
- 10:41:40this one this has no exit time duration
- 10:41:43of zero and let's go when the condition
- 10:41:46when we have this trigger
- 10:41:47okay so that's it although one thing by
- 10:41:49default this animation is going to Loop
- 10:41:51so let's just go ahead we can select the
- 10:41:53animation and over here let's just
- 10:41:55untake Loop time so that way the
- 10:41:57animation will not Loop okay so that's
- 10:41:59great now let's go into the script and
- 10:42:01over here let's get our animator so
- 10:42:03private animator animator private void
- 10:42:06awake let's get the animator just get
- 10:42:08component of type
- 10:42:12animator and let's define over here the
- 10:42:14private con string for the popup
- 10:42:22so we have this and then when we have
- 10:42:24either fail or success let's just go
- 10:42:26into the end
- 10:42:27met and let's set the trigger for our
- 10:42:30popup both up here and over here now we
- 10:42:34just have obviously one issue which is
- 10:42:35that it starts off as visible we don't
- 10:42:37want that so over here we can just do
- 10:42:39game object set active into false in
- 10:42:42order to hide it and when we get either
- 10:42:44of these let's set it both to
- 10:42:45true then then afterwards the animation
- 10:42:48will make it invisible so it will still
- 10:42:49be active but it won be invisible so
- 10:42:51that's fine so just with this everything
- 10:42:53should be working as we want so let's
- 10:42:54test let's just make sure to save it and
- 10:42:56go back okay so here we are let's try
- 10:42:59delivering an incorrect plate and there
- 10:43:01you go got a delivery fail okay great
- 10:43:02now let's try delivering a correct one
- 10:43:04so someone wants a cheeseburger so let's
- 10:43:07cook it slice some cheese let's get some
- 10:43:10bread so bread cheese and pick up the
- 10:43:12burger and the liver and there you go a
- 10:43:14nice delivery success all right awesome
- 10:43:17okay so with these handful of changes
- 10:43:19you can already see how we made quite a
- 10:43:20big difference in our game we didn't do
- 10:43:22anything to change any core mechanics we
- 10:43:24just made what was already there pop out
- 10:43:27we added a nice visual boundary to make
- 10:43:28the map look nice we added some nice
- 10:43:31particles when the character is moving
- 10:43:33then we added a nice tutorial in
- 10:43:34controls right as the game starts we
- 10:43:36also added a bunch of effects on the
- 10:43:38stove so it flashes has a warning and
- 10:43:40some sound and lastly we also added a
- 10:43:42nice popup when delivery is delivered
- 10:43:44whether correctly or incorrectly now of
- 10:43:46course we can always keep polishing the
- 10:43:48game until Infinity there's always more
- 10:43:50small things you can add to polish the
- 10:43:51game just a little bit more but at this
- 10:43:53point I'm very happy with what the game
- 10:43:55looks like so after all this work let's
- 10:43:57go into the next lecture where we're
- 10:43:58going to play our game from start to
- 10:44:00finish and see what we've
- 10:44:02done hello and welcome I'm your kod Maki
- 10:44:05in this lecture we're going to look at
- 10:44:06all the work that we've done and have
- 10:44:08some fun playing the finnal game okay so
- 10:44:10here we are in our nice starting main
- 10:44:12menu it's simple but it works actually
- 10:44:14think it looks pretty good so we have
- 10:44:16our our main menu working and we also
- 10:44:18have the loading system that we made so
- 10:44:20as soon as I click on Play There You Go
- 10:44:22loads the loading scene and here we are
- 10:44:23on the game scene so we start off with
- 10:44:25our really nice tutorial window and down
- 10:44:27here we have the controls of course all
- 10:44:29of these are Dynamic so depending on if
- 10:44:31the player rebinds or something this one
- 10:44:32is going to update so we can look at
- 10:44:34this window for as long as we want the
- 10:44:36game is paused in the background so it's
- 10:44:38on a paused game State then whenever
- 10:44:40we're ready we can interact so again
- 10:44:43that's the game input class listening to
- 10:44:44the input and again all the code in here
- 10:44:46is is really nice and clean so when we
- 10:44:48press the interact key the tutorial
- 10:44:50isn't directly listening to that but
- 10:44:52rather the general kitchen game manager
- 10:44:54that main State machine is the one
- 10:44:55listening to the input and this one is
- 10:44:57listening to that state so all our logic
- 10:44:59is very well organized all of the
- 10:45:02elements only listen to the things that
- 10:45:03make sense to them so anyways here we
- 10:45:05have tutorial let's interact and there
- 10:45:07you go we've got our nice game start
- 10:45:08countdown some really nice animation
- 10:45:10really nice sound and yep here we are
- 10:45:13then we've got our clock showing the
- 10:45:14game time and on the left side we can
- 10:45:16see our recipe
- 10:45:17once again all of the elements they're
- 10:45:19all Dynamic they're all spawn randomly
- 10:45:21and the icons for all of the recipes
- 10:45:23they're also all Dynamic so over here we
- 10:45:26have the character control that we built
- 10:45:28we have the collisions that we
- 10:45:29implemented and of course we have the
- 10:45:31ray cast testing for interaction so we
- 10:45:33can identify all the objects in front
- 10:45:35let's begin delivering some recipes so
- 10:45:37for example we need to cook some meat so
- 10:45:39let's go ahead put it on the stove so
- 10:45:40here is the really nice State machine
- 10:45:42that we built so we've got all the
- 10:45:44various States we've got the visual
- 10:45:45completely separated from the logic so
- 10:45:47everything is really nice and of course
- 10:45:48here we have the nice burning elements
- 10:45:50that we added in the Polish lecture so
- 10:45:52that one is burned so let's go ahead and
- 10:45:54use the trash bin to get rid of that so
- 10:45:56let's go ahead cook another one and
- 10:45:58let's make a cheeseburger so let's put
- 10:45:59some cheese let's listen to the alt
- 10:46:01interaction key and we can slice the
- 10:46:03cheese we can pick up the meat pick up
- 10:46:05the cheese then also pick up some bread
- 10:46:08and deliver the recipe and there you go
- 10:46:09our nice polished visual all right
- 10:46:11awesome so here you can already see
- 10:46:13everything that we've built the
- 10:46:15character the physics the logic the put
- 10:46:17all of the UI elements all of the world
- 10:46:18UI elements all of the various counters
- 10:46:21and how they are all prefi variants all
- 10:46:23of the plates the separation between the
- 10:46:25visuals and logic separation between the
- 10:46:27sounds and logic all the Polish elements
- 10:46:29that we made over there the nice Shad
- 10:46:31graph that we made then of course all of
- 10:46:33the basic things that a lot of tutorials
- 10:46:35won't teach you like for example how to
- 10:46:36make a pause menu how to make the
- 10:46:38options how to modify the Sound and
- 10:46:40Music Volume how to rebind the Keys and
- 10:46:42so on so with all that here throughout
- 10:46:44this course we'll learn how to make a
- 10:46:45really nice game with lots of
- 10:46:47interesting interactions which you can
- 10:46:48now apply to any kind of game any kind
- 10:46:50of genre you want so like I mentioned in
- 10:46:52the very beginning you can take pretty
- 10:46:55much what you made here which is really
- 10:46:56just a character controller and a bunch
- 10:46:58of interesting interactions you can take
- 10:47:00everything that you've learned here and
- 10:47:02make something on a Sci-Fi space so like
- 10:47:04for example make something like amongus
- 10:47:05you can make something like FTL or
- 10:47:07perhaps make some kind of survival
- 10:47:09crafting game so of the interactions you
- 10:47:11would have like resource nodes in the
- 10:47:13world then you can interact to GA those
- 10:47:15resources so with that that you could
- 10:47:17build something like rust or Minecraft
- 10:47:19or Don't Starve so hopefully in this
- 10:47:21course you'll learn a ton that you can
- 10:47:22now apply to your own custom original
- 10:47:24projects and if you've made this far
- 10:47:26then congratulations let's go into the
- 10:47:28next lecture where I'll will give you my
- 10:47:29closing
- 10:47:30thoughts hello and welcome I'm your code
- 10:47:32monkey and congratulations you have
- 10:47:35completed this course awesome seriously
- 10:47:37congrats looking at the stats on my
- 10:47:39courses very few people stick with it
- 10:47:41until the very end so if you're hearing
- 10:47:43this then that's excellent you're on the
- 10:47:45top 10% it means you are serious about
- 10:47:47learning game development and I
- 10:47:49generally hope this course has helped
- 10:47:50you on your own Game Dev Journey
- 10:47:52throughout this course you'll learn
- 10:47:53about the basics of unity and C you'll
- 10:47:55learn how to make a character controller
- 10:47:57how to do a physics raycast and use that
- 10:47:59for both Collision detection and
- 10:48:01identifying objects to interact with you
- 10:48:03learn about C interface and events two
- 10:48:06extremely useful C features you learn
- 10:48:08about Script Mod objects how to use the
- 10:48:10new input system Shad graph and tons
- 10:48:12tons more and the most important thing
- 10:48:14of all you'll learn how to build a
- 10:48:16relatively Lex game while writing good
- 10:48:18clean code I really hope that's the main
- 10:48:20takeaway you learn from this course
- 10:48:22learning how to write better high
- 10:48:24quality code learning how to refactor
- 10:48:26how to keep the visuals and logic
- 10:48:27separate keep the uid coup from logic
- 10:48:30learning all those things has now made
- 10:48:31you a 10 times better developer than
- 10:48:33when you started so I really hope you
- 10:48:35enjoyed learning all that let me know in
- 10:48:37the comments what was the most important
- 10:48:39thing you learn throughout this course I
- 10:48:40really hope this was very fun and very
- 10:48:43educational if you enjoyed my teaching
- 10:48:44style check out my other courses I
- 10:48:46really think the turn-based strategy
- 10:48:48course would be excellent for you right
- 10:48:49now it Dives even deeper into some
- 10:48:52Advanced topics and since you've watched
- 10:48:53this entire course all the way you now
- 10:48:55have all the knowledge needed to follow
- 10:48:57that course it will help you really
- 10:48:58solidify all the knowledge you gained
- 10:49:00especially everything related to writing
- 10:49:02good high quality clean code and since
- 10:49:04you use Unity check out my ultimate
- 10:49:05unity overview course it covers lots of
- 10:49:08tools and features of the engine so you
- 10:49:09can really use all the tools that you're
- 10:49:11disposal to make any game you can think
- 10:49:13of alternatively if you like visual
- 10:49:15scripting I have course on that or learn
- 10:49:17how to make a really nice Builder
- 10:49:19Defender game and definitely make sure
- 10:49:21to wish list my upcoming steam game
- 10:49:22Total War Liberation I will be posting
- 10:49:25Dev vogs and in those you will see how
- 10:49:27the code that I use in my own steam game
- 10:49:29is on the same level of quality as what
- 10:49:30you learned in this course okay so
- 10:49:32that's it for me this course was a ton
- 10:49:34of work so I generally hope it helped
- 10:49:36you a ton on your Game Dev Journey thank
- 10:49:38you so much for watching and I'll see
- 10:49:39you next time
About this transcript
This page contains the full transcript of Learn Unity Beginner/Intermediate 2026 (FREE COMPLETE Course - Unity Tutorial) by Code Monkey, generated from the public captions YouTube serves with the video. The transcript has 139,416 words across 18,682 segments, with the original timestamps preserved so you can click any line to jump to that moment in the embedded player.
What you can do with it
Use the transcript to take notes, quote the speaker, build a study guide, generate a summary with ChatGPT or Claude via the YouTube Summary tool, or export it as a timed subtitle file with YouTube to SRT. You can also re-open it in the transcriber to translate the transcript into 100+ languages.
Free YouTube transcript tool
YouTube2Text is a free YouTube transcript generator — no signup, no daily limit. Paste any YouTube link and get the full transcript instantly, with timestamps, click-to-jump, translation to 100+ languages, AI prompts for ChatGPT, Claude, and Gemini, and exports to TXT, SRT, VTT, or Markdown.