Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Azerbaijani
Basque
Belarusian
Bemba
Bengali
Bihari
Bosnian
Breton
Bulgarian
Cambodian
Catalan
Cebuano
Cherokee
Chichewa
Chinese (Simplified)
Chinese (Traditional)
Corsican
Croatian
Czech
Danish
Dutch
English
Esperanto
Estonian
Ewe
Faroese
Filipino
Finnish
French
Frisian
Ga
Galician
Georgian
German
Greek
Guarani
Gujarati
Haitian Creole
Hausa
Hawaiian
Hebrew
Hindi
Hmong
Hungarian
Icelandic
Igbo
Interlingua
Irish
Italian
Japanese
Javanese
Kannada
Kazakh
Kinyarwanda
Kirundi
Kongo
Korean
Krio (Sierra Leone)
Kurdish
Kurdish (Soranรฎ)
Kyrgyz
Laothian
Latin
Latvian
Lingala
Lithuanian
Lozi
Luganda
Luo
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maltese
Maori
Marathi
Mauritian Creole
Moldavian
Mongolian
Myanmar (Burmese)
Montenegrin
Nepali
Nigerian Pidgin
Northern Sotho
Norwegian
Norwegian (Nynorsk)
Occitan
Oriya
Oromo
Pashto
Persian
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Punjabi
Quechua
Romanian
Romansh
Runyakitara
Russian
Samoan
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Seychellois Creole
Shona
Sindhi
Sinhalese
Slovak
Slovenian
Somali
Spanish
Spanish (Latin American)
Sundanese
Swahili
Swedish
Tajik
Tamil
Tatar
Telugu
Thai
Tigrinya
Tonga
Tshiluba
Tumbuka
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zulu
hello and welcome I'm your code monkey
and here is a free complete course on
making a game from start to finish if
you've always wanted to learn how to
make a game or if you already know the
basics but want to see how to organize a
more complex project then this video is
for you it's perfect for both beginners
and more intermediate users this is a
completely free course video but it has
the same level of quality as my paid
courses or my Steam games you can
download the project files to follow
along or inspect the funnel game you can
even play the final game directly on
scene we're going to start commonly from
scratch and build a really awesome game
with tons of systems and mechanics
building this design requires working
with lots of unity and c-sharp features
so this is a really awesome project for
you to learn after following this course
and learning all of these techniques you
won't be able to build all kinds of
games in all kinds of genres this is
going to involve learning about the
basics of unity and c-sharp learning how
to make a character controller physics
raycast learn all about c-sharp
interface and events using script more
objects handling UI the new input system
and lots more
very importantly everything that we're
going to do here is going to be focused
on writing good easy to understand clean
code meaning that I will not be teaching
you bad practices that some beginner
tutorials teach the code that we're
going to write here is production
quality code this is not a throwaway
demo the quality of the code and the
structure of the game that we're going
to build is on the same level of quality
as my own Steam games as you can see
from the video link this is indeed a
complete very thorough course so don't
try to watch this whole thing in one
sitting take your time take it slow and
just focus on learning there are
chapters for every single lecture in the
video here's a quick overview of the
entire course all the steps that we're
going to take to reach the final
published game so first of all we're
going to start commonly from scratch by
selecting a Unity version and creating a
brand new project with that new project
we will then learn all about the basics
of the UNT interface and setup plane
layout
then the other important part is Visual
Studio which is where we're going to be
writing all of our code
after that comes an extremely important
lecture all about coding style and
naming rules like I said the code in
this course is on the same level of
quality as my Steam games so having
proper naming rules and good code sound
is Paramount next we're going to
download and import all the assets that
we're going to use in the course
everything is included so you can follow
along with every step of the way
with yes it's important we're going to
set up some quick post processing just
to make the game look good then for our
first piece of logic we're going to make
a simple character controller with that
logic working we will then Implement a
proper character visual with the
included assets
next we're going to learn the basics of
animation and the animator component and
with that we're going to make our player
really Common live with some simple but
really nice animations then we're going
to install the send machine package this
isn't actually used too much in this
course but I still wanted to include it
because it is such a useful tool so I do
want you to know about it after that
comes another extremely extremely
important lecture with regards to
writing some good link code we're going
to do a nice refactor to replace the
Legacy input Venture with the brand new
input system
learning how to refactor is an extremely
important and very valuable skill that
will massively improve the quality of
your code with that then we're going to
implement some nice Collision detection
to make sure our character doesn't want
through walls
next we're going to create the very
first kitchen counter and make a script
to handle how to interact with it then
we're going to learn all about c-sharp
events and create a proper interact
input next we're going to build a
selected counter visual which will
require us to learn about the extremely
useful Singleton pattern with the
counters working we're going to start
working on the kitchen objects
themselves so these are going to be the
ingredients and the plates we're going
to use scriptable objects to Define all
of the types
then a very important part of our design
is each kitchen object will have to be
placed somewhere so we're going to take
some time to really think about the best
way to achieve that all while riding
some good clean code next we're going to
enable the player to pick up an object
in doing so we're going to learn about
c-sharp interfaces then we're going to
make a container counter this is from
where we can spawn new objects
with that we will enable the player to
pick up objects and drop them anywhere
where there's space
then we're going to make the cutting
counter this one enables the player to
cut an ingredient into slices so to do
that we're going to make an alternate
interaction
and for handling the cutting we're going
to once again use script more objects to
define a proper cutting recipe
then we're going to learn about a really
awesome Unity feature we're on canvases
and use that to display a nice progress
Bar for our cutting progress after that
is a quick lecture just going to make a
very useful generic script to make any
object look at the camera
next for another counter we're going to
build a trash bin this is where the
player can drop objects to destroy them
then the stove counter this one is going
to be quite a bit complex we're going to
create recipes for cooking and for
burning we're going to learn how to make
a basic state machine and handle timers
next we're going to make the plates
counter this is a simple encounter that
just spawns a bunch of plates
after that we're going to make some
custom Logic on the plate to be able to
hold other objects
with that logic working we're going to
build a complete visual for all the
objects that can exist on the plate
then make a nice UI element on the plane
itself to showcase the icons of what
exactly is on that plate afterwards
we're going to make the very last
counter the delivery counter this is
where we drop the completed plates and
in this lecture we're also going to
learn about the unity share graph and
make a quick simple custom Shader
then we're going to build the delivering
manager class that generates the recipes
that the customers are requesting next
we're going to build a UI to showcase
the wedding recipes after that comes
something pretty crucial we're going to
add some music and then add some sound
effects for all kinds of game actions
without the game won't be almost done so
next we're going to build a proper game
start and a game end
then make a simple main menu and handle
scene loading after that hand on
creating a basic pause window
then make an options menu enable the
player to modify the audio levels and
rebound keys
after that we're going to enable menu
navigation with a controller and in the
end as usual comes the Polish stage so
we're going to add all kinds of small
tweaks and effects to make the game feel
really great like I've said many times
polish is what separates good games from
great games after all of that we will
have our final completed project so as
you can see you will learn about tons of
Topics by following this course also let
me point out one of the reasons why I
chose this specific design is because my
next free course won't be on taking the
game that we're going to build here and
make it multiplayer so if you've ever
wanted to make multiplayer games then
that course will be excellent for you
definitely take your time following this
course the multiplayer free course
should hopefully be out next month or if
you're watching this in the future check
the links in description although that
multiplayer video won't be starting from
where this course ends so definitely
make sure you watch this one now if you
are new to the channel then welcome and
here's a bit about me and my credentials
or why you shouldn't listen to what I
have to teach
my name is Hugo and I've been running
this Code Monkey YouTube channel for
five years now in total almost 700
videos on all kinds of topics including
tons of tutorials sharing my knowledge
to help you on your Game Dev Journey I'm
also a professional indie game developer
making games for over 10 years with 8
successful Games published on scene so
what I'm teaching here is based on a lot
of years of experience making a lot of
games just like with my paid courses I'm
always going to be in the common
censoring questions so if you get stuck
at a particular point or need extra
clarification on something go ahead post
a comment and I'll do my best to help do
make sure you include a timestamp of
what you're referring to I will also be
updating the pin comment with any
frequently asked questions that I see so
actually right now go ahead pause the
video and scroll down a bit just to look
at that comment since on YouTube I
cannot update the video after it's
published I will be updating that
comment over the next months and years
with anything that comes up also I've
been running this channel for five years
and in that time I've made almost 700
videos so there's lots of topics that
I've covered separately in more detail
all of those videos are linked in the
description throughout this course I
will be focused on building this
specific game using whatever it takes to
build it meaning for example when we get
to using c-sharp events I won't teach
the basics about how they work in order
to achieve what we want to build but if
you then want to learn about c-sharp
events in more detail definitely go
watch a dedicated video and I also made
a page on my website for this course it
contains a link to download all of the
project assets you can also download the
complete project files for every single
lecture so if you get stuck at any point
you can download the code at that
lecture and compare with your own
there's also references to all of the
videos and I will also be including
frequently asked questions for each
lecture so definitely keep that page
open in a second tab as you follow along
this course now this free course Took a
ton of work to make so I really hope you
find this video helpful go ahead and hit
the like button if it helps you it's a
small thing but it generally does help
this video on the YouTube algorithm
making this course was a ton of work and
by making it commonly free it means it
will obviously never make as much money
as if I had just made this a paid course
I'm personally okay with that decision
with the hopes that by making it free it
won't reach and help many more people
I'm also a big believer that education
should be free so if you can't afford
one of my paid courses like if you're
just a kid or going through a rough time
I still want you to have access to high
quality education so you can achieve
your Game Dev dreams one easy way you
can help me for free is simply by liking
this video subscribing to the channel
and just watching this course
that will hopefully help push this video
on the YouTube algorithm and help it
reach many more people another free way
to support what I do is I'm currently
working on my next team game called turn
one Liberation you can wish list the
game on Steam wishlists matter a lot for
steam visibility so just by doing that
you won't be helping me and just in case
you can't afford it and you find this
free course useful you can also support
what I do in a few other ways I spent a
bunch of money making this course I
hired an artist for the 3D assets so
that I had the right to distribute them
so that you can download it and follow
along
same thing for the music and sound
effects the logo and the cost to upload
the game to seem so I would like to at
least not lose money on this project
hopefully there's enough of you who
can't afford to help me so that I can at
least break even
and for one way you can support is I
added this exact same course on my
website as a regular paid course
although I want to be very very clear
there is absolutely no difference
between this free video and the paid
course there is absolutely nothing
behind any kind of payroll all of the
lectures are free all of the apps are
free everything is free you don't have
to pay for anything if you can't afford
it or you just don't want to the paid
version is essentially a donation the
only difference is this free YouTube
video has regular YouTube ads whereas
the paid version on the website doesn't
have any ads that's it that's the only
thing so the only reason why I made that
paid version is just in case some of you
can't afford it and you want to support
what I do and want to help me break even
on this project but again only do that
if you can't afford them if you can't
that's personally fine I hope you'll
learn a ton from watching and following
this free course beyond that if you
follow this course and you enjoy my
teaching sound perhaps look into my
other courses if you like this video
then I think you won't really like my
turn-based strategy course that is the
perfect course to follow up on this one
one it Dives even deeper into some of
the concepts used here and it will help
you make the jump from beginner to
Advanced and since you're interested in
unity I think my ultimate unity overview
course would also be very useful to you
each lecture on that course is focused
on teaching one entitled feature there's
already over 15 lectures including
plenty of small but very important
things that you just wouldn't see in a
regular YouTube video if you're
interested in visual scripting I have
course on making three unique games
internally with visual scripting and no
code at all or if you prefer code you
can learn how to build a nice Builder
Defender game so if you enjoy my
teaching Style on this free course then
check out my other ones then of course
YouTube has Channel memberships and
super thanks so you can use those if you
want I also have my patreon if you
prefer that and in a lot of my videos I
have some affiliate links if you ever
pick up anything through those I get a
nice commission and I also have some of
my own assets on the unity Astor so if
you enjoy this free course and you want
to support what I do there's plenty of
ways but again don't feel obligated if
you can't afford it or you just don't
want to that's perfectly fine I hope
you'll learn a ton from watching and
following this recourse alright so
that's enough talk of that for now
before we begin building the game from
scratch let's inspect the final polish
game that we're going to build so let's
see that in the next lecture
hello and welcome I'm your code monkey
here let's take a look at the final game
that we're going to build so we start
off on a simple but really nice main
menu so we've got a nice visual a nice
logo and a bunch of useful buttons then
of course the game has a nice loading
system so when I click on play it's
going to load into a unloading scene and
then funnel into the final game scene so
let's go ahead and play and if there we
go here we do see the game scene and
right away we see a nice internal window
so it's telling us how to play the game
so the basic interactions and then over
here the controls importantly these are
all rebindable so over here this element
is all Dynamic then we can look at this
tutorial for as long as we want and we
are waiting for the interact to continue
there's also a really nice song playing
in the background so the game has music
now we can look at this tutorial for as
long as we want and when we're ready we
can interact and continue and as soon as
we do if there you go we've got a nice
countdown some nice animations a nice
sound effect and there you go now we are
playing okay so here I am controlling a
nice character I can move in any
direction
there is Collision detection so
obviously I cannot go inside solid
objects so I can walk around and for the
goal of the game over here on the left
side we've got recipes that the
customers are waiting for so for example
One customer wants a simple Burger so
for that we gonna need to pick up a nice
bun so let's pick it up then the burger
obviously requires a meat Patty so let's
go ahead we can pick one up from here
but this one is an uncooked meat padding
so we need to drop it over here on the
stove and there you go it starts cooking
we've got a nice timer we've got a nice
warm bar UI
and there you go it keeps counting and
we've got some nice park on some nice
visuals and over there even a nice
indicator telling us the meat is about
to burn and there you go the meat has
burned so now I can pick this up and I'm
holding some burnt meat so the customer
probably doesn't want to eat this so we
can go over here to the trash or trash
it let's try doing another one and do it
properly so let's wait for it to cook
pick up a plate so we can pick it up
directly onto the plate there you go to
the meat is cooked so let's pick it up
then go pick up some bread and there you
go here we have our camelli recipe so
let's go into the delivery counter
deliver it and there you go a nice
delivery success all right awesome we've
just delivered our first recipe so then
someone else wants a salad so let's go
ahead pick up a tomato here we have a
big uncut tomato so let's drop it onto a
cutting board and now we can interact
with it so we can interact with a
secondary interaction key
and by interacting we cut the tomatoes
so it takes a few cuts and there you go
with slices and it's sliced into tomato
slices so let's do the same thing for
the Cabbage here we are holding a
regular cabbage then slice it and this
one actually takes a bunch more and
there you go got both slices okay great
so now let's pick up the plate pick up
both slices and deliver to the customer
and there you go got a nice success all
right awesome and of course we have a
correct identification of if we have a
crack recipe or not
so if I just pick up an empty plate and
deliver it there you go got a film
delivery because nobody wants just an
empty plate alright so here you can
already see quite a lot of interactions
quite a lot of systems at work so the
character has a nice character
controller it has physics interaction
you can see how it identifies the
counter that is in from the character I
can press a button to interact with the
counter and interacting with different
counters does different things so if I
interact with a clear counter I can pick
up or drop things over here I can pick
up drop it with an alternate interaction
I can do the second action then there's
the stove machine so that one has a nice
State machine so it counts up over here
we've got some nice particles we've got
a nice Bloom so all the Visions look
really great so we've got some post
processing we have a bunch of UI
elements directly on the world and
outside of here we've got some regular
UI elements
so we've got the recipes with Dynamic
icons for all of them we've got a timer
over there on the top right corner
showing how long we have to deliver on
our recipes and on the kitchen counter
we're also using a custom Shader so this
was built using shade wrap so as you can
see lots of internalized systems then
the game also has of course the basics
that any game should have so I can pause
the game and there you go we've got a
nice pause menu so we can resume to go
back or pause it again and of course
while pause everything is possible
that's great we can go back into the
main menu or we can go into options and
over here we can play around the sound
effects volume the Music Volume we've
got all of our controls importantly
these are the controls for the keyboard
and also the GamePad
so the game can be played with any
Gamepad so it can be an Xbox controller
PlayStation switch controller it doesn't
matter all of them work and we can also
rebind all these Keys both the keys as
well as the GamePad inputs so let's go
ahead and deliver a cheeseburger so
here's some burn meat so let's toss this
then pick up some more meat pick up a
plate here we've got some cheese we've
got some bread pick up the meat and
deliver it all right awesome and of
course finally at the end when our
timers left here we have a nice game
over window showing how many recipes we
delivered alright so this is the final
game that we're going to build as you
can see it involves lots of interesting
interactions which require learning lots
of different skills we're going to be
using c-sharp interfaces c-sharp events
the new input system shade graphs
critical objects we're going to learn
about c-sharp events making character
controller handle collisions and so on
like I said one thing that we're going
to focus heavily throughout the making
of this game is on writing good clean
code meaning that the final game that
we're going to build won't be very easy
to expand upon thanks to how long the
code is very clean it will be very easy
to add more recipes maybe more counters
with more actions maybe things like
perhaps washing dishes adding an oven
and so on or really you could make
something completely different
this game is all about character and
interactions
so that could be whatever you want you
could take this as a base and build some
kind of sci-fi game something like Among
Us or FTL you could make a survival
crafting game like rust or Minecraft or
Don't Starve really fun learning how to
build this game by the end you won't
have gained the knowledge required to
build all kinds of unique and
interesting games alright so now that
we've seen the final game Let's actually
build it just before we do let's get a
quick refresher of the absolute Basics
you should know in the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to just get
a quick refresher of the absolute Basics
you should know in order to be able to
follow everything in this course okay so
like I said this free course is targeted
at both beginners and more intermediate
users in order to start following the
course you really only need to know the
absolute Basics I've made three useful
videos with all of the basic knowledge
required to follow this course
watch the video on how to download
install and set up Unity then the quick
Unity Basics and the c-sharp basics
those three Quick videos contain all of
the absolute basic knowledge you need so
if you're a complete beginner go ahead
pause this video and go quickly watch
those and even if you are already
somewhat familiar with unity still go
ahead and give those videos a watch
perhaps in a faster speed just so you
know everything that this course assumes
that you know here I will assume that
you know the basics covered in those
videos like what is a game object what
is a transform what is a mono Behavior
how scripts have a start and update and
some c-sharp Basics as long as you know
those absolute Basics you should be able
to follow everything in this course I
won't teach everything above the
absolute Basics and if you are a more
advanced users definitely keep watching
the beginning of this course might not
have much that is new to you but as we
build the game and start using more
advanced tools like script of objects
c-sharp events and interfaces
refactoring code and focusing on Project
architecture and writing some good clean
code
if you are not a complete beginner you
will still learn quite a lot from seeing
how this project is built and again like
I said I answer comments every single
day so any questions you have just post
them there and I'll do my best to help
this course is split into lectures they
are all as chapters on videos so you can
navigate around let me also take this
time to point out that you are not
expected to follow this course in one
sitting go ahead and take your time
focus on actually learning remember
that's the only goal you're not
competing with anyone you're gaining
knowledge just for yourself
so take as much time as you need
re-watch some lectures if you feel you
didn't fully get it or just ask some
questions whatever you do take your time
and just focus on actually learning so
again if you haven't done so go ahead
pause this video and go watch those
three Basics videos with that we're
going to have everything we need to get
started we're going to start only from
scratch so let's begin creating a brand
new project in the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to begin
actually building our game so let's
create a chameleon 2 project and start
building it on from scratch okay so the
first thing that we need is to install
Unity now I cover this in detail on that
other Basics video so here I will assume
that you already have Unity Hub
installed the first decision we really
need to make is choosing a Unity version
Sony Hub you go into installs and
install an editor and now Unity
recommends that you use the LTS version
or long term sport you should be using
that one in most cases it's what it
installs by default which as the time of
this recording the latest one the latest
LTS one is 2021.3 however I want this
video to stay up to date for as long as
possible so for making this game I will
actually be using version 2022.2 if
you're watching this video where it is
came out then download this version and
if you're watching this months in the
future after version 22 on TS is out
then you can use that one it won't
probably be the exact same thing as
version 22.2 so you should be able to
follow everything exactly for any
changes I will Point them out in the
updated pin comment and if you're
watching this years in the future and
there's an even newer LTS version I
would still recommend you follow using
the 22 LTS don't worry about using a
quote unquote older version everything
you'll learn here in this version will
still be applicable even 10 years from
now so I said I'm going to be installing
this one in terms of modulus doesn't
really need anything I already have
Visual Studio Community installed and
all the other ones are unticked so
install
okay so the version is installed now
let's create a new project let's go into
the projects tab then create a new
project and now first up up here make
sure to select the right version so
again I'm going to be using 22.2 then
for the templates this has mainly to do
with the UNT render pipelines now if
you're a beginner don't worry about that
too much just go ahead and select the 3D
urp template so scroll down this one
right here 3D urp make sure to select
this one and not the one that says just
reading the urp here stands for the
universal render pipeline which means
our game will be playable on literally
any platform so we can make the funnel
game and put it on steam or consoles are
mobile it won't run on everything then
over here on the right side let's
quickly just download the template there
it is it's done
now select the name for your project so
I'm going to call this kitchen chaos and
then select the founder for it all right
so that's it again make sure you're
using the exact right version make sure
you're using the 3D urp template give it
a name a folder and let's head on create
all right so it's open and right away
you might or might not see a window
talking about urp material upgrades I
think this has to do with the template
not having the default materials updated
to the latest Erp version so if you're
watching this in the future chances are
you might not see this one at all but if
you do then just go ahead click on OK
and it will automatically upgrade all of
the default materials alright so here we
have our basic unity window now since we
started a project starting from the RP
template we have down here A bunch of
Erp helper files so you can click to
select the readme file and you can see
it over here on the right side on the
inspector if you want you can browse
around these links in order to learn
more about urp but in our case we're
building the our game we really don't
need this so we're here on the
inspection let's just click this button
to clean up these readme files just go
ahead click on yes and okay that's it so
basically you should only have these
files in your project window so there's
a scene folder and inside we've got the
simple scene then we've got the settings
and inside a bunch of urp assets while
this should have been set up
automatically since we use the 3D
template and then finally we just have
the urp equivalent settings asset now
let's just verify find everything worked
correctly so let's go to the top left go
into edit then go down into project
settings then over here let's go into
the graphics Tab and you should see the
urp High Fidelity asset assigned by
default if not you can click on the
circle icon and assign it then the other
menus over here the urp mobile settings
again this one should be set by default
then down here on the quality tab on
this one make sure High Fidelity is
selected basically whatever you select
here is the quality that we'll be using
in the editor and in turn the selected
quality over here also has a render
pipeline Ascent now in order to avoid
any confusion let's actually get rid of
the other ones so let's just click on
the trash icon to get rid of the
performance and the bounce quality so
just click and click okay so we only
have this one then let's close the
project settings and let's go into the
settings folder and over here let's
select the urp balance there are two
assets for each quality so select those
leave the High Fidelity and the
performance and let's delete these
alright that's it by the way if you made
a mistake and accidentally deleted
something don't worry you can always
just click over here on the plus icon on
the project window and then go over here
under rendering and you can create a new
urp asset with the universe personal
render okay so just like this so we only
have one quality setting we have high
fidelity the quality setting is using
this random pipeline asset which is also
using this renderer so that's really it
with this we have the absolute bare
minimum we need if in the end after
building the whole game you want to
provide multiple quality settings then
you can come back to this menu and
recreate them but in order to avoid
confusion while building the game let's
keep things like this as simple as
possible okay so that's the basic setup
done next we want to prepare our layout
so let's continue on to the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to learn
about the union layout and set it up so
first things first let's familiarize
ourselves with the various NT Windows to
create our own layout it's very
important that you feel uncomfortable
with your layout that you have easy
access to all the things that you need
then you know where everything is you
can see that there's lots of tabs
everywhere over here on the NT window
all of them can be dragged and dropped
in any different position so you can
customize your layout to get it looking
exactly as you want you can set it up in
any way but it will be easier to follow
this course if you're following the same
layout as me I'm assuming you've seen my
quick Basics video so I'm assuming you
know what is the inspector what is a
game object what is a transform what is
the console where is the hierarchy and
so on if this is the very first time
you're seeing the UNT interface go watch
that other quick video first just learn
the absolute Basics now for me I've been
using Unity for over 10 years now so
let's see the layout that I've developed
over the years first the inspector on
the right side just like default that
way we always have a nice view of the
selected object and whatever scripts and
components it has then for the hierarchy
I like to put it down here only on left
side we're going to make sure that in
our scene is always organized so we
don't need the hierarchy to take up tons
of space then with the project files
next to it this corner is enough to
really browse all of the files we want
the console to be on the tab right next
to it usually I find that when making
the game I want to look at the project
window but when playing the game I just
want to look at the console so keeping
them in the same place but on different
tabs works great then over here on the
center of the scene View and again with
the game view right next to it okay so
this is the basic layout that I normally
use now for a couple more options let's
go into the project window and on the
top right corner you can see over here
these little three dots by default it
shows you a two column layout so there's
a column here and a column here but
personally I prefer the one column
layout this shock is one of the project
files in a nice compact list view the
one thing where I prefer the other one
is if you're browsing for some visual
assets over here you can increase the
thumbnail size but for most times I
really like to use the one com layout
much more compact also since we're
talking about the project window just in
case you don't know there's over here
this little button with the eye this one
has to do with package visibility if you
toggle it then some of the inside
compacts are hidden whereas if you
untangle it then you can see all the
various packages with all the source
code and so on you can expand over here
the packages and right now it is showing
all of them all of them with source code
the things everything in there and if
you click on this then it hides it only
shows a bunch of core ones but for most
part you really want to leave this text
and leave this one collapse nice and
clean okay so then on the console over
here once again let's go into the three
dots and for the unlock entry for this
one I like to select one line this makes
the console nice and compact which I
personally prefer you can see more logs
without taking up more space and if you
want to read the home log you can always
just click on it to see the home stack
Trace now there are also some more
options over here if you want for
example show the timestamp this will
show the timestamp when each message
were sent you can use a mono space font
meaning a font where every character has
the exact same width so a bunch of
options but for me leaving it just like
this works perfectly fine then also
importantly over here these three
buttons these toggle the visibility for
the type of messages that appear in the
console the unlocked one this one is for
regular messages we're going to use this
a lot then we've got warnings and
finally errors if you untangle them then
the messages of that type will not show
up on the console so if you ever come
across an issue where nothing is showing
up on the console make sure all three of
these buttons are ticked then on left
side on clear you can click on the Arrow
to see more options I like to set it to
clear on play then collapse this one
basically collapses messages that are
the same all of them into one entry
personally I do nothing like this I want
to see every single message as it comes
out even if it's repeated I've also seen
this lead to a lot of confusion for some
people they think their code is firing
just one message when it's actually
firing hundreds So to avoid any
confusion make sure you leave this
Untitled then for airpods this will
automatically pause the game when there
occurs you should definitely have this
one toggled if there is an area you
definitely want to know about it you
want to know when it happens so you can
fix it whereas if you untuckle this you
might get some errors and the game might
keep playing which will then lead to
lots of confusion when something starts
behaving weirdly so always leave this
one toggled and then the editor button
this one is for more advanced use case
so don't worry about it okay so that's
the console then over here for the game
view we've got a button here to select
the aspect ratio let's go ahead and
select fully Gene this one is a 16x9
aspect ratio so everything is pretty
normal this will really only matter when
we start working on the UI but so I like
to keep it at 16x9 always then on this
button that says play Focus we can
modify some options basically Focus
won't play exam like this on this small
window if you choose maximize then it
will maximize this one when playing the
game and play in Focus won't play the
game even when the window is not in
Focus then another important one is
actually on the same one as the aspect
ratio here we've got a button to turn on
vsync usually When developing the game
you really want to toggle this that's
because right in the beginning when the
game doesn't really have anything you
can leave it on Talent then this might
run at like a thousand frames per second
and that will pretty much drive your GPU
crazy finally if your game view is
looking a bit too pixelated make sure
over here on the scale slider make sure
this one is not zoomed in this one
should always be pushed straight to the
left as much as possible okay so that's
the game view then over here on the
scene view for this one default should
be good these two buttons are extremely
important pretty much all the time you
want to keep the tone handles on the
pivot it and not on the center if you
ever see your handles on weird places
always come back to this you want to
sound pivot pretty much all the time
then for rotation sometimes local is
useful but for the most part you should
probably be keeping in and Global then
for the great showing the reason why yep
down looks pretty good a nice little
visual grid then you've got a bunch more
options if you want then next to it
we've got snapping this one we also
don't need this for now and finally same
thing for increment also don't need this
okay then on the right for the drum mode
let's leave it on Shaden for two then
let's leave this disabled since we're
working on a 3D game for lights let's
make sure this one is enabled for sound
we're only going to add this in the end
so it doesn't really matter for now then
for special effects usually you want
this one to be enabled so it shows
everything you can click on the arrow
and make sure all of them are toggled
the only exception is always refresh you
probably don't need this little scene
window to be refreshing at 60 frames per
second so you can leave that one
unticked and take on the others then
these are for the hidden objects so
let's leave them toggled for the camera
here are the defaults and finally gizmos
leave them all enabled as the defaults
alright so down that's end here is in
layout and going to be using throughout
the course it will be easier to follow
the course if you're using the exact
same layout as me so ideally you should
be using this but again like I mentioned
all the windows are customizable so if
there's something that you absolutely
prefer differently then go ahead you can
drag and drop and place any Windows
anywhere you want so once you have
layout your happy win you can go up here
to the top right corner where it says
default you can click on it and here
you've got a bunch of layouts so you can
save your new layout so I'm going to
save this one as kitchen chaos and then
over here you can select anyone you want
for example if you ever have some issues
with any kind of weird editor Windows
you can load back the default layout and
then go back and load your own layout
okay so with that our layout is set up
the next important thing is setting up
visual studio so let's do that in the
next lecture
hello and welcome I'm your code monkey
in this lecture we're going to set up
our Visual Studio alright so with the
Intel layout setup let's make sure
Visual Studio is also set up correctly
I'm going to be using version 22
Community this one is the free version
you don't absolutely have to use the
same code ID that I'm using you can use
writer or vs code or whatever you want
so let's see my setup for visual studio
but first let's actually set up
something over here in unity so let's go
up top into window and then let's open
up the package manager then over here on
the drop down menu let's select the
packages and select the ones from DNT
registry then let's scroll down to find
the visual studio editor package so here
it is this one this package basically
handles the integration with visual
studio so you can use the debugger and a
bunch of things alternatively there's
also a package over here for visual
studio code and there's also one over
here for jetbrains Rider so if you're
using a different IDE go ahead and
install the package for me I'm going to
install the visual City one so this one
just go ahead and install okay it's done
so next let's go up into edit and let's
open up the print preferences then over
here let's go down into external tools
and on the external script editor make
sure you select the one you're using so
again for me I'm using visual studio 22
and also over here you've got a bunch of
extra options now if you want to play
around with reading the source code for
the very CNT packages then you can tick
on these boxes but in our case for this
simple game we don't need that so go
ahead and leave everything just like
this with defaults okay so with this
setup now we can go over here into
assets and open up the c-sharp project
and this should open up visual studio
and alright so here it is now for some
more settings inside of here in my
visual studio I have a really nice
extension that adds a bit more colors to
my code which makes it easier to read
and write so up top let's go into the
extensions menu and manage extensions
and the important one that I've
installed is this one vs4 if you want
you can go into the online Tab and over
here search for it any Apple that show
up in here then for the settings on that
extension let's go up here into tools
and let's open up the options then over
here let's scroll down and find vs4 Yep
this one and here are all the settings
and expand this and a bunch more
settings now for me I think these are on
the defaults I don't remember if I
changed anything the important one is
over here the rainbow braces so these
have a bunch of Commerce which make it a
bit easier to read the code so let's
create a simple script just to see this
so back in until let's go into the
project window let's click the plus icon
and let's create the brand new c-sharp
script let's call it just testing wait
for it to compile and now let's open now
over here I'm just going to write a
bunch of simple code just to test it out
you don't have to follow this alright so
here's a bunch of sample code these are
the colors you can see it makes
everything a bit easier to read although
again this is not a requirement you
don't absolutely need this extension but
personally I do find it quite useful I
find that it helps make the code more
readable than having everything be gray
okay so that's the setup for this
extension next for the text formatting
options so once again let's go into two
holes go into options and then over here
let's go into the text editor then over
here I think I've got pretty much all
the same defaults then we can go into
the c-sharp rules so here are all the
settings if you notice something
different on your end go ahead and pause
the video and compare the settings but
again I think everything here is pretty
much defaults I believe the only
difference that I did was over here on
the code style over here for new lines
personally I like to have the currently
brackets on the same line but if you
want you can also change it and put it
on the second leg I think that's pretty
much the only difference that I did
everything else should be exactly the
same as defaults so that's the code
sound settings and speaking of that the
next lecture is very important we're
going to talk a bit about naming rules
although just before we go let's just
clean up our testing script so let's
close this one click on the X then back
into Unity we don't need the script so
let's just delete it okay so with that
we have Visual Studio setup and ready to
go now let's continue in the next
lecture to learn about some naming rules
hello and welcome I'm your code monkey
in this lecture we're going to learn
something extremely important let's
learn about naming world this one is a
very important lecture that you should
definitely refer back to whenever you
have some questions so first what
exactly are naming rules these are
really just rules you follow when
writing your code it is extremely
important that you are consistent in
applying your own rules you don't want
one class in your game to be written a
certain way and then a different class
using a completely different style that
would create tons of confusion so naming
rules and writing the code correctly is
very very important one mistake that I
see a lot of beginners do is they send
me some code and ask why it's not
working then I take a quick look and I
see that all of the code is written in a
very messy way some functions are on
lowercase others using snake case some
films are in personal case some in camel
case and so on remember that code is
case sensitive so it is extremely
important that you write the code
correctly if you change a character from
lowercase to uppercase then you are
suddenly referring to something
completely different if you're a
beginner keep that always in your mind
code is case sensitive so don't just
write code semi-randomly write it
properly as if you were doing an English
literature test now with that said when
it comes to naming roles you can use
whatever name neurons you want different
people like different rules for example
you can use a prefix in your variables
you can use a postpick you can use
capitals for consonants chemical case
for properties snake case for Fields by
the way here are the definitions of what
those terms actually mean Pascal K
starts with a capital and every word is
capitalized camel case starts lowercase
and then uppercase for the first
selector of every other word kind of
like a camel hump in the middle and
snake Haze is where you add an
underscore in between the words I send
every rule can be valid the important
thing is that you are consistent in
always following through with your rules
as you might know Unity mono behaviors
have some deformed functions you can
Implement things like start and update
which are written using pastel case
since you can't really change in these
rules at least on function names I would
say you should base your rules off of
theirs so for functions you should
probably be using Pascal case for the
rules like I said choose whatever makes
sense to you here are some of my own
personal rooms that have developed
jumped over the last 10 years and the
code sound that I won't be following in
this course for functions I use Pascal
case just like unity and just like the
c-sharp standard for function parameters
I use camel case for Fields also camel
case properties are in personal case
constants are in uppercase snake case
then another rule is that I like to add
the top of the variable as a postfix so
if it's a list type in the list if it's
an array open array and now you might be
thinking with this wouldn't it be an
issue if we change the type then the
name is suddenly wrong and the simple
solution for that is that if I change
the type then I just use Visual Studio
to quickly change the name that's it
then for the currently brackets like I
mentioned in previous lecture I like
them on the same line some people have
some very strong opinions about this
really it's just a visual style and this
is the one that I personally prefer if
you like new online then go ahead and
use that it doesn't change how the code
Works in any way in a final rule spend
some time deciding on a proper name and
don't be afraid to rename things you
will note how all the code that we're
going to write in this course has proper
names for everything you should never
use a variable with a single letter like
X X or k the exception of course would
be iterated in a for Loop also don't use
acronyms or abbreviations those might
seem player right now but in a few weeks
you might not remember what they mean
remember you don't get bonus points for
writing extremely compact code so
prioritize making your code readable and
understandable even if it requires
variables and functions with long names
so these are my general rules and the
code style that I personally follow
figure out what works for you and follow
your own naming rules but naturally in
this course I will be using my own code
cell so if when following the course you
are not sure how to write some type of
code you can refer back to this lecture
and watch it again like I've mentioned
many times the code that I won't teach
you how to write in this course is on
the exact same level of quality as my
paid courses and my Steam games so as
such because that this lecture these
naming rules are all extremely important
okay so with this very important lecture
out of the way now let's start playing
with some visuals by importing some
Assets in the next lecture hello and
welcome I'm your code monkey in this
lecture we're going to import the
project files with all the assets that
we're going to use by the way remember
that if you have any questions go ahead
and post them in the comments I go
through those every day and I'll do my
best to help okay so with the project
created the next thing we want is to
import the assets that we're going to
use to make this game you can download
all of the assets with the link in the
description which by the way like I
mentioned a while ago that link contains
a Unity package that contains both the
assets and the final game so when you
download that you get ENT package just
go ahead and double click or click and
drag and drop it on the projects window
here is the asset import window just
make sure you select all and let's
import okay so here it is let's import
the assets folder and inside comes all
of the assets meshes textures and so on
so everything we're going to need and
then it also imported inside of it
another ENT package so if you want to
import the final project with all of the
code already written it's also here if
you extract this one you're going to get
the complete project files now of course
don't do that if you want to follow
along with the course and be aware that
if you're following along and you
accidentally end unpack this one it will
override all of your own files so if you
want to inspect the final project files
go ahead and do that but do that in a
separate project in order to make sure
that we have no accidents I'm going to
delete this one from the current project
so just go ahead and delete okay so
that's it and over here we've got all of
our really nice visuals we can look in
the prefabs visuals and over here we've
got a visual for a container Sergo
that's a container counter then we have
a cutting counter we've got a trash bin
then on the kitchen object visuals we've
got all the visuals so a block of cheese
we've got some burned meat we've got a
plate and so on these are all the nice
3D models that we're going to use in our
game and then over here on the textures
folder we also got a bunch of General
icons as well as actual icons for all of
the various parts okay so all of the
assets have been important now let's
continue on to the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to set up
post processing now here let me make a
quick note usually when making your
games you probably don't want to hand on
post-processing right way you should
first get an ugly prototype up and
working before worrying about any
visuals so normally I would only add
post-processing much later on in the dev
process but since this is a course in
video format in order for the video to
look a bit more appealing let's set a
post processing right away now we
already have the project set up to use
urp so adding post-processing is
actually super simple it's actually
already added by default first before we
do that let's rename our scene with a
proper name so inside the scenes folder
it starts off with sample scene this
will be our main game scene so let's
just rename this to game scene okay and
now here on the hierarchy we can see by
default this scene already contains a
global volume game object this is how
you actually add post-processing and by
default you can see that it also already
has a sample and profile attached this
is how you add all of the various
effects you can click on this link and
it will show it over here on the project
window now let's film this from scratch
instead of starting from this one so
let's go into that file into that asset
and just delete it okay so now we have
no value profile now let's go ahead and
click on new to create a brand new one
okay so now here we can add overrides
add all of the effects that we want
let's drag some visual meshes that we
imported in the last lecture to get a
better look at all these effects and
what they do so first let's make some
kind of more so let's make a 3D object
let's make it a plane let's name this D4
also one extremely important thing
whenever you create a brand new object
always check the object's transform
position by default when you create an
object it appears in front of the scene
camera which will probably not be on
zero zero zero you always want to be
very careful with the position of your
actual objects so for a plane we do want
this to be on the origin so on zero zero
zero so make sure you always do that
then let's scale it up a bit so on the
scale let's put it on 555 which by the
way you've got this nice little icon
this was added in a recent Indie version
basically if you enable this and matches
all of these values so if you just
change one of them it changes all of
them so let's put this on Five okay
great now for the visual let's go ahead
into the mesh render on the materials
and let's select the brand new material
so let's click on the circle icon and
over here let's find the floor material
so here it is it's the one included in
the assets there you go we've got a nice
basic form material now let's also drag
the player visual so let's go inside the
assets folder and over here let's go
inside the prefabs visuals and down here
we find the player visual so let's just
go ahead and drag this one so there it
is a nice player visual let's also drag
a counter so let's find let's say the
Clear counter let's drag this one let's
rotate it to face the camera something
like this and let's also put a cutting
counter again we're just placing some
visuals just so we can see what the post
processing will do and let's also place
a bunch more things so let's say a
tomato let's place a tomato over there
and maybe cabbage all the way over here
okay so we've got a handful of nice
visual elements so we can test out our
post pressing by the way here's a quick
empty tip on scene controls whenever you
are on the scene view which make sure
you're on scene View and not game view
those are different so on the scene view
you can move the camera with a mouse you
can pan with mouse 3 so the middle Mouse
button so hold that and pan around we
can rotate with the right Mouse button
you can rotate around Point by holding
down left alt and left click and just
drag it around to rotate around an
object you can select an object like for
example player visual then you can press
on F to select that object and now if
you hold alt and click it will rotate
around that object also another method
is you can hold the right Mouse button
to move it around and then you can use
was to move so d a and so on then you
can even press shift to move in faster
and you can use the scroll wheel while
holding down the right Mouse button or
to modify the speed at which you move so
there are plenty of camera controls to
really get you seeing exactly what you
want to see now for another quick empty
tip you can move the scene camera to
where you want the game camera to be so
let's say I want the game camera to see
things from about this angle so you just
position the scene camera then on the
hierarchy select the camera game object
so the main camera right here and with
that object selected you press Ctrl
shift and F and if there you go you can
see over here on the camera preview let
it position the main camera looking on
the exact same position at the exact
same direction as the scene camera set
the shortcut Ctrl shift F or
alternatively go up into game object and
over here on line with view now if you
look here is the scene View and over
here we've got a nice camera view so
just position the camera somewhere where
we can view all of the Assets Now with
this let's add some post processing
effects so first let's select the global
volume game object and over here we can
add all of our effect overrides first up
let's begin by adding tone mapping so
there you go we've got the effect and
over here we've got a nice little
checkbox so you can enable it in order
to enable this effect and set one of the
options now for this one I'm not too
familiar with color correction but I
find that usually adding a neutral tone
map usually that helps also make sure
you're looking at the game View and not
the scene view if you're looking in the
game View and you enable and disable
this effect you should see a difference
whereas on the scene view if you enable
and disable it doesn't actually show
that even if you're on the scene view
over here you have all the effects
enabled even with that some effects for
some reason don't show up on the scene
view so when playing around these
effects almost make sure you're
unlocking through the game view so like
I said you should be able to toggle this
and see a visual difference on the game
view if you don't then make sure the
camera has post processing enabled so
let's select the main camera game object
and down here there's a tongue for post
Crossing make sure this one is enabled
and then also on the render pipeline
assets so let's find that one on the
project window over here we've got the
settings and we've got the urp High
Fidelity this one should be using a
renderer so if you click on the renderer
over here you should have post-rossing
enabled again all of this should already
be correctly set up by default so if
you're going to take a global volume
enable our disabled you should see a
visual difference okay so next Effect
one that I always like to add is a bit
of saturation so let's add an override
post processing and let's add a brand
new here it is color adjustments then
over here you've got plenty of things to
play around with for me I like to add a
bit of saturation so just lift it up a
little bit let's say just about 20 and I
also like to add a little bit of
contrast over here and let's also add
20. and there you go it makes the colors
pop a little bit more so personally I
don't like this effect then later on
we're going to have some glowing objects
for example the stove let's actually try
dragging that into the scene so let's go
into scene View and in the assets let's
find the stove counter so here it is and
inside the stove counter there are some
things so here it is the stove on visual
this one is disabled by default also on
the inspector let's just enable on this
game object to make it visible again
don't worry about the positioning of the
objects on the scene view right now
we're only positioning them just to set
up the post pressing we're going to
delete them all at the end of this
lecture okay so now in enable let's go
into the game View and over here we see
the stove enabled so now let's go into
the local volume let's add an override
go into post pressing let's add a volume
effect so right now notice how that one
is not glowing red hot for that work we
need to have Bloom and we need to enable
the threshold and the intensity if we
raise the intensity we do see yep there
we go a really nice low there by the way
here's a quick visual attempt if you
want to make your game feel a bit more
ethereal and magical one good way is to
put the threshold that on low value
below one so something like 0.5 and then
put the intensity as a little bit and
with this notice how everything has a
slight low even colors that don't have
any extra intensity so the floor is
glowing the character is going so
everything looks quite a bit ethereum
this is a bit extreme but it is an
interesting effect also another quick
note here in case you're not seeing
anything change make sure you go into
the render prop online assets so the urp
High Fidelity and over here make sure
AGR is enabled you can look at so low if
I disable it yep that one stops glowing
and with that enabled it does start
glowing AGR stands for high dynamic
range so that is how you can have a
color go with an intensity above one
which actually makes it low when you
have the balloon post pressing if even
with that you're still seeing issues
then make sure you go into the renderer
and over here for the post processing
sometimes Unity has a weird bug and
doesn't generate this post-process data
file so if that does happen just go
ahead untoggle and toggle this and it
should work and finally like I said on
the camera make sure you have post
Crossing in Arrow so with all that you
should be able to see the game view glow
okay back into our effects with our
balloon working like I said you can
lower this below one to get a nice
ethereum look but this is a bit too
intensive on what we want so let's make
it a bit more subtle so on the threshold
let's put it at 0.95 so there's a slight
low on the white Parts but nothing too
intense and for intensity let's put it
at a wrong number one okay so I think
that's a nice amount of Bloom all the
colors glow a little bit and we can see
over there the stove it is indeed
glowing okay great now if you ever
forget all these steps and you can get
your project to Glow I made a nice video
with a nice checklist of everything
needed for you low definitely go ahead
and watch that video whenever you have
issues then for another fun effect we
have yet so let's go into ad override
post Crossing and let's find the
vignette what this one does is adds a
bit of Darkness to the colors so if we
enable the intensity and we increase it
you can see what it does so it adds
Darkness around the corners there
personally I find this one looks good
when it's quite a bit subtle so let's
put the intensity at some like 0.25 and
then for the smoothness let's also put
it on 0.4 so just like that just a
slight Darkness on the edges so
personally I think it looks pretty good
and that's pretty much it for the Post
Crossing on the volume component I like
how this looks you can see difference
with the volume enabled or disabled
quite a big difference looks pretty nice
but again these are just visuals so feel
free to play around maybe add some more
effects using different settings these
are just visuals they don't impact the
game logic at all so feel free to make
it work exactly as you wanted then yet
another thing related to post processing
but not in this component it's some
anti-aliasing for that one place where
you can change it is on the main camera
over here you see a film for post
Crossing and you have a bunch of types
so fxa a or smaa or if you want some
more higher end post processing you can
go into the render prop online Essence
so urp and hyphenoly and over here we
see anti-analyzing msai this one is a
bit more expensive but looks a bit
better if you want to see difference you
can go over here into the aim View and
on the slider up top on the scale you
can increase this quite a bit so with
this we can now see the pixelation and
you can see over here if I switch at the
only thing from 4X back into the table
you can see lots of jagged edges and if
I put it on 2x Yep looks a bit more
smooth 4X a bit more smooth and 8x even
more smooth so with that you can see
difference on all the edges on the
things by default this renderer has on
4X and nothing on the camera this
already unlocks pretty good but to make
the video look even better I'm going to
put it on 8X and on the main camera I'm
also going to leave it with no
anti-alency you can combine them but if
you do then everything looks a bit too
wiry so I don't quite like that effect
so put this one on none and the other
one on 8X although again this is just a
visual so if you have a low end PC feel
free to go into the urp and over here
disable anti-alizing so the game looks a
bit worse but it won't run much better
okay let's drag the scale back down okay
now one final thing we can add is some
really nice screen space ambient
conclusion for that let's go into the
render so not the render pipeline asset
the renderer and over here by default it
already added screen space ambient
Collision if it didn't add you can click
on ADD render feature and over here you
won't be able to see it I don't see it
because I already have it okay so here
it is basically what this effect does is
it adds some tiny Shadows where geometry
intersect if we enable and disable it
quickly we can see the effect over there
on the counters so you can see with
default effects it already Works quite
nicely for example look there on the
player we can barely see the difference
between the head and body but if we
enable this it has that nice little
Shadow I think it looks really nice but
then we've got a bunch of settings we
can play around increase the intensity
the radius and so on Now One important
thing when setting all these effects is
to remember the point of view of the
camera in this case we're making a
top-down game so before we play around
these settings let's actually position
the camera in a correct position so
let's go ahead select the main camera
and let's position it above pointing
down so let's put it on an X of 0 on a y
of 21.5 on his head of minus 21.3 then
for the rotation on the X 46 then 0 and
0. and finally on the camera over here
on the field of view instead of 16
that's really wine for this game let's
go with 20. okay so this is the view
that we're going to use for our game let
me just rotate the object so they
actually face the camera so on the
hierarchy let's just select all the
objects let's rotate them all around and
just position them again we're only
using these just to see what they look
like we're going to delete all of these
objects in a bit okay so yep that's the
game view now that we have the camera
set up let's work on the settings for
the eminent conclusion so let's go down
select the renderer and over here for
the settings for the intensity and let's
put it on four for the radiance let's
put it at 0.3 and direct lighting
strength let's put it all the way up to
one okay so you can toggle this enable
and disable to see difference and yep I
do think these settings look pretty good
finally the last thing we need to check
is in lightning window so let's go into
window then down into rendering and
let's go into lighting how it pops up
the unlighting window personally I like
to Anchor it over there next thing
inspector and over here we're really
going to leave everything on defaults so
you can leave it as the lighting
settings assets and nothing assigned and
then on the environment tab over here
again all of the defaults I didn't touch
any of these so we've got environment
lighting from the Skybox and then some
multiplier of one so everything pretty
much on defaults although again like I
said most of these visual effects are
very much personal preference so if you
want to make your game look a bit
different than mine then go ahead you
can play around with lighting over here
you can change Skybox gradient color and
so on if you want you can use some bake
lighting then if you want you can add
all kinds of extra effects and also by
the way remember that the effects are
stored on this profile over here so for
example you can click over here on the
Clone button and it will include the
effects and let's click on it to find it
yep there you go so that's the one that
I've built and here's a clone one so if
you want you can make a clone one and
then make it look very different for
example let's go into chromatic
aberration make it really intense and
for example let's go into the counter
curves and over here for some reason
let's drag the green up and so on so
there you go completely different visual
so if you want to play around make some
weird effects and if you want to go back
to just revert back into the original
profile personally I'm quite happy with
how this looks so I'm going to be using
this one okay again you can enable and
disable the volume game object to see
quite the big difference that
post-processing makes if you ever want
to make your game look quite a lot
better always make sure that some post
processing alright so like I said this
looks really good I like it now before
we go to the next lecture let's just
clean this up so let's get rid of all of
these objects so the counter cabbage
tomato and so on let's get rid of all of
them except the four so let's leave the
four and get rid of all these alright so
here we have our nice empty scene let's
just save our scene and let's get ready
for the next lecture
hi there this is a quick intermission so
how are you doing are you enjoying the
course so far are you having any trouble
with anything is there something you
didn't understand if so remember I'm
always active in the comments answering
all the questions so if there's anything
you need some extra clarification go
ahead and ask and I'll do my best to
help also remember to check out the pin
comment YouTube videos cannot be updated
so for any notes or comments I'll put
them in the pin comment and definitely
check out the website page for this
course as people ask more and more
questions I will keep that page updated
with any frequently asked questions for
every single lecture so that way you can
see what others have asked and learn
from them and you can also download the
project files for each lecture so keep
that page open on a second Tab and check
it every time you start watching a new
lecture I really hope you're enjoying
the course and I hope you've already
learned quite a few things go ahead and
hit the like button and subscribe to the
channel if you haven't already
okay so let's go to the next lecture
hello and welcome I'm your kudmaki in
this lecture we're going to begin
creating our character let's make a nice
character controller so we can move our
character in the world
okay so first let's begin by creating
the character game object
and now usually most beginner tutorials
will tell you to just right click go
into 3D object and create something like
a capsule that way you would have the
game object with the visual included
however for a good project structure and
good organization you should only
separate the visuals from the logic for
example here in let's say that I don't
want my capsule exam like this let's say
that I want my player to be a little bit
more skinny to do that I would have to
modify on the scale on this game object
so put it maybe on 0.7.7 so something
like this basically by doing that by
modifying the visual I also modified the
scale on the actual player game object
having a non-uniform scale on a logic
game object that can cause all kind of
problems with any kind of logic
component also I would prefer to have my
character on the floor but if I put it
on yf0 notice how the character is half
underneath the floor so if I were to use
this method I would have to apply some
kind of offset in order to make the
visual above the floor so that would
require rearranging all the logic to
work with an offset on the Y position so
because of those reasons and many more
you should not Place both the logic and
the visual on the same game object
instead you should separate them so
let's get rid of this and instead let's
create an empty game object let's name
this the player
let's put it on zero zero zero okay and
now inside of it now inside let's create
let's say a capsule now in this one we
can easily scale this to get any size
and shape you want so for example 0.7.7
then since the visual is a child of the
game object we can also easily offset
this so let's say you put it up by about
one unit so with this we can position
the visual so that basically the player
game object is over here on zero zero
and the character is above the floor so
we don't have any weird offsets this
will make all of our logic much more
simplified
and on this empty Parent Game object we
can attach all of the logic components
we want and then in the child visual we
can either replace whatever visuals we
want so as a general rule you should
always try to do this only separate the
logic from the Visions in your game
objects
okay so with that we have the player
game object now let's make our character
controller script
and before we do let's keep things once
again organized so before we do let's
create a brand new folder so let's right
click on the assets create a brand new
folder call it scripts and now inside
let's right click and create new c-sharp
script called the player wait for the
code to compound then select the player
game object and attach the script again
remember logic components go on the
parent game object not the channel
vision so the challenge visual this one
only has visual components and the
player this is the one that actually has
the logic components so let's open up
this script
okay so here's our first c-sharp script
like I said I'm going to assume you know
the absolute Basics go watch the c-sharp
basics video If you haven't seen it yet
so I won't assume that you know what is
a function what is a variable what is
start and update so pretty much the
absolute basics for a character
controller we first need some input from
the player and for that EMT actually has
two methods you have the Legacy input
manager and the new input system
basically the Legacy input manager is
super simple and very easy to use so
this one is perfect for quickly
prototyping and the new input system is
extremely capable with tons of features
but it's also a bit more complex so what
I do is while I'm doing a simple demo or
testing out a new prototype by just
using Legacy input manager but when
making a more complex project like for
example my sim game then at a certain
point I refactor my code to use the new
input system so here I'm going to teach
you both as well as teaching you how to
refactor code which is an extremely
useful skill so let's first begin by
using the Simpson Legacy input manager
we want some basic was movement to move
our character and we're going to need to
run that logic on every single frame so
let's do it on update and let's actually
get rid of the code that Unity writes by
default let's start coming from scratch
and let's get rid of this just close
okay so here let's start by writing
private void update and now here very
important if you're a beginner make sure
that update is written exactly like this
if you write update with lowercase if
you do this then it won't work the
function will not be calmed
automatically I'm pointing this out
because I have seen a bunch of comments
from beginners wondering why their code
doesn't work and it's as simple as this
with a lowercase Unity will not call
this automatically it needs to be
exactly perfect so again if you're a
beginner make sure you write the code
exactly the code is case sensitive so
this is very important
also another note you saw that the code
that Unity wrote by default when we made
a new script it just had void update it
did not have the private keyword private
is what is called an accessor you have
private then you have public and then
there are some more advanced ones
secondly you can omit the accessor and
in most cases it will default to private
however in writing good clean code you
should be as explicit as possible there
should be no room for misunderstandings
so while technically you could emit the
private you should always include it to
make your code easy to read and easy to
understand
this one is the first of many clean code
rules that I will teach you during this
course like I said all of the code that
I'm writing here is on the same level of
quality that I use in my own
professional games I'm not going to
teach you bad practices like so many
beginner tutorials do so always be
explicit always include the accessor
okay so we have our update Running code
on every single frame then to test if a
key is being pressed we just go inside
input then over here we've got two
functions so we have get key and get key
down
both these functions were turning Boeing
so that's how the true or false the
difference between them is that get key
down this one only returns true for a
single frame when the key is pressed
whereas get key this one stays true for
as long as the key is held down for
example for an action like jumping you
just want to know when the player
presses the button so for that one you
would use get key down however in our
case for a character controller we want
to know if the key is being held down we
don't want just one frame but always
so for movement let's make sure we go
with get game
then requires a key so let's write our
key code and then choose the key let's
say we want w
and then let's just put this inside and
if just like this okay so here we have
code we want to run while holding down
the down key let's do a quick test just
to verify everything is working
perfectly and for testing we can use a
super useful debug.log this one lets us
print a message in the console someone
said One log here just say something
like pressing and then let's also do an
else and if else let's do a debug.log
and just do a dash okay so here is our
very basic script let's make sure to
save it so Ctrl s then back in unity
over here make sure you have the script
attached to the player game object and
now we can test and now down here on the
console we can already see dashes so I'm
not pressing anything also like I
mentioned in the setup lecture if you're
seeing just one message then maybe that
means you have over here the collapse
Target if you talk on it and look how it
only shows one message but then over
here on the right side it says the
number of messages personally I prefer
to always keep it untoggle so I can see
every single message also over here on
the right make sure you have info
messages visible if you untangle this
and you don't see it so make sure this
one and actually both of them make sure
all of them are enabled okay so we're
seeing a whole bunch of dashes and one
more note if over here these chromebars
stop scrolling so right now you can see
it's stuck up instead of being down
there so if that happens one is easy way
to reset that is just click over here on
clear and it goes back into AutoZone
okay so we have the dashes I am not
pressing anything now as I press yep
there you go there's a message if you
don't see it make sure the game window
is in focus
so selective game View and click right
here on the middle to make this one the
focused window then if you press the
down key you should see the message and
if I Let Go yep there it is and I stash
okay great so all the basic logic is
working back in the code here now that
logic is working let's get rid of the
else here
and let's set this for all the other
keys so let's copy paste this so we're
going to need w a s and D so let's make
all of these
okay so we have our inputs let's also
get rid of the logs we don't need this
all right so we have all of our key
presses now let's construct a vector
with our inputs and since we're just
going to have two axes
the double s that is forward and
backwards and this one is left and right
so just two axis
so because we have just two let's use a
vector two and let's call it the input
vector
let's construct it so we'll do a new one
and start off at zero zero okay
then over here the logic is pretty
simple so when we press W then let's go
into the input vector and set the Y to
pause one
then when we have an S we want to go
backwards so put the Y on -1 for the a
we want to go left so that's an x on the
minus one and finally for the D that is
an x on plus one okay so with this we
have our correct input Vector let's do a
quick log just to test so debug down log
on the input vector
okay so let's test all right so we can
see in log zero zero okay makes sense
now if I press W yep we've got an 1 on
the Y if I press a we got minus one in
the X press D plus one press s and minus
one okay great so everything works
except we also need to be careful about
one other thing if I press both W and D
with this look at that the vector is 1 1
which is correct that's exactly what it
is then except the factor one one
actually has a bigger magnitude than
just one vector if we leave it like this
then the character will move faster when
moving diagonally versus when moving in
just one direction for our input Vector
we really want it to be normalized
meaning we wanted to have the same size
regardless of the combination of keys
that we're pressing so back in the code
here after calculating the input vector
and let's simply normalize it so we go
into the input vector and we set it
equals to input Vector Dot normalized
so this will normalize our input Vector
let's see and over here if I press
doubly you've got one press s minus one
okay so all those work now if I press
both W and D if there go now it says
0.71 when you combine both these I need
the math these do end up with a
magnitude of one so with this our
character will move at the same speed on
both diagonals and straights okay so we
have the input Vector on correct now
let's actually apply some movement for
that there are many ways of making a
character controller for example you can
decide to use physics or not over here I
want to keep the game simple so let's
not use physics instead let's just move
the player transform directly over here
we have our input Vector okay great now
we want to apply this to our character
position so first we access the
transform
this one refers to the transform where
this script is attached to
this script was attached to the player
so this is going to refer to the player
transform then we want to modify the
position so let's access the position
and now for moving we don't want to just
assign it if we do something like this
like this the player would never leave
the center of the world he would always
be near zero zero so instead we don't
want to just assign it but instead we
want to add onto it now if you're a
complete beginner and you don't know
this syntax then this one is exactly the
same as this so transform dot position
equals transform dot position plus input
vector so both these little lines are
doing the exact same thing personally I
prefer to use the shorthand I find that
equally readable and more compact okay
so we have this and we add our input
Vector to the transform position except
we can also see a really nice error
basically it's telling us that we are
mixing two types our input is a vector
two where we only have an X and Y but
transform that position is a vector 3
meaning it has an X Y and Z one simple
solution is to cast our input Vector
onto a vector three so we just convert
this from one type into the other one
and yep we don't have the error so let's
test and now if I press W any of the
character does move Let's ignore the
massive speed for now so it does move it
does seem slightly correct except you
can obviously notice that it's not
correct we are moving on the x-axis on
left and right that is correct but then
we are moving up and down instead of
fourth and back basically we convert the
effector 2 directly into a vector three
so we are moving on the X and Y axes but
in our 3D game we really don't want the
characters to fly so instead we want to
move on the XZ axis so back in code here
instead of directly casting this down
into a vector 3. let's construct a move
to your vector similar to Vector three
let's call it our move there for our
move Direction and over here we
construct a new vector3
and basically we're just going to assign
the input y to the Zenon here so first
of all for the X7 is correct so input
vector.x then for the Y let's leave this
one on zero and finally let's use the
input vector.y as I said on the Move
direction also now at this point you
might be questioning if we're using a
vector 3 here why don't we also use a
vector 3 appear and then just assign the
Z directly that's certainly a
possibility and for making a super quick
prototype I might even do that myself
but the proper answer to that is once
again all about writing good clean code
the input logically only has two axes
there's no z-axis on your keyboard so
logically it makes no sense for the
input to have three axes and beyond that
you should keep the logic separate so
you should first get the input and then
actually move the object we're going to
see the benefit of that separation when
we refactor this code to work with the
new input system doing that will in turn
make enabling Gamepad joystick support
super easy because we have the input
Vector separated from the actual
movement some of that to say and let's
do things properly let's keep the input
Vector separate from the movement Vector
so we just translate the X Y onto X end
and then we just apply this into our
transform position
okay so let's test so now if I press the
right turn left and press W and S and
there you go okay great so it is indeed
moving Left Right forward and back okay
great so it is working but as you can
see it's moving insanely fast you might
think the issue here is just applying
some sort of movement speed multiplier
except there's actually one sneaky issue
here on the game view on the top right
corner we've got a stats button and over
here we can see a whole bunch of things
specifically we can look at the frame
rate we can see that it's running at 144
frames per second over here on the left
side on this button I have vsync enabled
this will cap the frame rate to the
monitor's refresh rate so that is why
I'm seeing 144 Hertz I can overhear
disable vsync and the upload that goes
all the way up to 700. basically now the
game is running as fast as my computer
can run it and if I press the movement
keys and look at that now it's moving
even faster
now I've completely lost track of where
my player is this is not what we want we
don't want the player to move at
different speeds depending on the frame
rate we want it to always move at the
same speed regardless of frame rate so
when you do any kind of movement Logic
on an update you always need to make
sure to multiply by time dot Delta time
what this variable contains is the
number of seconds in Labs since the last
frame for example let's unlock to this
we no longer need the input Vector so
let's unlock just the time that down to
time okay so we can see there there's
basically telling us how many seconds it
is taking to render a single frame once
again note how I have vsync enabled so
I'm running at 144 frames per second and
now if I disable it let's see what
happens to that number so if I disable
and you have a look at that that number
is now much much smaller and the game is
now running much much faster so by
incorporating this value into our
calculation we are going to be taking
into account the frame rate
thus making sure that movement is always
frame rate independent right now with
this frame rate if I move you can see
I'm moving at this speed and now if I
enable vsync change the frame rate and I
move and I'm still moving at the exact
same speed
okay that's great except obviously it's
not exactly great it's moving way too
slow so let's also incorporate a
movement speed now for this once again
most beginner tutorials will teach you
to go all the way up here and find a
public float move speed
maybe they found it to some villain like
7f something like that
then you have this field and then down
here you simply use it in the
calculation so movement here move
multiply it by move speed and by time
dot time so this is what most tutorials
will teach you by making it public up
here what you're doing is you're
enabling access from the editor so if
you go over here in the editor over
there on the player we can see the move
speed variable we can see this exposed
and we can modify it this makes it
really easy for testing and for
iterating upon the value even while the
game is running
so the game is playing I can move and I
have this move speed now I can modify
this and yep now I got a different move
speed so I can use this to quickly to
rate and find the perfect value
so it's great to have this variable
exposed in the editor and this feature
is indeed the reason why most beginner
tutorials will teach you to make it
public it's so you can see it in the
editor that is indeed a very valuable
thing being able to easily iterate upon
important values is always very useful
however when you make something public
when you do that you don't just expose
the film to the editor you are exposing
it to every other class in your entire
code base so some other class could
access this field and set the player's
movement speed to something like zero
and you would have no idea that was
happening because the issue would not be
on this code right here I have an entire
video on this subject why you should not
make everything public this is an
extremely important topic to know about
this one tiny change will massively
improve the quality of your code
definitely go ahead and watch that video
to learn why such a bad thing and make
sure you don't do it so to avoid all
kinds of problems you should never make
films public so very quickly the obvious
alternative is make it private making it
private means that only this class only
the code in here only this can modify
this film so you know for certain that
no other class can ever modify this
however making it private also means the
editor cannot modify this film so we've
lost our very useful iteration approach
so what we can do to expose it just to
the editor is to keep it private and
then we add the attribute serialize
field
this way this field is still private
meaning that it can only be modified by
the code inside the player class but
with this attribute over here in the
editor yep we do have an editable field
so only the code in that class in the
editor can modify it nothing else can
touch it nothing else can read or write
which is exactly what we want one of the
main rules in writing good clean code is
minimizing complexity and one of the
easier ways to minimize complexity is
simply to minimize axis by making this
feel private we are minimizing
complexity because it doesn't matter how
complex our game is maybe our code base
is a thousand classes long it doesn't
really matter because only this class
can never touch this field so if we have
a bug related movement speed we know for
certain it has to be inside this code
and nothing else so we minimize the
things we need to keep in our head which
is always a very good thing okay so with
all that said we have our movement speed
and down here we are incorporating it
into our calculation just with this we
have our character working with a
variable movement speed and by using
Delta time we have our movement
correctly being frame rate independent
so here's our character and using the
keys I can walk around and yep the
character moves in any direction so we
have movement only working while using
the Legacy input manager like I said
we're going to learn how to refactor our
code to use the new input system
learning how to refactor is an extremely
important skill to improve your own
programming skills it is something that
you should always do when necessary it
will massively help you improve the
quality of your code
so we're going to do that but before we
get to that let's actually do something
a bit more fun and add some proper
visuals and animations to our player in
the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to replace
our boring capsule visual with a nice
proper character mesh okay so in the
included assets project files over here
if we go inside the prefab visuals we
see a nice player visual let's position
it inside the player game object so
let's drag it inside again because we
separate the logic and visuals this is
going to be pretty easy we don't need to
modify the parent game object at all we
just dropped the visualize this channel
that's it also again very important make
sure the visual is over here on low
composition zero zero zero only the
parent game object should move the
visual itself should never move if you
notice some weird positions as your
player moves and rotates always check to
make sure that the channel visual is on
zero zero zero okay so with this let's
delete the old capsule delete it okay so
here we have a pretty simple but really
nice character visual it's really just
two spheres stacked on top of one
another with a bunch of eyes very simple
for the visual itself the material is
using just a solid color so here it is
inside the assets material you can see a
bunch of player bodies with different
color these different colors they won't
be used in the upcoming multiplayer
video basically each player will have a
different color also by the way if
you're a complete beginner here's a
quick lecture on materials these are
materials and if we call it select we
can see a bunch of sets related to that
material basically the materials have a
Shader and then a bunch of properties
now the Shader is the actual code that
runs on the graphics card that says how
an object should be rendered by default
you have a whole bunch of included
shaders we're using the universal render
pipeline so you should mostly be using
the ones inside the urp and by default
you probably want to be using the
standard light Shader then of course you
can also build your own custom shaders
one excellent tool for doing that is
shade graph which I have covered in
detail in a previous video it's a fully
visual tool that you can use to make
shaders without having to write any
shutter code it's a great tool I've also
made a bunch of tutorials on all kinds
of effects you can make although right
now we're not going to be using custom
shaders we're going to do that later on
the course but for now we're going to
stick with default light Shader so
materials have a combination of shaders
and the properties on that Shader for
example over here for the phone light
sharing you can see that it has over
here based map that has a counter field
this is what you can change to apply a
different color to your player also as
to how you apply a material to an object
over here on the player visual you can
see the objects are made up of a sphere
so this is the mesh and then the mesh
render this is the one that has the
material so both these are what stores
the shape as well as the visual for the
object the mesh is just a 3D shape but
just by some of the mesh filter doesn't
actually render anything so it needs a
mesh render which needs a material
attached to it so for example over here
on the hierarching let's right click on
empty space and let's create a brand new
Cube just to see it so if there you go
it does create an object and as you can
see it has a mesh filter and a mesh
render now to apply a different material
you can click on this little circle icon
and it shows you all the materials in
that project alternatively you can grab
the material directly from the project
window so for example the player body
just grab it and drop it in there or you
can also drop the material over here on
scene view as you can see as I Mouse
over different objects it applies that
material to a different object although
note that only works over here on scene
view it does not work on game view so
this basically sets the material over
there on the object right now one more
very important thing on materials if you
have multiple meshes only using the
exact same material and then you modify
the material it won't change the vision
while all meshes using that material so
for example if I modify the color here
put it on something different there you
go all three instances all three objects
that are all using the exact same
material they all update to the new
color if for example you wanted the head
to be a different color from the rest
then you would just create new material
so you can right click on the project
window let's create a new material then
you can give it a name give it colors
use a different shade or whatever and
then use this one for something
different so that's pretty much the
basics for materials and by the way if
you're a complete beginner and you have
questions remember to post them in the
comments and I'll do my best to help
like I said I want to keep this video
moving I'm trying to teach as much as
possible while still keeping the video
reasonable length so if you need any
further clarification on anything
specific just go ahead and ask in the
comments okay so when materials are out
of the way here we have our player with
visual let's just get rid of our Cube
okay and just with this if we test and
yep over here we already have a nice
player visual walking around okay great
except the player isn't actually
rotating ideally the visual should be
facing the walking direction so if I
walk down it should be rotated to face
down so let's have that doing that is
actually going to be pretty simple let's
go into our script here we are on the
player script and over here we already
have the movement Direction so we're
going to use this in order to make sure
to rotate the game object to face this
move Direction and for rotating and
transform there are many many ways to do
it one obvious one is to modify the
transform dot rotation however this one
as you can see works with quaternions
for me even though I've been doing Game
Dev for over 10 years I still find
quaternions quite a bit confusing so I
normally don't use this method another
method is to modify the transform dot
Euler angles this one is much more
intuitive and makes more sense to me it
works with regular Euler angles which is
much easier to understand if you don't
know that name it really just means the
angles that go from 0 to 360. then for
another method you can also use the
function transform Dot and look at this
one makes a transform look at a certain
point so it can be a transform Target
can be a vector three for one position
and anything like that so this is a very
useful function we could calculate a
point right in front of our move
Direction and look at it or finally the
method that I personally like to use for
this specific purpose which is just
modify the transform dot forward this
one has the normalized vector
representing the foreign axes and
importantly you can get it and you can
also set it so you have both read and
write you can read it to get the current
transform for it but you can also write
to it to essentially rotate the
transform so we can just assign this to
our forward Vector also by the way you
also have transform dot up and transform
dot right both these work exactly the
same way for example transforms are
right this one is extremely useful for
2D games but over here we're working in
3D so we want to transform that forward
and all we need is the forward Vector
which is really just in move Direction
so let's set this one equal Z move there
okay so just like this it shouldn't
really work let's also just clean up the
log we already need to see the Delta
time okay so let's see like this okay
here we are and as I move and you better
go and look at that the player object
does indeed rotate to face the move
Direction okay so it's already looking
great all right awesome however it also
looks a bit odd with how it's instant so
I move left and right look at that it
instantly rotates so there's no
smoothing nothing it's way too janky so
let's add some nice simple smoothing and
for that let's use a really awesome
really useful math function called lerp
it helps you interpolate between two
values I made a quick video showcasing a
bunch of uses for it you can alert
floats Vector 3s quaternions or just
about anything it's really perfect for
making some smooth movement or smooth
rotation so for that we can access the
function inside the vector 3 class so we
can find an alert then here we actually
have two options we've got learn this
one interpolates and we've got slurp
this one interpolates but with a
spherical interpolation basically if
you're dealing with rotations like what
we have here then we want to be using
slurp whereas if you're dealing with
just positions and you want to use so
here let's use slurp this one as you can
see takes an a a b and a t like I said
this interpolates between A and B based
on T so for example if T is zero then it
won't return the value a if T is one
then it won't return to Value B if C is
0.5 then it won't return the point in
between A and B if you want to learn
some more about interpolation and the
math behind this then I highly recommend
you look at my video on splines splines
are basically just a whole bunch of
merps put together so anyways over here
we can add some smoothing to our
Rotation by just using the current
transform.ford as our a
then for the B this one is our Target so
let's use the move there and finally 14
let's use time dot Delta time meaning
that with this over time the character
won't rotate towards our Target movement
Direction so just with this let's test
so here if I move to the right and you
have a look at that it is indeed
rotating it's way too slow but yep it is
rotating smoothly all right so let's
just add a bit more speed so over here
let's just find a float for the rotate
spin let's put it at some like 10f then
we just multiply it to times that down
time multiplied by our speed let's see
and move any up there you go look at
that much much better okay great so as
you can see everything works as I move
the character does rotate to face the
move Direction all right great so here
we have our character with a nice visual
all rotating to face the move Direction
now next step is we want to add some
nice animation so let's do that in the
next lecture
hello and welcome I'm your code monkey
in this lecture we're going to add some
animations to our player character now I
have already included some pre-made
animations with a pre-made animator over
here inside the Asus folder but let's
first do it from scratch so you'll learn
how to do it first to animate we're
going to need the animator component if
we go inside the player visual game
object once again remember all the
visuals go on the visual game object so
for adding the animator component we
want it on the visual and not on the
logic component so anyways over here as
you can see by default I already attach
it with the assets included but let's do
it from scratch so let's remove this by
default now let's add a new component
let's go on an animator also one very
very important thing here it's the
animator component not the animation
component these QR can only difference
the animation component this one is
actually related to unity's Legacy
animation system from a very long time
ago it's only here pretty much for a
backwards compatibility and for super
simple use cases so most of the time
make sure you're using the anime tour
component okay so to drive this animator
component we need an NM troller let's go
into our project files and let's create
and create a brand new animated control
let's call this my player animator then
let's select the player Visual and just
drag the controller on there okay again
if you have issues then you cannot drag
the animator onto the film make sure
you're using the animator and not the
animation component okay so with this we
have assigned our animator controller
now let's double click on it to open the
animated window and if you don't see it
then go into window then go into
animation and open up the animator
window and also if you still don't see
anything that maybe you might have some
issues with your layout if that's the
case then go on to the top right corner
layout and go back into the default and
then back into your own layout and
finally if you still don't see anything
on this window if you don't see defontes
make sure you have the object selected
in the hierarchy so with that you should
be able to see these states so this is
our animator controller now I have a
really detailed overview of the animator
and the animation windows in my ultimate
unity overview course so you can go
watch those lectures for some really
in-depth explanations about everything
this does basically the animator is a
state machine so you have various States
and you can create transitions between
each state by default you have these
three special States there's the entry
State exit and any state these are used
for making transitions but we don't
really need to worry about them just for
now first let's just make a basic new
animation and for that the easy way to
do it is to open up the animation window
so let's go up top into window go into
animation and open up the animation
window so here it is again that's a
different window that's animation not
anywhere and for me for this window I
like to dock it down here so there's a
nice timeline so I think this is good
okay and now if we select the object in
the hierarchy that has our animator then
we can see the text here so to begin
animating we've got a nice button to
create an animation so let's go ahead
and click on this and now let's give it
a name for now let's first make the
iPhone animation so let's just call this
Idol and name just like that we have
created an animation you can see the
animation window down here has changed
we now see a nice timeline showing the
time and also on the animated controller
you can see the new animation was added
as a brand new state so a new state was
created and if you click to select it on
the right side in the inspector you see
the motion so the actual animation
selected and you can also see that
there's an arrow pointing from the entry
onto the unknown state so that means
this one is going to be the default
State when the animated controller
starts it won't start playing right on
this state let me just point out one
more thing related to animations so on
the project window we can see yep here
is our animation that we just created
and you can see the inspector unlocks
just like this now if your inspector
looks differently that might be because
you accidentally created the Legacy
animation that has to do with the
previous animation system that I talked
about the one that is Legacy that should
really no longer be used so if you see a
different inspector then a quick way to
fix it is to click on these three dots
on the inspector these three dots then
you change the inspector into debug
inspector and over here you see a toggle
on foreign legacy so for the animations
that we want to use right now we do not
want to be using Legacy animations so
make sure this one is untoggled if in
our case is toggle just untoggle it then
go back into the normal inspector and
now yep it shouldn't look just like this
okay so we have our animation and now
it's on our animator controller now it's
actually make an animation so let's
select the animation window though and
again let's make sure to select the
objects and let's select the player
visual game object so here on the
animation window we see this nice little
red button this one enables or disables
recording so if you click on it you can
see yep the timeline is now red meaning
that we are now recording and now we can
do anything to any channel objects and
it won't record any changes we make now
note what I said that's very important
it needs to be challenged objects if you
select for example the apparent game
object then all of a sudden it stops
recording so you can only animate child
objects so let's select the player
visual let's enable recording then let's
expand the player visual let's make sure
that our timeline is on zero so drag it
all the way to the left and now for
example let's grab the head object and
let's move it just a tiny tiny bit
basically just move it enough in order
to make sure that the position over here
is in red meaning that we have recorded
a keyframe then let's drag the timeline
by a little bit let's go over here to
frame 30. this one is actually going to
be half a second and soon to be that
because over here on the samples this is
the frame rate for the animation so at
6C that means we have 60 frames this
makes one second so 30 frames would be
half a second you can also zoom out by
scrolling over here or dragging the
handles down here so let's go into 30
half a second and on this one let's move
the head by a little bit something like
this as you can see down there we can
note that I record the new keyframe and
now if we hit on the play button we can
preview the animation any upon like that
that does do exactly that so it starts
off down and then moves up okay so
that's great but we don't want to snap
back so let's actually add another
keyframe right at the end so let's stop
playing the animation and to make sure
we have a perfect Loop let's just click
to select the keyframe let's press Ctrl
C then let's go down into the one second
Mark let's press Ctrl V and there you go
there's the exact same keyframe so now
if we hit on play the other go we have
our nice seamless Loop so the head goes
up and down and repeats forever alright
awesome okay so that's great now let's
also do one thing let's also record a
keyframe on the body however we don't
want it to move at least not in this
idle animation we just want to have a
static keyframe so let's select the body
and let me actually move it a bit to the
side just to make sure to record and now
manually we can modify things over here
here to modify the actual keyframe data
so on this one I don't want it to move
so let's put it all the way back at zero
just make sure we have a nice keyframe
recording now the reason why we are
recording the body position even without
moving it is because the wonk animation
will indeed move the body but when we
get back to idle we want the body to go
back to this exact position so that is
why we need the keyframe here okay so
that's done so we can stop recording so
let's click on the red button again okay
great by the way one more note to make
sure that the animation Loops go into
the project window and over here select
the animation and make sure on Loop time
is enabled it should be there by default
okay so the animation is set up and if
we unlock in the animator it's already
the default set so if we hit point we
should be able to see the anal animation
playing non-stop so let's hit play and
if there it is the anal animation with
the head moving up and down everything
works perfectly alright awesome okay so
next up let's make a wonk animation now
for me when making an animation that is
based on another one I like to actually
duplicate it instead of starting from
scratch so over here on the project
window let's select the anal animation
and let's duplicate it so Ctrl D let's
learn name this one to the wonk
animation and now if we select the
player Visual and then we go into the
animation window over here we see a nice
little drop down menu for all of the
animations except right now we don't see
the wonk animation we only see the idle
animation that is because this menu only
shows animations that are attached to
the animator so first we need to add the
animation onto the animator component
and how we do that is actually super
simple let's just open up the project
window and just write the wonk animation
and drop it here that's it so with this
we have attached a new state to the
animated controller and now if once
again we select the object in the
hierarchy go into the animation click
the drop down menu any up now we do see
the wonk animation so let's click to
select this one and now for this one
let's make the animation so let's look
in scene View and make it bounce just up
and down so I'm going to enable record
go back here and for the body this one
already has a keyframe so let's go up
here move it a little bit and then copy
the keyframe put it the same one at the
end something like this so there you go
just goes up and down once actually
input it offsets it looks a bit better
so something like this by the way in a
bit we're going to replace these
animations with the ones that I made
previously so don't worry about making
the animations perfect unless you want
to do that okay so there you go that's
the animation although for walking
should be much faster so here's a quick
animated tip this top bar here lets you
select all of the keyframes within a
certain time so if I click the select
note how it selects both those keyframes
and also if you click and drag once on
top of here you can select multiple
keyframes so for example to select
everything just click and drag to select
all of them and now you see these nice
little vertical bars so if you click on
those and then you drag them you can
basically modify the time of all the
animations and everything matches up so
for example let's make this one super
fast let's put it just 20 frames there
you go now it's a much faster walking
Mission okay great let's click on the
right to stop recording all right and
back in the animator so over here we
have both animations and now what we
need is to make a transition going from
idle into wonk otherwise the wonk
animation will never play so how we make
a transition is also super simple let's
right click on the I don't say let's
make a transition then now we have a
nice little arrow under the mouse and
now if we go into the wonk and click on
it there you go we have a nice
transition now we can click on the
transition itself to select it and over
here in the inspector we see a bunch of
transition options so let's expand the
settings yep there you go everything now
like I said I covered all of these
options in a lot of detail in my
ultimate TNT of recourse so if you want
to learn more go watch that here on
let's just learn the basics for how to
achieve our goal and making a simple
player animator the important one is
over here the exit time basically if
this one is toggled then this transition
won't be triggered automatically meaning
it won't play the outline Mission and
immediately transition into the walk
animation so for example if we hit play
and look at it quickly if there go
there's the idle any of transitions into
wonk and now it stays there forever okay
so that's good but not exactly what we
want we want the Wonka mission to only
play When the character is walking and
when it stops we want to go back into
the idle animation now for that we need
to use animator parameters so back in
our animator on the top left corner we
see something called layers we don't
need to worry about that for now and
then next week we see parameters then we
can click on the plus button or to
create the brand new parameter and you
can see all the various types that we
can create now for wonky we want
something that we can set to either true
or false so let's go with a nice bullion
and for name let's go with is wonky
again pay very close attention to the
capitalization this is extremely
important just like code is walking is
different from is walking so make sure
the capitalization is perfect okay so
with that we have our nice parameter now
let's click on transition going from
idling to wonk and now let's untick exit
time we don't want this transition to
trigger automatically and as soon as we
do we see this nice little warning
basically it's telling us that this
transition will never happen so over
here we have the nice conditions if we
click on the plus icon we can add some
conditions and for this one we want this
transition to happen from idling to walk
when the parameter is walking is set to
true so that's it this is our transition
now let you see the reverse so let's
right click on the wall make Transition
go back into Idol let's click the select
transition get rid of the exit time and
conditions when is Walking is set to
false okay so just like this our basic
animation logic should be working so
let's test so here we are and the
character is playing the online Mission
by the way you can look at the end
better while the game is running so let
me just drag the animator window just
drag it and put it on the side of the
game view so we can see both at the same
time okay great and right now note how
it's not updating so there's nothing
moving over here on the animated
component that is because like I said
you must select the object so on the
hierarchy make sure you select the
player Visual and you have there go now
you do see that updating so make sure
the object is selected in the hierarchy
and over here we see a nice little
progress bar showing the Adeline Mission
constantly playing in looping okay great
another important thing is over here the
parameters you can manually change the
state of these while the game is running
so for example if I click it's going to
trigger the is walking parameter which
should trigger this transition and
should go into one so if I click and if
there go transitions into the wonk
animation and now yep it is playing The
Walking animation and if I click to
untick it look at over there what
happens untake and there you go
transitions back into idle alright
awesome so as you can see we have
overall logic working we have the
animator with both of our states and by
changing this parameter we can change
which animation is playing now of course
the goal is not to trigger this manually
by clicking on it but rather doing it
through code but at least for now we
know that our animator is fully set up
again if you want more detail on the
animator and animation windows and
everything related to animations then
check out those lectures in my ultimate
TNT overview course and also later on
for more advanced use cases I have video
on the animation rigging package this
one is for more advanced use cases for
making Dynamic procedural animations
it's really fun so definitely check it
out but only after finishing this course
that one is a much more advanced duel
for now let's continue here so we want
to trigger our parameter but do it
through code and again here we have yet
another clean code question technically
we could add that code directly over
here on the player script we could just
grab the animator component and change
the parameter and in this case for this
very simple game that would actually not
necessarily be a very bad approach since
the game is so simple with so few
animations but like I said I want to
teach you proper good practices so let's
make it properly and actually separate
the animations from the logic for then
let's go into our project right click in
our scripts folder create a new c-sharp
script let's come with the player
animator let's select the player visual
game object and attach the component
okay so now here first let's grab the
animator now one approach is like we've
seen we could just make a serialized
film and and drag the reference in the
editor that's one approach or
alternatively since the animator is
attached to the same game object as this
script then we can just do a get
component both approaches are really
valid so here let's use get component
just to see a different approach so we
just have a field for our animator so
animator and then we just do a private
void awake and then awake lets you get
component of type animator and we set
our animator variable again like I
mentioned very important make sure you
don't mix animator and animation these
are two different components we want the
animator okay so with this we have a
reference to our end meta component and
now how we modify the parameter is
actually very simple we just access the
animator and then we have a bunch of set
functions you can see we have one for
each type so we've got a set bone set
float then down here a set trigger set
Vector so function to set any parameter
type now we made the Boolean so let's
use the set bone and this one as you can
see takes the name for the animator
parameter by the way strings are a
horrible horrible way of identifying
things but suddenly this system really
does require strings to identify the
parameter we want to change change if
you're wondering why strings are bad for
identifying things the reason is because
it's very easy to make a mistake for
example if you use is walking here then
this won't work however if you instead
right is walking then all of a sudden
does not work if your right is walking
like this doesn't work like this doesn't
work and even though it doesn't work it
will also not throw any compiler errors
that is because for the compiler a
string is a string it's always valid but
then when the code runs this one is
going to be different than our parameter
which is named exam like this always
remember that strings are case sensitive
so that's one reason why you should
never use strings to identify things
it's very very easy to make tons of
mistakes that are then very difficult to
find out but like I said in this
animator system we have to use strings
there's no other way in order to
minimize our usage of strings one thing
we can do is for example let's define a
constant up here so let's make a private
make it cons for a constant meaning this
will never change make enough type
string and conlet is wonky again refer
back into the naming wrong section for
constants we always use uppercase snake
case so is walking and let's set it with
is wonky again make sure you don't make
a mistake here make sure you type it
exam like you did on the animator then
down here let's use is one and now if
you do make a mistake so if we
accidentally use something different now
we do get a compound error so at least
we have a little bit of protection okay
so this one takes a string for the name
and then a simple Boolean for the value
so this is going to be the value that we
want to set to our parameter now for
this one we want to set to True when the
player is walking and false when it's
not so for that we need to ask the
player what it's doing so let's go over
here into our player class and let's
make a function to return just that so
let's make it public because we're going
to access it from another script we're
going to return a boom and call it is
wonky now over here we just need to
return if the player is walking so let's
make a local field to store that saved
so over here private bone is walking
again note the capitalization for films
we start with camel case whereas for
functions we have Pascal case so these
are different okay so basically in order
to Define if we are working that's very
simple it's just down here we have the
movement Direction so we are walking if
the move direction is different from
Vector 3.0 which by the way Vector 3.0
is just a shorthand for writing zero
zero zero so if the movement direction
is different from zero then we are
indeed walking so we Define that we
update that film on every update and
then over here we just return it okay
just like this and now back in our
player animated component over here
first we need a reference to the player
so let's add it here let's add a
serialized film of type player and we
need to compound this in order to drag
the reference so let's just come without
this line just make sure the code
compounds now here with the code
compound let's write the reference of
our player okay that's it and then over
here for the animator set is wonking
let's go into the player and let's ask
is walking and of course we don't want
to do this just on awake we want to do
it on every single frame so let's do a
private void update and on update let's
do this alright that's it so this should
be working let's test so here we are
starting off as Idle and as I move yep
there you go it is playing The Walking
animation and now if I stop and if there
go back into idle alright Awesome
everything does work perfectly okay
great we can can even look at the
animator to see the state change so here
with both side aside and with the
objects selected in the hierarchy right
now you can see he's walking his phone
so it's on idle and as I move that one
stays true that one goes into wonk and
now if I don't let go if there and go
back into falls back into idle all right
awesome so with this everything is
working perfectly if you're having
issues make sure you pay attention to
the capitalization so make sure the name
you wrote here is exactly the same one
that you wrote here and it's exactly the
same that you're using here alright so
all of our animations are working
perfectly now if you want you can go
ahead and make your own animations or
you can use the ones that I pre-bumped
so in the included project files inside
the assets here we've got the animations
and we've got the player with the idol
and the wonk animations if we double
click on this don't look at it you can
see yep it looks exactly the same so
there's a parameter called is walking in
our transition so everything is exactly
the same just over here let's select the
employer Visual and on the prefab like
we saw we already have the animated
component we just removed that one from
the prefab in order to build it on from
scratch but if you want to use my image
then we can just go ahead remove the
animator that we added and then right
click on this one on the remove
component let's revert back to changes
and there you go here we have our
animator with the player controller so
that's the one in the animations and
just like this if we had on play and
actually over here I found an issue
although in your case there shouldn't be
any issue because I've updated the
assets but this is a good time to teach
you about any issues with animations so
if you select the animation and you
select the animation and over here you
might see some of them in yellow saying
missing basically the way that
animations work is based on the actual
name of the object if it cannot find an
object with the exact same name then it
cannot load the same animation so my
problem is that when I initially made
the assets package I made this animation
and the object was previously named face
and then I renamed it the head so now it
normally loads so if you ever have
problems with loading animations just
make sure the name is perfectly matched
so in my case I can just click in here
in order to rename this keyframe on the
animation and I'm just going to use the
name that I renamed it so head and just
like this yep the animation does play
correctly so it's just a nice quick tip
if you ever have problems with and
missions always remember that the stored
keyframes their own stored based on name
so if you rename the thing in here or
over here on the game object if you're
in a name you're going to have missing
animations but if you make sure the
names match and the animation shouldn't
work perfectly so let's hit on play and
if there go there's the anal animation
and if I move yep there's the nice wonk
animation so everything still works
perfectly because it's only using the
exact same parameter alright awesome so
like I said if you want film free to
make your own animations or use the ones
that I've included for me I'm going to
be using these ones so the ones that we
made just for learning which I created
down here so the multiplier animator and
these animations I'm just going to
delete these just to keep the project
clean so just delete and just like that
okay so now there we have our character
fully working let's quickly handle our
camera
hello and welcome I'm your code monkey
in this lecture we're going to quickly
install cinemachine this is a Unity tool
that makes handling cameras super easy
our game isn't really going to have a
moving camera so this part isn't
strictly necessary but same machine is a
super useful tool so I definitely want
you to learn about okay so let's begin
by installing the package let's go into
window open up the package manager then
up top let's make sure we are in the UNT
registry make sure you're on the all Tab
and now just scroll down until you find
yep there it is send machine okay so
let's go ahead and install this
all right Sunstone so let's close this
and now the way that send machine works
is by creating what is called a send
machine virtual camera so let's go up
top into the game object menu then
scroll down into cinemachine and over
here you can see that we can create a
multitude of virtual camera types now
just by the names you can see how this
tool is insanely useful for example
making a free download camera doing that
from scratch is a bit tricky but with
same machine it is super easy for our
case like I said we want the absolute
most basic thing possible so let's just
create an empty virtual camera okay
that's it this creates a virtual camera
over here in the hierarchy and turn this
object has the send machine virtual
camera component and also importantly
when we added this it also added over
here on the main camera if we scroll
down we can see it has a sin machine
brain component basically the way send
machine works is it works on top of the
main camera so it doesn't replace it it
works on top of it and drives the main
camera so now that we're using send
machine if we try modifying the main
camera game object so there's one over
here if I try to drag the field of view
nope does not work I cannot move it if I
try to move the position nope can't do
it it if I try to rotate it nope that
does not work like I said when working
with cinemachine the sin machine brain
is what drives the main camera so rather
than modifying the things over here on
the camera itself what we need to do is
change them on the virtual camera so
over here we have pretty much the exact
same options that we have on the main
camera for example modifying the fov
over here we've got the lens so we can
modify the fov and if we look in the
game scene as we modify this one yep it
does modify the actual properties on the
actual main camera now this has tons and
tons of options related to everything
the most important ones are all kinds of
options down here for the body and the
aim so this is where the camera is
positioned and where it's looking at
using this you can make a funnel camera
in five seconds it really is insanely
useful if you want to learn about Sim
machine in more detail I have a
dedicated video on it I go through what
all of these options do then I also have
another super detailed video on how to
make a camera system with pan Zoom
scroll in both 2D and 3D and a bunch
more features again all of it using send
machine but in our case we really want
to keep it simple so let's just position
our virtual camera on the same settings
that we had previously so for first
let's set the film review so for a game
we want something narrow so let's go
with just 20. then for the position
let's put it above so zero on the X then
21.5 on the Y and minus 21.3 on the Zen
then for the rotation 46 on the X and
then 0 on the others okay so our camera
is positioned in the exact same position
and if we head on 20 yep everything
still works the same the camera is going
from the same point of view and the
character still works everything's still
exactly the same now since we're using
cinemachine we can easily add some
things on top of this like for example
we can add some noise to our scene
machine camera to make it smoothly move
a little bit this one is a fun simple
effect that can make our game feel a bit
more Dynamic especially in games like
this where we have a fixed overhead view
how we do that is over here on the scene
Mission virtual camera we've got a film
for noise so let's click and let's
select basic multi-channel purlin and
then over here we've got the noise
profile so we can choose one of the
included ones or we can create our own
profile so for example let's go with
handheld normal mild and by the way you
can actually modify these settings while
the game is playing so here it is the
game playing and you can see what this
effect does it adds a nice little wobble
to the camera and then over here at my
student frequency so we can play around
these so you can make it really intense
so something like this that is way too
intense so there you go quite a lot so
for something more subtle maybe put 0.5
and 0.5 there you go just a slight
little movement in the camera so this
would help make the game a little bit
more Dynamic so this could be a fun
effect although actually in my case in
order to make sure that the video
doesn't get way too compressed I'm
actually going to disable this on my end
so just set the channel noise to none
but you can see how easy it is to add
complex camera features when using send
machine and of course when using
cinemachine if you want you can use it
to make your game a lot more unique now
for me I want to design here where the
camera is fixed but let's say for
example you wanted the camera to
actually follow the player like I said
you'll watch that dedicated video tool
and learn all about cinemachine but over
here very quickly let me just show you
how to do that but at the same time
don't bother following this part it's
just to show what scene machine can do
that I'm going to revert back to this
state so first of all for testing one
great thing about scene machine is you
can have multiple virtual cameras you
can have as many as you want and then
the priority and the game object enabled
state is what defines which camera is
actually being used so for example on
this second one let's make it follow the
camera and put the priority on 20 so
that it's above then over here for the
body I'm going to select transposer
let's put it with World space it
requires a funnel Target so let me drag
the player as the final Target and put
it as slightly above and behind Okay so
it's pretty similar as before then for
the aim let me also drag the aim player
Target and just with this it should
already work so if I head on play if
they're going to look at that the camera
is now moving and following the player
so I can move the player anywhere and
yep the camera follows along so as you
can see it's this simple to really make
some complex camera movement doing some
complex camera logic just like this
would require a ton of work manually but
with thin machine it is super easy then
you can even play around with either
priority or enable and disable and there
you go see the machine even transitions
between the state of only your virtual
cameras so as you can see in lots and
lots of things you can make with your
camera very easily all thanks to
cinemachine like I said in my case I
just want the fix overhead camera so I'm
just going to delete this secondary
virtual camera and there you go just
this one on top looking at the player
and looking down with a low fov and Yep
this is the exactly the kind of camera
that I want for my game okay so that's
in machine it's a really awesome tool
for making camera handling much much
easier so this was a quick lecture all
about learning about Sin machine now
let's handle the tests that was actually
left and done quite a while ago let's
finally learn how to refactor code and
implement the new input system so let's
do that in the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to refactor
our code from the Legacy input manager
onto the new input system so the
simpleton character controller that we
made is working perfectly fine within
Legacy input manager like I said this
one is excellent for making quick
prototypes and demos as you can see it's
super easy to use
but now let's quickly refactor this code
to use the new input system instead also
like I said in the beginning of this
course here I'm going to be focused
primarily on building this game so for
example for any Unity tools that I use
like the new input system I'm going to
cover enough to be able to use a tool
and Achieve our goals in building this
game
of course every tool does a lot more
than just what we're going to use so
definitely make sure to watch the
dedicated videos Link in the description
for example the input system tutorial is
40 minutes long covering everything you
need to know about system whereas here
we're just going to learn enough to know
how to use it so let's refactor this
code to make it work with new input
system except before we work with new
input system let's just refactor this
code so we can completely decoup on the
input from the player class again we
want to focus on writing good clean code
so we should keep all of our input logic
in its own class that other scripts can
access remember the goal with clean code
is to minimize and manage complexity so
every class should do one thing and just
one thing meaning that the player class
should only handle the player and then
the input list should only handle the
input the only reason why I put this
over here in the beginning is exactly to
teach you about refactoring and how it's
a very common thing that you should be
doing all the time this is exactly how I
build my own games I start by making a
prototype and I write the input directly
inside the player class then at some
point I refactor the code to split them
up so don't be afraid to refactor code
it's a Perfectly Natural part of the
Game Dev process and actually a very
very good thing okay so let's make a
script just to manage our inputs let's
make a new c-sharp script call this game
input let's create an empty game object
give it the same name input as always
keep things lean so put it on zero zero
zero let's attach the script and open
okay so here's our script and let's get
everything related to the inputs on the
player for the input we are calculating
the input Vector then getting the actual
inputs from the keyboard and returning
the input vector
so let's put this on the other script so
over here let's make a new function
let's make it public since we want to
access it from the player we're going to
return a vector 2 and let's call it get
movement vector
now here let's really just copy paste
the exact same code that we have on
player so let's copy paste all of this
let's go and paste it here
okay so we get the input Vector we get
the inputs we normalize it and then
return the input vector
okay so that's it super simple also by
the way here we have an interesting
question
which is do we normalize the input over
here or do we do it over here on the
player both options can be valid you can
make it so that the game unplug glass
returns a regular input or you can make
it return a normalized vector you can
use either option but whatever you do
make sure you are explicit so over here
I am going to normalize input inside the
game input class however I'm also going
to make sure to rename this function so
instead of get movement Vector get
movement Vector normalize that way it is
100 clear this returns a movement Vector
as a normalized vector okay great
so now let's use this in our player over
here in our player class we need some
reference to our input class now later
on in this course I'm going to teach you
about the Singleton pattern but for now
let's just do a simple direct reference
again remember don't make it public make
it a serialized film private so over
here
let's make a serialized film private of
type game input and let's call it just
game input
okay so we have this we're going to drag
it in the editor then over here we
simply grab the vector 2 for the input
Vector we simply go into this one and we
get the movement vector normalized and
okay that's it no more errors let's just
make sure to save all of our scripts and
back in the editor let's go into the
player and just drag the reference for
the game input okay so just like this
everything should still work everything
should work exactly the same as
previously Let's test and make sure so
here we are moving and yep everything
still works I can move in any direction
okay so far so good
and what we have done here is
essentially we have refactor our code
and conveniently separate the input from
the player class this is an excellent
thing so again don't be afraid to
refactor code also what we did here of
putting the code in a separate class and
then doing a quick test to make sure
that everything soon works the same as
previously this is exactly what you
should do whenever you do some kind of
reorganizational refactoring in the end
you want to end up with the exact same
behaviors previously just with the code
organized in a different way okay so now
that we have this separate game input
class now we can very easily refactor
the Legacy input manager onto the new
input system so the first thing we need
is to install the package so let's open
up the package manager let's make sure
up here we are in the ENT registry make
sure we are in all and let's scroll down
to find the input system so here it is
let's go ahead and install
okay the package is installed and right
away we see this message basically it's
asking us if we want to enable the new
input system
now you could click on yes but let's
actually go ahead and click on no we're
going to enable it manually so click on
no then let's close this window and now
let's go up here into edit then let's go
into project settings then on the left
side let's go into player and now let's
scroll down expand over here the other
settings tab
and keep scrolling down until we see yep
here it is the active input Henley this
is where you can select which input
system you're using basically if you
click yes on that window it would
automatically set this option to use the
new input system so it would only enable
that one and can only disable the unless
input manager but like I said the lace
input manager is still pretty useful so
normally for me I prefer to enable both
of them so let's go ahead click on both
and this will restart the editor so okay
let's go alright the editor has
restarted so now the new input system is
now enabled okay so the way that this
system works is by creating something
called an input actions asset so on the
project files let's click on the plus
icon let's create something and let's
find the input actions so we need to
scroll down here so click on the little
arrow to go down and find the input
actions creates this file let's call
this the player input actions
okay now let's go ahead and double click
on it and yep there you go out pops out
the input system window basically this
one is where we're going to manage all
of the settings for all of our inputs
also by the way and like I've mentioned
if you're watching this in the future
and for some reason the input system got
a new update and changed this window if
so make sure you check the pinned
comment I'll keep it updated with any
changes on anything in this course so
over here we've got the action Maps then
we've got the actions and then we've got
properties now action maps are how you
can have different maps for example one
action map would be for the player
whilst walking normally and you could
have another one whilst driving a
vehicle then for the individual actions
in each action map and finally the
properties for each action again if you
want to learn about the entire input
system itself in more detail go ahead
and watch my dedicated video on it in
order for this course to not be 20 hours
long I'm really only going to use enough
to make sure that we can achieve our
goal so over here we just need one
action map so let's click on the plus
icon let's name this the player and now
for the actions right away we have a new
action
so let's just rename this one let's call
this action move then with the section
selected over here on the Action
Properties we can select the action type
again in the dedicated video I cover
what all of these mean
for movement we do not want a button we
want movement in multiple directions so
let's go with value then over here for
the control type for this one let's go
with the vector 2 and then let's expand
our action over here we can see our
bindings however we don't want this
default binding so let's actually delete
this one instead let's click on the plus
icon and over here for the type first
for the keyboard and let's go with this
one up down left right composite
so this one adds essentially four
bindings let's go ahead and name this
was
then for the up let's select the
bindings over here on the path let's
click on it then we can either find it
manually over here or click on the
listen and I'll press the W button yep
there you go W then for down let's go
ahead and listen s then for the unless
listen a and for the right let's listen
d
okay great so with this our input as it
is correctly set up one thing you must
never forget is up here make sure to
save the asset you can see this little
asterisk here that means we have unsafe
changes also alternatively there's an
auto save there but for now let's just
manually save the acid okay great
so now let's see how to actually use
this in our code there are many ways we
can use the input system one way is by
using the built-in player input
component so for example on the player
we would add the player input
so you could add this one attach and
input actions asset so this is our
player input actions then over here we
have various behaviors in order to be
able to trigger our actions but in this
course like I said I'm going to be using
the exact same code quality that I used
in my own Steam games so I will not be
using this component so let's remove
this instead I won't be using the native
c-sharp method so what's like the player
input actions and over here on the
inspector we see this nice toggle to
generate a c-sharp class
let's go ahead enable it and for these
films we can leave them all on defense
that's okay let's just go ahead click on
apply
and now it's going to generate those
scripts and compound them okay great
basically what this is doing is auto
generating some c-sharp code and on the
employer input actions we can see over
here yep we've got the generate script
if you want you can even open this to
see all of the source code now all this
like it says here this was all auto
generated so don't make any
modifications here
if you change anything any manual
changes won't be lost when you save some
changes in the input asset so if you
want go ahead and read through in order
to see how all this works but in order
to use it sectionally super simple you
don't need to worry about this script
first thing we need is to construct our
script class that was Auto General so
let's do it over here in our game input
let's make a product void awake and on
awake let's construct it
so let's do a new player input actions
so we construct an object of this time
so we have this although just like this
it won't be active so we need to
manually activate whatever action map we
want so let's go inside and let's go
inside the player so this is the action
map that we created and let's call
enable one okay so just like this it's
really already working all we need to do
is modify our code over here on the yet
movement Vector so for that we're going
to need to access this so let's actually
make this a member variable so private
let's store it up here instead of making
a local variable in here okay
so we have this one and then down here
on the input vector
let's go inside the player input actions
inside the player action map and then we
called it move so we've got this one and
then we defined it as a vector two so
over here we can call read value and
this one takes in the type of the value
now we Define it as a vector two so
let's read it as a vector two and just
like this this returns a vector 2 which
is really going to be our input Vector
so let's put it exactly like this and we
can now get rid of the rest of it all
right so that's it and just like this we
should already have everything working
exactly the same as previously
so let's just do a debug download just
to make sure so let's test so here we
are and the output is zero zero now I
press W there you go plus one minus one
left right and all of the ones in
between all right awesome so we have the
new input system all of it working
flawlessly also by the way over here we
can normalize the input just like we
were doing previously so we do it over
here through code or alternatively we
can also go into the player input
actions and over here there's something
called a processor so you can go into
this action add a processor and make it
normalized so these processes here can
be quite useful I cover the modeling
detail in the other dedicated video but
over here let's stick with making it
through code that works just as well
okay so that's our refactoring done with
that simple change we are now using the
new input system
so you can see how by refactoring our
code to make sure to use the game input
less when we change from the input
manager onto the new input system when
we made that change we did not have to
touch a player class at all the player
class just has the game input to get the
movement vector and does not care what
system he uses to get them so here we
have a very practical very excellent
example of the power of writing good
clean code because we separated things
correctly we managed to change something
completely and not have to make any
changes on any other class
so now that we're using the new input
system let's just quickly see one of the
main benefits of this system which is
easily supporting gamepads and more keys
for example a lot of people like using
ones but some people also like to use
the arrow keys with this system that is
super easy to add so let's go into the
move what's another one let's add
another one up down left right composite
let's call it arrow keys then let's just
put them so let's listen on the up Arrow
then over here we've got the down arrow
then we have the left arrow and finally
we have the right arrow alright so we've
got all the arrows and now we don't even
need to touch any code at all let's just
make sure to save the ascent which again
in turn that is going to Auto generate
the c-sharp class and go into compound
okay so we don't need to touch any code
at all let's just hit on play and now if
I move we're using the ones Keys yep
still works and if I go into the arrow
keys yep also still works alright great
now for another one let's make it for a
Gamepad so I just connected an Xbox
controller and we can see over here on
the log yep the game did identify it so
this is the new input system in action
let's once again open up the input
actions and over here on the Move let's
add another one and this time let's just
make it a regular binding and over here
on the path once again if we want we can
go down here and specifically find some
joysticks so you can find any of them or
once again let's just use in listen now
I'm just going to move the thumbstick on
the controller yep there it is I know if
you wanted you could go specific and
make it just work with Xbox controllers
or you can just use the generic left
stick this will make it work with an
Xbox controller or a PlayStation or
really anything so let's go with this
one and that's it nothing else we need
to do let's just save the asset and
that's it we don't need to touch any of
our code to make our game playable with
a controller so let's go ahead and test
so here we are and first of all if I
move the keys yep song Works move the
arrow keys yep both of them works and
now if I use my Gamepad any up there you
go everything works perfectly alright
awesome so as you can see this is one of
the main benefits of the new input
system it makes handling different
inputs really super easily as you saw we
didn't have to touch our code at all we
just had new bindings and just like that
our game is playable with all kinds of
inputs
so here you can really see just how
powerful new input system is okay so
with this our basic character movement
is working great we can walk around
everything looks great now in the next
lecture let's apply some collisions to
our player
hey again here's another quick
intermission I hope you've already
learned a ton from the course have you
seen the benefits of writing good clean
code has the course already helped you
understand some more advanced concepts I
really hope the answer is yes to both
those remember to follow the website
page as you follow along I won't be
adding frequently asked questions to
every lecture if you ever get stuck you
can just download the project files for
a lecture and compare with your own and
definitely check out the related videos
when I reference them this course is
focused on making this game but you
should definitely learn more about some
of these Concepts in more detail and you
can learn that in the videos that I
mentioned by the way if you're watching
this right now this is the secret con
loud so go ahead post the time step in
the comments with a nice monk Emoji I
want to see how many people make it this
far okay so that's it for now let's go
to the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to apply
some collisions to our player movement
okay so here we have our game so far we
have our player walking around and
everything looks pretty good however now
let's create over here in the hurricane
let's right click create a brand new
Cube so there you go let's place it over
here and push it down okay there's the
cube make it just a little bit bigger so
there's the cube and by default it has a
boxcon leather component so it has
physics and the player if I move and
nope there's our issue the player is
going right through the object now the
player is not meant to be a ghost so
let's fix this over here in our player
script we are hearing the input Vector
calculating the move Direction and then
just moving the transform so right now
we're moving it no matter what now
before we do that let's first do a test
to see if any object is in the way and
how we're going to do that is by firing
a raycast this one is a physics
operation that basically fires on laser
from a certain point towards a certain
direction and then tells you if it hits
something how we do that is let's go
inside the physics class and let's call
the raycast function
this one as you can see has many many
versions of this function with all kinds
of parameters let's use this one option
number seven which takes a vector 3 for
the origin a direction and a max
distance so first for the origin that is
from where we want to fire our recast
let's put the player object in so that's
transform dot position
then for the direction this is going to
be our move Direction so let's use our
move there and finally for distance
let's use some kind of player size
player width something like that
some lights to find up here a float for
the player size and put that 0.7 units
let's try out with the size just like
this okay so basically this returns a
Boolean it's going to return true if it
hits something and funks if nothing is
in the way so let's just do a bone call
it can move and basically we can move if
this raycast doesn't hit anything so we
can move if this one is false so if the
raycast is false then can move is going
to be true
that's very simple so if we can move
then we move the transform position
otherwise we don't okay that's it super
simple Let's test
so here we are I can move around and if
I go towards the cube and nope no longer
works so I can no longer go inside that
Cube okay great now in your case if it's
not working
first of all make sure that the cube
make sure it is touching the floor we
use the transform position as the origin
which is right on the floor so if the
box is raised up then you won't be able
to go through so make sure the cube is
touching the form also make sure the
cube has a box on leather component it
can be any type of calendar but you if
you made a cube then it should have a
box layer by default and it should have
the same shape as the visual
and also remember that the 2D and the 3D
physics systems those are completely
separate they are completely different
worlds so make sure you're using 3D
components and not the 2D ones so for
example if I add boxing weather 2D if I
add this one then it will not work so
make sure you're using the 3D and not
the 2D components same thing over here
on the script make sure you're using
physics and not physics 2D also finally
if you're still having issues make sure
you check the player position
again the player should be on a y of
zero the only thing that might have an
offset is the player Vision although if
you're using the same acid me then this
one should also be on a y of zero so all
of these on y of zero and then you can
also check the four by default this one
has a mesh calendar but if it is exactly
on yf0 with no rotation then it
shouldn't cause any issues alternatively
you can also just disable or remove the
mesh con leather from before since we're
not going to need that so with all that
yep everything works I can move the
player but I cannot go through solid
objects alright awesome so it is working
but for this particular use case a
recast isn't necessarily the best method
we should use basically Rick asses like
I said kind of like a super thin laser
but as you can see the player visually
has an actual body shape so the visual
and logic are using can only in
different shapes if I go ahead and push
towards the box you can see it works
just fine however if the player is a bit
more off to the side and the center of
the player right in front of it is not
the box and I move and yep there you go
now I am going through the box the
reason is because the erase accounts
being fired from the center of the
player and like I said it's kind of like
an infinitely thin laser so it has no
shape so as long as the center of the
player is not hitting the box and it can
go through it whereas what we really
want is for the visual and logic to have
pretty much the same shape so let's not
use a raycast over here on the code
instead of a recast we can use a physics
query with an actual shape
there are all kinds of casts you can use
as you can see all of them with
different shapes you've got a box cast
if you want to have a box a capsule if
you want the capsule or a sphere cast
all of these were pretty much the exact
same way except instead of a raycast
which fires an infinitely thin laser
these are going to have an actual shape
and for player controllers for the most
part you really want to be using a
capsule cast that's usually the
generally accepted player shape although
alternatively a boxcast also can work
very well in our case let's just go with
a simple capsule cast this one to define
a capsule has a 0.1 and a 0.2 by the way
if you have no idea what is a capsule
then we can go over here in the
hurricane let's right click create a 3D
object let's make it a capsule and there
you go this is the capsule it's kind of
like a stretch sphere so it has around
the top round bottom and then over here
in the middle it's just a cylinder and
over here for the raycast takes a 0.1
and a 0.2 so that is going to be the
bottom of the capsule and the top of the
capsule basically with those two points
we can Define the height of the actual
capsule okay so let's just get rid of
this capsule let's just lean it and over
in the code let's put those now 4.1 it
is indeed going to be the transformed
opposition since that is the point at
the bottom and for the second point
for this one it's essentially going to
be the player head so we can take the
transform dot position so this is the
bottom and we can essentially just lift
it up so let's add a vector 3 dot up and
multiply by some kind of player height
let's define up here a float for the
player height
and I tested it in the editor and the
player is about T and Stone
so over here let's go ahead and move it
up by that much
okay so next we want the radius so this
is pretty much the player size that we
defined previously so let's use the same
thing
but as always let's make sure to write
good clean code since now we are
referring to a radius let's actually
rename this to be a bit more clear and
by the way here's a quick Visual Studio
tip you can right click on a symbol and
then you can click on the rename option
alternatively use a shortcut Ctrl R
control R if you do that then now you
can change the name so for example on
player radius and note how it changes
every single instance of that variable
so this renaming feature is extremely
useful always make sure to rename
something if you find the name that
works best Okay so let's rename this to
play radius then we have Direction so
that is as usual going to be our move
Direction
and then finally we have the move
distance for that we can use the actual
move distance so that is going to be the
movement speed multiplied by time dot
all the time
so I just find here a fluid for the move
distance
and you should see that just move speed
time dot Delta time we have the move
distance and we use it both in here as
well as down here
okay so here we have our cancel cast the
rest logic is exactly the same so if
this one is false that means it didn't
hit anything so if it didn't hit
anything then we can move and then we
move the transform okay let's test and
over here now if I go towards the box
and the Epson works is only the same as
previously that's great and now if I go
towards the end and make sure that the
center is not hitting the box and I try
to move forward and nope now we no
longer go inside the cube so even on the
edges everything still works perfectly
alright awesome so it works it looks
good but it also is a little bit janky
for example let's stretch this cube out
a little bit so let's put it just on One
Direction so stretches like this let's
see now if I move towards it then nope I
cannot go through it so that is correct
and if I move left and right yep that's
also correct that works however if I now
press W and D at the same time in order
to move diagonally and nope right now it
does not move the reason is because the
diagonal Vector that one is indeed
hitting the collider but usually in
games when you move diagonally and you
cannot move in when Direction then it
tries to essentially hug the wall and
move around it so if I press wnd it
should essentially be moving straight to
the right so let's solve that so here in
our code we're making our Capstone cast
okay that's great then we need to test
if we cannot move so let's see if we
cannot move so it can move is false
if so then that means we cannot move
towards this direction
and if we can then essentially we
basically want to split the movement
Direction and just move on the X or just
on the Z so first let's attempt just the
X movement
so attempt only X movement let's create
a new vector 3.
let's call it move the year X and we
make a new Vector three let's take in
the move there dot X then zero on all
the other so we only want the test
moving in the X Direction
and then let's do literally the same
thing so let's get our can move try to
move under this direction so let's go
inside a move there move there on the X
so we do that capsule cast
and if we can move then that means we
can move only on the x-axis
so can move only on the X
and if so let's set the move there
equals the move there X
so if we can move them down here when we
use the move there we're going to move
only on the X
and if we cannot move
then that means we cannot move only on
the X
and if so then let's attempt only Zed
movement so over here again let's do the
exact same thing so let's copy this
let's just change this one so instead of
move to your X we've got moved here on
the Zen so over here we use 0 on the X 0
and Y and axis we moved here and get the
Zen then let's use this movement
Direction over there and finally the
same thing so if we can move
then that means we can move only on the
Zen and let's set the move there equals
the move there Z
and if not then we cannot move in any
direction
okay so that's it now this might seem a
bit confusing but it becomes a lot more
clear When You See It In Action again
remember the scenario we're trying to
solve which is when moving diagonally so
for example when we're moving forwards
into the right if we do that then let's
say this one is going to hit something
so we cannot move so if we are trying to
move both forwards and to the right then
we're going to only attempt the X
movement so we're only going to try
moving to the right and then we're going
to see yep going to the right that does
work so we can move and we're going to
move just to the right all right so
let's test and see if all of this is
working all right so here we are and if
I move straight to the wall and nope
there is 11 so I cannot move anymore
okay great now if I move just left and
just right and it does work now if I
press W and then D and if there you go
now it does hug the wall and continues
to move same thing if I go on the left
over here if I press D no I cannot go
through it now if I press D and S at the
same time and there you go it hugs the
wall and moves around so now our
controller is much more easy much more
understandable
okay so this is great now this is one of
those tiny things that makes your
character controller feel much more
responsive so that's great however we
also do see one more issue right now you
can see that I'm right next to the wall
and if I press A and D then look at that
I'm moving with this spin however now if
I press wnd look at that now I'm moving
diagonally and it's actually moving
slower basically this is the same issue
that we saw previously where we had to
normalize the input so we didn't go
faster in diagonals basically now we
have the opposite problem since we are
normalizing the vector we are cutting
down on the left right vector and with
that basically if we are moving
diagonally then we are essentially going
slower whereas if I stop moving diagonal
and just move left right it moves at a
different speed that solution for this
is really super simple over here in our
code when we are constructing the move
to your X and move the ears in when we
do this very simple let's just normalize
it so if this one is less than one then
it won't be going into one so let's
normalize that one and down okay that's
it let's test and now from here move
forward and hug the wall on left right
yep does work and if I stop moving
diagonally just going left right yep all
still works with the exact same speed
all right awesome okay so that's really
it as you can see it's super simple to
add Collision detection to your movement
scripts you just do a physics query to
testify our character should move and
just move it by the way if you want to
learn more about collisions and physics
queries there's a bunch of interesting
videos that you can watch for example
one is on various methods of finding a
Target then another one is on various
methods of handling projectiles and
finally another one is a very quick
checklist on why collisions are not
working basically there's lots of really
interesting things you can do with
physics so make sure you understand
these functions okay so now that we have
all of this working let's first just
clean up our scene so over here our
default Cube we don't want this so let's
just get rid of this and with this we
are ready to build our first kitchen
counter and let's do that in the next
lecture
hello and welcome I'm your code monkey
in this lecture we're going to begin
building one of our main game mechanics
we're going to make a kitchen counter
and handle the logic for the player to
be able to interact with that counter
okay so let's begin by making our
kitchen counter and just like we did
when we made the player let's first make
an empty game object and place the
visual inside of it so let's right click
on the hierarchy and create an empty
game object call this the clear counter
so it's going to be clear on top so we
can place and pick up objects let's make
sure to reset our transform so let's put
it on zero zero zero let's move it just
a little bit just so it's not exactly on
top of the player okay now inside let's
add the visual so let's go inside the
assets folder and then over here we've
got the prefabs visuals and inside we've
got the counters visuals and over here
let's find the clear counter Vision so
let's go ahead and drag it inside the
game object again make sure the
challenge visual is on zero zero zero
the unlockable position okay great now
just like we did in the online lecture
where we added Collision detection that
shouldn't already be working by default
but in order for it to work it needs a
physics line either however note how the
vision over here there's no collider and
inside there's no collider there's only
visuals again this is the same thing
that relates to separating logic and
visuals basically the visual prefab this
one only has visual components so only
meshes animations and that sort of thing
and the main Parent Game object this is
the one that is going to have all of the
logic components set means any kind of
scripts Behavior as well as any
colliders
so over here on the parent game object
let's add new component let's find a box
Collider again make sure you add a box
of leather not a boxing leather 2D and I
chose a boxing Ledges because this is
the shape that makes most sense for our
counter and now let's scale the boxing
leather again that's the boxing ladder
not the transform so leave that one with
a scale of one one that's good and over
here on the box leather for the size
let's put it up with a size that fits
the visual so 1.5 1.5 1.5 and finally we
just need to lift it up a bit over here
on the scene view you can see those
little green tiny lines these refer to
the boxing leather shape so let's lift
it up by a little bit in order to make
it perfect let's put it up by 0.5 on the
Y alright so there you go that one does
have the perfect shape
if we test just like this it should
already be working it's okay so here's
my player and if I move towards it and
yep there you go it does work so it is a
solid object I cannot go through it okay
great
let's just visually rotate the calendar
so let's do that and again for rotation
let's make sure we rotate the apparent
game object and not the visual we want
the visual to be on rotation zero zero
zero okay great so on the parent game
object let's just rotate it around by
the way here's a quick empty tap if you
want to rotate hold down control and
then click to rotate and now instead of
rotating on every angle it goes on a 15
angle increment so just hold down this
way you can easily get it to 180 degrees
so it's just for fun just make it face
the player okay great so now let's
interact with this counter and doing
this is actually super simple
we already learned how to do a raycast
to handle collisions and for
interactions that's exactly the same
thing
so let's go into our player script and
we're going to do a recast to handle
that
but before we do let's organize our code
here let's make a proper function to
handle our movement
so let's make it private since this is
going to be in local function return
void and call it handle movement
and then inside let's put all of this
code so let's copy all this put it in
there and then on update we simply call
this function okay great and now let's
make another function so private void
let's call it handle interactions
and we just call this function on our
update okay great everything is much
more organized so now here let's do a
raycast
so once again go inside physics do a
raycast
for the origin let's start on
transform.position
for this obviously we want the move
Direction so an approach would be to
make this a film variable sorted up here
so that way we can access it in both
functions however if you remember how we
handled the whole issue with the
diagonals basically we're modifying the
move Direction so for moving diagonally
then this one modifies to only move left
or right we don't want that for the
interaction we want pretty much the
exact same one even if it's pointing
towards a solid object so let's not make
the same member variable only reuse it
instead let's just grab it again create
it again over here so we get it and we
want this one even if it's pointing
towards a solid object so let's use this
as our move Direction
and now for the distance let's define a
fixed distance
so something like two units would work
and also here's another very important
lesson with regards to writing good
clean code so you would think to write
code like this so let's put the two
right in here that would work everything
would work perfectly but then let's say
you get back to this code after one week
would you remember what this 2f means
the answer is probably not you would
probably very easily forget exactly what
this means so because of that you should
never use numbers directly in the code
like this instead you can either make a
field appear if you want to make it
customizable
or much simpler is actually what we
already did previously so let's define a
local variable with a proper name
so let's define a float and this one is
going to represent our interact distance
so let's call it exactly that interact
with the distance and let's put 2f and
over here instead of using a number
let's just use that variable now if we
were to get back to this code after a
long time it would be extremely clear
what this parameter represents
the technical term for what we did here
is called Magic numbers and I've also
covered them in detail in another quick
video
but as I always remember very simply
never use magic numbers
okay so with this we have our recast
it's pointing forwards for this distance
but this is actually not very useful
because the rickhouse this one only
returns a bullion so all this tells us
is if there's something in front or not
it does not actually get as the actual
object reference so for that let's use a
different version of the raycast
function so as you can see we've got all
kinds of versions in order to get the
object reference let's use this version
right here this one which has an out
parameter for a raycast hit note the out
keyword here this is important this
means that this is an output parameter
whereas the other parameters those are
all essentially inputs that you give to
the function whereas this output this is
basically a value that the function
outputs so let's use this so we've got
the origin we've got Direction then
we've got the rake asset in order to use
it we need to make sure to write the out
keyword here and then also very
important we need to write the type
so let's call it break asset and then
the name so let's call it break asset
basically what we're doing here is
essentially defining a variable of this
type with this name we're defining it
and giving it to the function
immediately so we can use it afterwards
if you don't include the type if you
just include the name then you get an
error because this name Rick has said
this was never defined alternatively you
can Define it before you pass it in so
over here you can do recast it recast it
and just like this it works because you
are defining it here and using it here
but in order to make the code a bit more
compact you can just Define it here in
the same place where you get it okay so
let's use this and with this the
function still returns just a Boolean so
just hit something or not but then we've
got the rake asset output this will be
filmed with data from the Collision if
we do hit something
we can inspect this to see what that it
contains so you can right click on top
of the type and then go to definition
and up here we do see the definition for
the rake acid struct you can see this is
a structure to get information back from
a raycast you can inspect this to see
all of the kinds of things that this one
returns for example you have a vector 3
point for the impact point in workspace
where the ray actually had a collider it
can get the normal of the surface and so
on so you can get all kinds of things
for a use case what we want is to
identify the object that we hit and for
that we can use the transform so it's
going to be the transform of the rigid
body or the collider that was hit so
let's just do a quick test if we hit
something lets you unlock on that object
so let's do an if so if this one is true
then that means we hit something so if
so let's do a debug unlock go inside the
rake asset and log the transform okay so
like this we should be able to see on
the console if we do hit something let's
also do an ounce just to be able to
easily see when we hit something so on
else let's just log an empty Dash and in
our game in order to make sure that our
Collision is working that we are
correctly detecting it let's just
duplicate this object but before we do
let's make this a proper prefab if you
have an object of a certain tab that you
want to create multiple instances of it
you should be using a prefab rather than
just duplicate an object that way with
the prefab if you make any changes to
that prefab it applies to all of the
copies of that prefab
so let's first make this one a prefab
and again since this is our first prefab
let's first make a nice folder to keep
things organized so folder for our
prefabs and to make game module prefab
is super simple you just click and drag
directly from the hierarchy and drop it
inside the folder there you go there's
our prefront and now let's just
duplicate this make sure it has a
different name so it has one so that's
enough with this we should be able to
see it just for testing let's put it
just off to the side okay so let's see
so here we are in the console we see a
dash so by default we are not hitting
anything okay so that makes sense now if
I move towards this object and if there
you go it does I didn't find that object
and if I stop moving it stops
identifying okay great now if I move
towards this one and if there we go this
is the one with the name of one and this
is the one with the name of none all
right awesome so just like this we are
correctly identifying what object is in
front except we also have an issue so if
I move towards the object then yep it
does work but if I stop moving once I'm
still facing that object right now it's
returning none now the reason for that
is because of the move data that we're
using here if we're not moving in any
direction then basically this Vector
won't be zero zero zero so we're going
to be firing a raycast towards no
direction at all so obviously it's not
going to hit anything the solution to
that is super simple we just need to
keep track of the last interact move
Direction so let's go up here to find a
film for that so let's make a private
let's make a vector 3 and call it the
last interact Direction
and then down here when we have our
handle interaction so we get the
movement here okay that's great so then
we just check if the move direction is
different from Vector 3.0 by the way
this is a constant a shorthand for zero
zero zero so if it is not zero then that
means we are moving in some Direction
so so let's set the unless in direct
direction to this move Direction and
basically if it is not if move there is
zero then we are not going to modify
this so this one is only going to
contain the unless interact Direction
and then down here instead of using the
move Direction Let's just use this one
so that way even when we stop moving we
are still going to be using the last
indirect Direction okay so with this
let's test so here we are and if I move
towards it yep it works and if I stop
moving and yep it still works alright
great so we can move towards it Point
towards a certain object and then yep it
still works okay great now let's
actually interact with this counter and
to do that let's make a class for the
counters itself so let's make a new
script in the UC sharp script let's come
with the same name so clear counter
okay there's our script
now very importantly for attaching the
script remember that we have two
instances of our prefab if you just
select it in the heart key and you just
drag it on there if you do that then
you're not actually adding this script
to the prefab itself you're only adding
it to this specific instance of that
prefab so if you look at this one yep it
has a script but this other one which is
a copy of the same prefab this one does
not have it also over here on the
inspector you can see the little script
icon has a nice little plus that means
it is something that you are adding on
top of the prefab so that means this
script is not present on the base prefab
basically this is not what we want we
don't want just this object to have this
script we want all instances of this
prefab to have this script so instead
let's get rid of this one from here we
want to modify the prefab itself so one
way to do that is to select the prefab
on the project window so here it is the
actual prefab and now we can drag the
script on there so that works or another
alternative is something like the prefab
in the hierarchy and on the inspector
over here we see a nice button to open
the prefab and if we actually go into
scene view then we can see what that
does so with the object selected so this
is an instance of that prefab but if we
click on open then essentially we are
opening and we are working inside the
prefab so now if we make sure to add our
script and let's go back outside this
prefab so on the top left corner over
here we can see where we are so we were
inside our scene and then we are inside
the clear counter prefab so if we click
on the scenes we can go back now it
tells us that we made some changes to
the prefab so let's save them and if we
add that script and we can see both
instances of the prefab they both have
the same script and we can see on there
on the icon that this is not an override
this is an actual script at on the base
prefab so whenever working with prefabs
always make very sure that you are
adding it on the right place
if you want something on the base prefab
make sure you either add it on the
prefab itself or go inside the prefab by
double clicking on it or select an
instance in there and open to go inside
the prefab so always keep in mind
different switches between a prefab and
an instance of a prefab okay so we have
our script let's open it and over here
let's just make one super simple
function
so let's make it public because we want
to call this from our player class let's
return void and just call it interact
okay that's it super simple for now
let's just do a debug.log and just say
interact
okay so that's it and now over here on
the player when we have our handle
interactions function so interact we do
our raycast and we find out if we hit
something so when we do the first thing
that we should do is identify what this
transform is so is this something just
like a dumb Cube or is it an actual
counter now when it comes to identifying
things this is another place where a lot
of beginner tutorials will teach you to
use the unity attack system so that's
over here in the editor when you select
any object over here in the inspector
you can see a tag so you can see
untagged and you can add all kinds of
tags this is something that a lot of
beginner tutorials teach but Unity tags
are horrible you should never never use
them I covered in more detail why that
is in the advanced concepts video the
main reason is because of well pretty
much the same thing that I mentioned a
while ago when we were handling animator
parameters so you were doing this and I
talked about how this one takes a string
and how strings are horrible way for
identifying objects they are very
brittle very error prone it's very easy
to make mistakes and tags have the exact
same problems because tags are strings
so we do not want to use tags to
identify objects instead over here on
the player script let's use a different
method for identifying objects and the
best way to do that is to Simply get our
counter component
so we have our transform and then from
inside that transform we can call the
function try get component this one then
takes the type of component and again
note how this is an out parameter so
let's put out and we want to test if
this is a type clear counter so clear
counter and call it clear counter
and this one basically does the same
thing as a recast so it returns a
Boolean so either true or false
so if this one is true then that means
that object has that component so over
here we know has clear counter
by the way if you're not familiar with
tryget component this is pretty much the
same thing as the regular get component
except it automatically handles the null
check for you
so if we just did this it's exactly the
same thing as this so you do an if
recast it what's X is a transform get
component
component of type clear counter
naturally this one is not inside now but
let's store this
well your counter equals this then you
do if this one is not known
then we know has a clear counter
so basically what we have up here is the
exact same thing that we have down here
so just using trigate component it's
just a bit more Compact and I find much
easier to read than to always get
component and test if it is not null
over here we just have one function with
a nice out parameter and everything
works perfectly so that's the try get
component I much prefer that method so
let's use that by the way on the trackit
component over here you can see it has a
type inside some angle brackets
basically these are called c-sharp
generics these are an extremely powerful
c-sharp tool I have a dedicated video on
them and I've used them in tons of
videos definitely go ahead and learn
about them basically this lets you write
code that works with many classes not
just one specific type in this case the
target component can work with any type
of component
so it can be Unity built-in components
or it can be components that you made
yourself then if it finds a type it
returns true so for right now it's not
strictly necessary to know the specifics
about how c-sharp generics work but
definitely make sure you add that video
to your queue and watch it afterwards
c-sharp generics are an extremely useful
c-sharp feature okay so we do this and
basically if we are inside of here then
we know this object has a clear counter
and we have our clear counter reference
so over here it's super simple let's
just call the interact function
alright so that's really it let's just
get ready else we no longer want that
log so we should be able to see unlock
whenever we call our interact in a
counter alright so here we are and if I
move around okay that's good over here
the console is empty all right now if I
move towards the counter if there you go
I'm interacting with it and if I move
towards this one if there you go
interacting all right great so with this
we are correctly identifying the object
and interacting with it now let's just
do one final thing over here we are
doing a recast to find the counter
and right now we are doing a raycast
towards any object that has any kind of
physics calendar
so maybe that's our counter or maybe
just a random wall for example if we had
an invisible wall in front of our
counter then this code would not work
that's because this raycast and this
raycast set it only Returns the very
first object that it does hit so if the
counter was behind the wall then the
brake acid object here would be a
reference to that long object perhaps
that's what you want or perhaps not in
that scenario one thing you can do is
instead of using recast you can use the
function raycast all
and difference for this one is instead
of returning just a Boeing just true or
false instead it returns an array of all
of the objects that it hit with that
raycast then you could cycle through
them and identify the object so that's
one approach or another option is over
here on the recast
if we look at these function versions We
can see that some of them has what it's
called a layer mask basically you can
set a certain game object to a specific
layer and then if you're using layer
mask then you can make sure this recast
will only hit objects within that layer
anything not on that layer will be
ignored for that recast this is super
useful so let's learn how it works for
layer mask we can go up here and Define
a type of layer mask so let's make
another serialized field private let's
make it of type layer mask let's call it
the counters layer mask
okay so we have this and then down here
when we have our recast let's use it so
let's find the function that matches up
these parameters with the layer mask so
here it is we have the origin then we
have Direction Drake acid the max
distance and then finally we have our
layer mask and let's use our counters
layer mask okay great now back in the
editor let's select our player game
object and yep there we see our field of
type layer mask and you can see how we
can select all kinds of layers and how
we set these layers to an object is
let's just select our clear counter
although again we want to make sure that
this change applies to all encounters
not just this one specific instance so
let's go inside the prefab and over here
we've got a Film Forum layer and you can
see we've got a bunch of default layers
and then we can add some more so let's
add some layers and over here let's go
to the first empty one and let's call it
counters okay we've added the layers so
let's go back select our object and now
on the layer let's put it on the
counters now it asks you if you want to
modify the layer for all Channel objects
now since we made sure to keep the Dean
logic and physics components only on the
parent object let's just modify this one
and leave the other ones on the default
so let's just modify this object only
okay so with that our counter is now on
the counters layer let's leave the
prefab make sure to save it okay great
and now if we go back into the player
and over here on the counters layer mask
yep we do see the counters layer so
let's just click the selected by the way
this drop down menu can actually select
multiple so you can select all kinds of
layers so this is multi-select but we
only want to counter so only like this
and just like this if we do test and if
I move towards it and if there you go
get the nice interact on both them so
everything still works is only the same
but now if we had another physics on
leather in front of it it would still
work because we're using a layer mask to
only recast against counter objects
alright great now I should point out
another way to work with layers is with
something called a bit mask that's a bit
more advanced usually the layer mask is
much easier to follow but if you want to
learn about bitmask go ahead and watch
that video and also another quick note
in this game we're only going to
interact with one single object type
it's only going to be a counter even
though we're going to have multiple
types of counters but for games where
you want to interact with multiple
objects like for example having an
interact action to talk with an NPC
another one to open a door or push a
button for those kinds of multiple
interactions to build the system like
that make sure you look into my how to
interact with objects video it covers
how to do all of that how to interact
with all kinds of objects it's all based
on c-sharp interfaces which we're
actually going to use in a few lectures
and also have a dedicated video on that
topic so keep following this course but
then make sure to watch those videos add
them to your watch list and make sure
you do watch them watch out how to
interact video it is something that is
necessary in so many games and most
tutorials don't actually teach you the
correct way of doing it anyway so back
in our game we are correctly identifying
and interacting with each counter but
obviously we don't want to interact
automatically just like this instead we
want to press a nice button to interact
so that means we're going to need to
create an interact input action so let's
do all of that in the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to create a
proper interact input action and in
doing so we're also going to learn about
a very powerful and c-sharp feature
called events
okay so here we have our game so we have
the player and if we move towards the
counter yep we are correctly identifying
it and interacting with it except of
course we don't want the interaction to
happen automatically it should be on a
player input so let's make our interact
action let's go inside our player input
action so let's double click on it and
let's make a brand new action so we've
got to move and now we're going to have
another one so let's click on the plus
icon for this one let's call it interact
and for this one action type we do want
it to be a button okay great then on the
default binding let's go into path let's
listen and by default let's bind it to
the E key just like so many games so
let's go ahead select this one and once
again let's make sure to save the asset
and let the C sharp OS be generated okay
and over here in our game input script
in order to listen that is very simple
so we go inside the player input actions
then inside the player action map and
then we can find the interact action
and then over here we can see a whole
bunch of events that we can interact
with we've got these three cancel
performed and started these are the
three phases of every input again I
cover these stages in detail in the
input system video the important thing
is that these are c-sharp events which I
also covered in another dedicated video
essentially they are a way for how you
can write code to then get notified when
something happens rather than running
code on every single update constantly
testing something for example over here
on the movement movement is a
pre-constant action so it does make
sense to ask the input on every single
update if any movement is pressed but
for an action like the interact the
player is only going to press that say
once every five seconds so it makes no
sense to constantly check for that
action on every single update instead we
just want to be notified when that
action is triggered and that is exactly
what an event does again watch the
dedicated video to learn all about
c-sharp events in detail they are
insanely powerful and we won't be using
them more and more as we go through this
course
for now here are the absolute Basics
events have Publishers and subscribers
the publisher creates and fires the
event when something happens and the
subscriber listens that event and gets
the enlisting function called when the
event is fired now on the generated
c-sharp class we've got these three
events the one that we want for this
case is the performed event so let's go
into this one and basically we want to
add a listener to that event
and we can subscribe to that by doing
plus equals so this assigns a listener
to that event and now Visual Studio has
a nice shortcut so if we press on Tab if
there go it automatically creates a
function now if you're not using visual
studio you can just manually write this
function the only thing you need to make
sure is that the function signature
personally matches the event signature
as usual we can inspect the event so we
can right click on it and go to the
definition and up here is the definition
and you can see that this is an event of
type action with a combat context action
is what is called a dungit I also have a
video on delegates if you want to learn
more about them in detail for now we
don't really need to worry about what is
delegate we just need to use it so in
order to subscribe to the event we need
to make sure that this one returns voyne
because an action returns void and needs
to have a parameter of this type combat
context if I erase this parameter if
there go now we have an error because
the function signature does not match so
it always needs to match the exact same
signature okay and also one more note
over here when subscribing to the event
make sure you only add the function name
meaning you do not add parentheses we do
not want to count function we just want
to pass in the function itself as a
reference okay so now when the player
presses the interact action it's going
to fire off this event which in turn
will call this function so over here
let's do a debug download just see what
this contains for example let's print
out the compact context okay so let's
see so here we are and if I press on E
if there you go I've got a nice event
okay great so with this we know when the
player presses the key now the next step
is how do we get the player class how do
we get this one to know when this is
performed and the answer is we're going
to do the exact same thing we're going
to make an event over here on the game
input class and the player won't listen
to that which in turn the game input
grabs from the input system again the
home point is separating our concerns so
the player does not care about the input
system does not care about the interact
action it only wants to know when
something related to interact happens so
over here let's make that nice event
first of all let's make it public
because we want the player to access it
then we need to add the event keyword
next we add the donkey type like I said
you can learn more about delegates in my
dedicated video you can create your own
custom Delegate for your event or you
can just follow the c-sharp standard and
just use the standard event handler and
this one exists inside system
so let's make sure to go up here and add
using system and this one has the event
handler class this one is pretty much
easy sharp standard for events as you
can see it returns void it has an object
for the sender and an event RX parameter
like I mentioned in the events video you
are not forced to use this target you
can use whatever delegate you want like
for example you saw that the performed
uses an action delegate so you can use
anything you want to choose that the
event handler is the c-sharp standard so
it's easier to follow unless you have a
specific reason to deviate from the
standard you should probably use this
one so let's use this and then finally
for the name usually you start the name
with on and then whatever happened so in
our case let's go with on interact
action
okay so we have defined our event and
now for firing it let's go down here
into when we have the interact performed
and let's go into the event and for
finding it it's pretty much exactly the
same thing as calling a regular function
so we just call it with parentheses then
usually for the object sender this is a
reference to whoever is sending this
event so usually the this keyword and
then for the event RX this is in case
you want to send some arguments with the
event in our case we don't really need
to send any extra data for this one just
firing the event is going to be enough
so for that we can use the constant
event RX dot empty okay so that's it
with this we are firing an event except
just like this we're actually going to
have one potential error if we have no
subscribers no listeners to this event
then essentially this field won't be
known so this one over here is going to
trigger a non-reference exception let's
do a quick test just to see this
happening so here if I press on E if
there go we have a null reference
exception
so when working with events you need to
first test if there are any listeners
and only then do you actually trigger
the event
so you do if this one is not null if it
is not known that means there are some
subscribers so we can fire the event so
like this it won't work but there's an
even more compact way to do this which
is perfect for events so instead of this
we've got our on interact action then we
can add a question mark this is called
the non-conditional operator basically
the code is going to execute from left
to right
and then when it gets to this question
mark it's going to evaluate the left
side and if it is null then the
execution won't stop right here on the
question mark and will not throw any
errors whereas if this one is not null
then it continues executing to the right
except with this syntax we have an error
We cannot put parentheses directly after
the question mark but what we can do is
simply just call invoke and that does
the exact same thing that console
function so what we have here is exactly
the same thing that we had previously
so what we have over here and over here
these are the exact same thing it's just
this one is much nice much more Compact
and especially for events this one is
super useful okay so with this we are
correctly firing for our event now let's
actually listen to it so let's go over
here into the player class
and let's listen to our event
let's do it on a private void start make
it on start not an awake this is a very
important rule which I'm actually going
to cover in detail in the next lecture
but for now just make sure to listen on
start and not on awake so over here we
access the game input then let's access
the on interact action event and as
usual let's listen to it so let's use
press tab to listen to it so it is
exactly over here that we want to run
our interact code so let's go down into
the handle interaction code that we had
previously so this one
so let's copy paste all this code put it
up here
so we get the interaction going to the
object and Trigger the interact now
obviously code duplication is a big
No-No so we're only duplicating our code
just for a quick test just make sure it
works
once again refactoring is super useful
so we're going to refactor this code to
get rid of code duplication in the next
lecture but for now we just want to test
to make sure that this does work
so let's just remove the interact over
here from the handle interactions so the
only interact function being called is
over here when we have our actual input
so let's test and see if we can press to
interact with the counter alright so
here we are and as I move around if I
approach a counter yep there you go we
no longer have the automated interaction
and now if I'm facing the counter and I
press the enter I key if there go here
we have our nice interaction all right
awesome so I can approach I can interact
and do whatever I want
alright so here we learned about c-sharp
events these are super powerful so if
this is the first time you're hearing
about them then you've just had an
awesome new tool to your tone box
definitely make sure you watch my
dedicated video to learn about them in
more detail events are super useful the
next thing we're going to need is just a
visual to highlight the current selected
counter so let's do that in the next
lecture
hello and welcome I'm your code monkey
in this lecture we're going to add a
visual to our selected counter and in
doing so we're also going to learn about
the very useful Singleton pattern okay
so over here we already have the logic
to identify the counter in front of the
player and we can interact with it
however once the logic works there is no
visual indicator at all so let's add
that now as usual the super quick and
dirty way of doing it would be pretty
simple over here on the player script we
could just directly enable a visual mesh
on the target counter so down here on
the handle interaction when we have this
over here we can tell the clear counter
to enable some kind of visual
technically that would work but that
would be some pretty dirty code we would
basically be making the player
responsible for enabling some kind of
visual which would mean that we were
mixing logic with visuals again we
always want to try separating the logic
from the visuals as much as possible to
keep our code nice and organized so
instead of doing the quick and dirty
route let's do it properly back in the
editor let's create a brand new c-sharp
script call this the selected counter
visual
and now let's go into the prefab again
let's go inside it so let's select the
clear counter on the hierarchy then on
the inspector let's open up go inside
the prefab and now let's select the
visual inside it and let's duplicate
this so you can press Ctrl D to
duplicate it let's name this when it's
selected and then inside there's a
visual with a mesh filter and a mesh
render so over here let's swap out the
material
so let's click on the circle icon and
now included in the assets is this
material counter selected so it's all
the way yep up here the counter selected
basically it's just a solid white color
within low Alpha so on the kitchen
counter inside the sunlight game object
let's make sure to use this one with
this we have kind of like a ghost visual
so if we enable and disable this game
object we can see the difference Also
let's do one tiny thing which is right
now we duplicated the actual visual
meaning that these objects are exactly
the same they have the exact same size
and when that happens you might end up
with some rendering bugs if two meshes
are on the exact same position you might
sometimes see the colors constantly flip
back and forth
so in order to make sure that doesn't
happen let's make this one deselected a
tiny tiny bit bigger so over here with
the selected game object selected on the
inspector over here we've got the scale
and also we've got this nice little
button here if it's like this then we
can modify each proportion differently
from one another whereas if we click now
these are all linked so now I'm
modifying one will modify all of them so
let's put this on 1.01 meaning this one
is going to be literally just one
percent bigger so that's enough of a
difference to make sure we don't have
any rendering bugs and by default let's
also start with the visual hidden so
let's do that not on the parent select
game object but rather on the kitchen
counter inside of it let's make sure to
disable this game object by the way the
quick shortcut is shift alt and a you
can enable or disable the object very
useful so let's start with this one
disabled so that it's hidden and
basically the goal is that when this
counter is selected we're going to
enable it and show this Visual and when
it's not selected we're going to disable
it okay so over here on the selected
let's add the script that we made so
these selected comes revision all right
so let's open it now here first thing we
need to know is know which counter is
selected meaning we need to know which
counter the player is currently looking
at so let's go over here onto the player
script and let's basically just do some
simple logic to keep track of the
selected counter so over here let's make
a field so a private
let's make it a type clear counter and
just come with the selected counter
then down here we have our handle
interactions logic okay so we do all of
this we try to find the counter in front
and if we do find it then we have it
here so here on let's just check if it's
different so if this clear counter if
the one in front is different from the
current selected then let's set the
selected to this one
and let's also make sure to essentially
unselect so we want to make sure to set
this one to know when there's nothing in
front of the player so if the raycast
does not hit anything then there is
nothing in front of the player so let's
set this like the counter back into null
and also if there is something but that
something does not have the clear
counter script then it's also not a
counter so over here let's also do an
else selected counter equals no so
basically if there's a counter in from
the player then it's going to set it if
not then it's going to be no
let's just do a simple debug download to
check on the selected counter okay and
also just briefly now that we've made
this selected counter logic actually up
here when we have our interact action
like we saw we were previously copying
some duplicated code
but now we no longer need this since we
already know the selected counter so
over here when we've got the interact
action
let's just check if we do have a
selected counter so if it is not null if
so then we go there and we call the
interact function so that's it we no
longer need all of this logic okay
that's great so let's test back in the
editor and let's go back into scenes
let's make sure to save the prefab
make sure the script was attached save
it and let's hit on play and right now
if I'm down here yep there you go we've
got null and as I approach if there go
that one is a clear counter and if I
move towards this one yep it's that one
okay so basically we are keeping track
of the kernel selected counter now
basically we just need to notify the
visual whenever this one changes so when
this one is pointing at that one or
pointing at no or pointing at that one
we need to know when that happens
and for that we basically have two
options now one option is pretty much
what I mentioned a while ago which is
over here we have the selected counter
so we can run some kind of logic on the
sunlight counter we can do that over
here on the player then perhaps over
here the counter would fire off some
kind of event saying it has been
selected and then the counter visual
would listen to that event and update
itself now that approach would be useful
if we wanted to add some kind of logic
on the clear counter while selected and
that approach would also have the
benefit where the visual encounter would
only listen to events on its own counter
so that's one approach pretty much a
very direct approach but another one is
very simple the player would simply fire
off an event whenever the selected
counter changes and then all of the
counter visuals would listen to that
event then they would identify if the
event relates to that counter and if so
update their state
now the benefit of this approach is that
the logic doesn't get bothered with any
selection logic so over here the clear
counter script never really knows if
it's light or not and that's a good
thing because it doesn't need to know
although the potential con with that
approach is that all of these selected
countervisions are only going to listen
to the same event so both approaches
have pros and cons here on let's go with
the second approach where all the
counters listen to a player event
the potential performance con doesn't
really matter on a game of this scale
we're only going to have about a dozen
counters so even if 11 of them are just
wasting on listening to the event it's
really not going to matter and going in
with this approach will actually help us
learn about the Singleton pattern which
is extremely useful so first let's go
over here onto the player class and
let's make the event that we're going to
fire
so as usual let's make it public so we
can access it let's make it an event and
as usual let's also use the standard
event handler let's make sure to add
using system so here Visual Studio adds
it automatically okay
then let's call this on selected counter
changed
also this is a great moment to learn
about the event arcs this is how you can
extend a c-sharp event in order to pass
in some more data so how you do it by
following the c-sharp standard is very
simple we just create a class
so over here let's make a public class
then for name usually you include the
name of the event with eventars at the
end so in this case on selected counter
changed and then event arcs then on this
class we make it extend event arcs
and finally inside the class we add
whatever that we want like for example
we want the current selected counter so
let's make a public clear counter and
put the selected counter
okay so we have this nice event arcs
with a bunch of extra data and then over
here on the event handler we use the
version that takes a generic and we pass
in our event arcs again I covered the
generics in more detail in a separate
video definitely go watch that one if
you haven't seen it yet c-sharp generics
are one of c-sharp's most powerful
features okay great so we now have our
nice event now let's fire it off so
let's go down here to when we're
modifying the selected counter so here
it is we've got all of these ones so
when we modify let's fire off the event
so we go into this event and as usual
let's use the question mark and then
call invoke then for the object sender
it's going to be this so pretty much is
centered and then for our custom
eventarics let's construct an object of
that type so construct a new object and
then inside we pass in the selected
counter and we set it to this selected
counter now don't be confused by the
fact that we're using the exact same
name if you actually Mouse over the
cursor Visual Studio actually helps you
by telling you which object refers to
this so with the cursor here note how
all of these are highlighted but this
one is not highlighted that's because
this field this is the film inside the
unselected counter change event RX
whereas this one out here is the object
that we're referencing in here so even
though these two have the exact same
name here we're accessing the film
inside of that and we're assigning it to
the reference that we have down here
okay so that's really it we're firing
off the event when the selected changes
and we're passing it in and let's also
make sure to do it over here so let's
copy and paste some code and there you
go just like this except of course we
can already see a bunch of code
duplication usually that means it's time
to refactor so let's do that pretty
quickly let's go down and make a brand
new function so let's make a private
Droid let's call it set selected counter
and we're going to receive a clear
counter for the selected counter
then over here we just set this dot
selected counter so we're modifying the
member variable with the one that we
receive on the parameter and then let's
also fire off the event so let's copy
paste the event
just like this the exact same thing okay
so that's it and now up there instead of
code duplication we just do this
so over here we set the clear counter
just call the function pass in that one
and get rid of this and on that one just
pass a null just like this get rid of
all this and here the same thing just
pass in no alright so with this our code
is much cleaner and everything still
works is all the same so here we have
everything done on the player side let's
just get rid of unlock we know we need
this so we're still handling the
selected counter logic and then down
here we're firing off the event now we
need to do is go over here into the
selected counter visual script and here
what we want to do is to listen to that
event in order to do that we need a
reference to the player object now so
far when we've been listening to events
like for example any player class up
here we were listening to some events on
the game input so there you go the
uninteract action so for the game input
reference we just added as a serialized
field
we did this and then we drag the
reference directly and technically we
could do the same thing over here on the
sound like the counter visual but we're
going to have like a dozen counters in
our map so it would be pretty tedious to
drag and drop the play reference to
every single one of them so instead of
using a serialized field another
approach is to use the Singleton pattern
this one is an extremely useful
programming pattern it's very useful for
things where you only have one instance
of something
in this case we're making this game
single players so we're only ever going
to have a single player by the way
here's one obvious quick note like I
mentioned in the beginning of this
course
after this video there's going to be
another one converting this game into
multiplayer and in that case we will
have multiple player instances but this
is also an excellent reminder of how
refactoring code is perfectly fine for
right now for this game it is intended
as single player so for now we're going
to use the Singleton pattern then in the
future when we convert this to
multiplayer we won't simply refactor
that logic again don't be afraid of
refactoring code it's a Perfectly
Natural part of programming and game
development okay so let's implement the
single note pattern this is actually
super simple the name sounds
intimidating but it really is very
simple
over here on the player script
let's make a public field this one let's
make it static
if you don't know static basically it
means that this film belongs to the
player class itself and not to any
instance of a player so for example if
you had a hundred players you would have
a hundred instances of moose mean you
would have one for each player but there
would only be a single static film
because this static film belongs to the
class itself and not to any instance so
let's make a field of Thai player and
then for the name the convention is to
call it instance and the reason why I'm
using Pascal case here so capitalized in
the beginning the reason for that is
because this is actually not going to be
a film but instead it's going to be a
property
remember the naming rooms that we
covered in the beginning of this course
it's very important you follow your
naming rules always be consistent so
your code is easier to understand
so with that said since this is the
first time we're using a property let me
quickly explain what it is
basically it's the exact same thing as a
regular variable except you can add some
logic when getting and setting that
field so here let me write some quick
code just to show difference between a
property and a regular field so for a
regular field you would call this maybe
instance field something like this so
this is a regular field
then you would have some kind of public
static
return the player and call it get
instance field
then over here you would return the
instance field
and then maybe another public static
void set instance field where you
receive a player for the instance field
and you would set the player that
instance film into this instance field
so this is how you do this logic with
fields and now with properties
you would do public static Flair then
call it instance
then on the property itself you open up
the currently brackets
inside the property you put a get then
you return something
so for that something usually a property
has a field underneath it
so you'd have a private static player
for the instance that's a different name
from this one
on the get you would return that
and on the set
you would set the instance equals z
value
if you're confused here don't worry
basically I'm just repeating just so you
can see difference here we have a field
with a get and a set function so regular
functions and up here we have a property
and inside the property the property
itself has a get and set functions which
can also do some logic so you can do
some logic in between or you can just
return the underlying value so basically
using your property is pretty much the
exact same thing as using a separate get
and set function also one more bonus
thing which is that c-sharp is smart
enough to automatically create the
underlying film for a certain property
so if you just want to do a get and a
set then you don't need to Define all
this you can just Define a property and
then inside you can just do get and set
and there you go this code here works
the exact same thing as we had
previously which in turn is the exact
same thing as all the code we have here
with the getter and a Setter function so
here it is a valid functional c-sharp
property now I have to say that
personally I very very rarely use
properties in fact the only place where
I use them is over here on the Singleton
pattern for everything else I normally
use regular films with get and set
functions personally that's just the way
that I like to code but that's really
just personal preference so if you don't
like to use properties then go ahead and
use them anyway so the reason why I like
using a property specifically for the
single pattern is because the implicit
implementation allows you to do
something really nice again remember to
go on with clean code we want to
minimize complexity and the best way to
do that is minimize access here if we
set this property and we set it as
public then that means that any other
class can both get and set so anyone
else can have both read and write access
so we have the exact same problems that
I warned you about when I spoke about
why you should not make everything
public and of course if we make this
private
then at that point we kind of lose the
purpose of our Singleton since no one
else will be able to access this
basically we want to be able to access
this reference from classes outside of
this one we just don't want those
classes to also have right access
now thankfully properties have an
excellent thing which is you can Define
accessors for here both the get and the
set so we can make the property itself
public which means by default both of
these won't be public but then we can
also add the accessor over here private
which in turn means that the get won't
be public so any other class can get
this but private means that only this
class can set it this way we have the
exact level of accessibility that we
want this is the reason why for this
specific use case properties are very
useful with just this one line of code
we already have our instance with the
perfect level of accessibility
so now that we have this field to set it
let's make a simple awake so let's go
over here private void awake and on
awake we just set instance equals this
however remember that a key point of the
Singleton pattern is you only have a
single instance of something
so in this case we should never have
more than one player if we do then
something went wrong
so we can add a nice safety feature here
let's just check if instance if it is
not known meaning it has already been
set to something
if so then that's an error something bad
happened similar to a debug.log error
because this should never happen so
let's say there is more than one player
instance this way we have a nice safety
check just in case something goes wrong
alright so that's really it for the
Singleton pattern we just defined a
property with a public yet in a private
set and on the Wake we just set the
instance that's it as you can see it's
super simple and now for the really
useful part over here on the selected
counter visual now we can access the
Singleton instance in a super easy way
let's make a private void start and on
start we just access the player class
and from the class we can access the
static instance so we can access the
Singleton and now we can listen to The
unselected Counter event and over here
by default Visual Studio gives this
function the name of the event and also
the property
this is in the very descriptive name so
I like to rename this so control RR and
just rename the instance here instead of
instance let's rename it to player okay
great so over here we can listen to this
event
however here is yet another extremely
important thing note how I made this on
start that is very important if you do
this over here on a week instead of
start and over here on the player you're
also setting the instance on awake if
you do that basically there is a chance
that this code won't run before this
code and if that happens well then this
one the player instance has not been set
yet so this will be null and don't throw
a known reference exception now whether
this happens or not it's actually
somewhat random it depends on the order
in which Unity decides to run both these
scripts if Unity decides to run the
player first and this one second
if that happens then there's no problem
but if Unity decides to run this first
and then this one then we have a problem
let me do a quick test and see if in my
case it triggers that error any up in my
case it did trigger that error so here
we have a no reference exception
any app it is being fired on this line
now one solution to this problem is you
can tell Unity specifically which order
the script should run in so you can go
up here into edit then go into the
project settings
then on the left side you've got
something called The Script execution
order and basically over here you can
set the order in which all of these
scripts run so if you were to make the
player script run before the default
time that would make sure that even
though both these scripts aren't awake
this one would run before this one so
that would fix that problem however you
should really only use this approach in
the last case possible where there
really is no other way in this case we
do have another better Wing personally I
have a very simple room that I like to
follow that helps solve this issue as
you know Unity has both an awake and a
start
and all of the awakes on all the objects
will all run before all these starts so
the simple rule that I follow is that I
use a wake for the initialization of
that script and for any external
reference for that I use it on start so
in this case for initializing the player
and setting the instance that will lead
to the initialization of the player so
let's do it on the Wake whereas over
here on the visual
since here we're going to access the
player which is an external reference
for this one instead of doing it on Wake
let's do it on start this way we are
guaranteed to make sure that this
instance has been set okay so with all
of that here we have our instance so
that works great and we have our events
so that's great then here we have our
event and inside we've got our event
arcs so we can go inside the event arcs
object and inside we have our selected
counter so we need to do is just compare
which counter this Vision belongs to
so let's actually make a film up here so
as usual let's make a serialized film of
type clear counter
so we have this one and before we go
into the editor just make sure it
compiles and let's comment this out so
now let's go back into the editor and
over here let's drag the reference but
again remember we're working with a
prefab so let's click on open to go
inside the prefab and now once inside it
let's select the selected game object
and just drag the clear counter
reference okay great let's go back
outside and save the changes all right
so now here in the code it's actually
very simple so we just do an if
if the selected counter matches this
clear counter
if so then we want to show this visual
if not we want to hide it so let's also
add a reference for that visual so let's
add another serialized field of type
game object for the visual game object
then back in the editor again let's go
inside the prefab and on the select
let's drag the channel kitchen counter
so drag down that is the visual game
object okay let's go back save and back
in the code here let's make some simple
show and hide functions so private void
show
and a private void hides
and now on the show just going to visual
game object and call set active so this
enables or disables the game object so
for sure let's set it to true and for
hiding let's set it back into fonts okay
so now it's super simple if the selected
counter is this counter then let's show
the visual if it is not then let's hide
the visual alright that's it super
simple let's test so here we are and if
I approach that counter yep there you go
look at that nice selected Visual and if
I get into this one yep there you go I
can see it all right great so here we
had a really nice visual to our selected
counter and more importantly we'll learn
about the super useful Singleton pattern
as well as learning about c-sharp
properties and a very helpful room for
how to avoid code timing issues so this
was a really detailed really important
lecture if you're feeling confused about
anything go ahead watch it again or just
post a question in the comments and I'll
do my best to help so with all of this
this is all great we have these unlike
the counter and we can see which one is
actually being selected then by pressing
a button we can actually interact with
it so I can move and interact with any
of these counters but right now just
interacting with them doesn't really do
anything so the next thing we need is to
create some proper objects for all of
our ingredients so we can later pick
them up and drop them on counters so
let's begin doing that in the next
lecture
hey again quick intermission your pass
C15 lecture marks so congratulations
looking at my regular core stats it
seems about 80 of people give up by this
point so great job with sticking with it
the difficulty in complexity is
increasing over the lectures so I just
want to check in to make sure you're
understanding everything remember to
post in the comments if you need extra
clarification on anything and I'll do my
best to answer
also check the website to see what
questions others have asked and of
course remember this is your Learning
Journey you're not competing with anyone
but yourself so take your time re-watch
some lectures if you need to just focus
on learning okay let's go to the next
lecture
hello and welcome I'm your code monkey
in this lecture we're going to learn how
to create the kitchen objects like the
various ingredients okay so far we have
our player we can walk around I can
approach each of these counters and I
can interact with now the next one is to
create objects the player can pick up
and drop when interacting with a clear
counter so let's begin by making the
actual objects so let's create a new
empty game object call this one the
Tomato then again as usual let's
separate the visual so in the included
assets let's go inside of it then we've
got the prefab visuals and we've got the
kitchen objects visuals and inside we've
got all of the ingredients so let's just
find the Tomato Visual and drag it as a
child of the tomato and again as usual
make sure to put on position low
composition zero zero zero and for the
main one let's put it on a y of zero and
just push it a little bit off to the
side just so we can see okay great
now this one is obviously not going to
exist over here in our world instead
we're going to spawn it so let's make it
a prefab let's just drag it over here
into our prefabs okay there it is let's
delete it from our scene and actually on
our prefabs let's make a nice folder to
keep things nicely separated
so inside the prefabs let's make a
subfolder
currently the kitchen objects
let's put the tomato inside of it and
let's also make another folder
for the counters and let's put the clear
counter inside of it okay so everything
is nicely organized all right now that
we have this let's go inside our clear
counter script and over here let's add a
simple reference to our prefab
so let's make a type transform called
the Tomato prefab
by the way here you could make this
prefab reference of type game object
which type you use in this scenario is
pretty interchangeable I talked about
those differences in another video so
when using prefabs using them as
transforms or game objects that's pretty
much personal preference and personally
I just prefer to use them as transforms
okay so we have this let's just make
this a serialized field so we can set it
in the editor and over here in the
editor let's open up go inside the
counter prefab and just drag the Tomato
reference okay great let's go back
outside save now back in the code here
when the player interacts with it let's
just spawn it so let's call instantiate
pass in the Tomato prefab and now here
is a good question which is where
exactly do we spawn this we don't want
to spawn on this counter's origin
remember that the counter the way we set
it up the origin on the actual object is
over there on the bottom we don't want
to spawn the tomato inside the mesh that
would not make sense instead what we
want is to spawn up here so the next
question is okay so how do we get this
point on top of the counter one approach
would be to use a vector 3 directly in
the code that would work but not very
usable so a more designer friendly
method is to Simply use an empty game
object as a Target so on the counter
let's first go inside our prefab
and over here let's create an empty game
object inside of it let's call this the
counter top point
let's make sure to leave this one as
empty so no components just a transform
and now let's just position it so let's
lift it up by just about enough so let's
make sure we see so there you go just
about that so let's put it on position a
y of 1.3 all right so this point is
going to be our spawn point let's make
sure to save the prefab
then back in the code here let's add a
reference to our point
and for reference let's also use a
transform reference currently the
countertop point
okay now let's just come this line just
so the code compiles so we can drag the
reference back in the editor inside the
prefab let's just write the countertop
Point reference okay great so now here
when we call instantiate let's
instantiate it inside the countertop
point so this one's found the object so
let's say the transform for the Tomato
transform
and then we go inside this one and let's
just make sure we position it correctly
so let's put it on in local position of
vector 3.0 so this one put the object
exactly on top of our countertop point
also here very important don't make a
mistake make sure you're modifying the
low composition and not the global
position okay so with this let's test
over here in the editor let's go back
save our prefab and hit on play so here
we are let's approach a counter and
interact with it and if there you go it
does work the Tomato was indeed spawned
all right awesome okay so with this we
have pretty much our Basics working
we can move up to a counter we can
interact with it and spawn an object but
now let's say that we want to spawn a
different object so let's say now we
want to spawn some genes first of all
let's make the actual object so on the
Tomato let's press Ctrl D to duplicate
this one let's rename this to the cheese
block and let's go inside of it
now in here instead of the Tomato visual
let's drag here it is the cheeseboard
visual so let's use this one instead
okay there's our nice visual
let's make sure to save the prefab and
go back out and now let's say that we
want this one to spawn a tomato and this
one on the left to spawn some cheese so
let's override the prefab and over here
drag the cheese block and now if we hit
on play
can go up to this one yep there's a
tomato go this one any up there's some
cheese okay so it all looks great but
now let's say we want to know what
object we just spawned like what object
is on top of this spawn transform just
like this in the code all we have is a
transform reference so with this the
only way to know what type we spawned
would be if we had different prefabs for
every single object then we could
compare them one by one and see which
one this matches but then let's say what
if we wanted an actual string for the
object well then we would need to add
tons of fields for all these strings for
all of the objects then what about an
icon for each type once again we would
need tons of fields each one for each
icon but if we did it just like that
with a bunch of lists then they would be
separate that's not very good we should
have a proper way of defining our object
types and all the data related to them
so this is exactly where scriptable
objects come in these are objects you
can create in your project funnels which
are perfect for anything where you have
multiple instances of a type like for
example multiple weapons multiple armors
multiple recipes or maybe multiple
ingredients as usual I have a dedicated
video on script along objects they are
super useful definitely watch out for
more detail over here on let's just use
them so the first thing we're going to
need is to actually Define the type and
we do that in a c-sharp script so in our
scripts folder let's create new c-sharp
script call this the kitchen object so
now personally so is just what I like to
open to my scriptable object definitions
just to make it very clear that it's a
script mode object however this is not a
requirement it's just a naming room that
I like to follow and we're calling this
kitchen object because we're going to
use this to Define any kitchen object we
want to interact with
so that's going to be our ingredients
like for example the tomato and cheese
but also things like a plate and then
potentially you could Implement things
like a frying pan or framing signature
or anything like that so it's going to
represent any kind of kitchen object the
player can interact with Okay so let's
make the script and now let's open it
and over here okay first things first is
this is not a monobehavior instead let's
extend scriptable object and then
technically you can have functions
inside a straight ball object but for
now let's just get rid of this so just
an empty class and over here on let's
just Place whatever fields we need to
store whatever that we want so like I
said first we want a prefab so let's
make a public transform for our prefab
by the way here note how I am indeed
using public this is pretty much the one
exception to the room I only use
scripting objects as read-only data
containers I never write to them so
since I found that rule I usually make
the fields in the description object
public that way I can access them
directly without having to make a public
getter but if you want to feel free to
keep following the general rule of not
making anything public you could
definitely make this just a regular
serialized film then exposed with a get
function that would work personally I
just find it simpler to make it public
since I know that as a personal rule I
will never write to a script mode object
field okay so we have a transform for
our prefab let's also add a Sprite for
the icon Sprite and finally let's just
add a simple string for the object name
all right so we have our scribble object
definition we have all of the fields for
all of the data we want to store now how
do we actually create a scribble object
for that let's go up here before the
class name and we're going to add the
attribute so let's add the square
brackets and the attribute is the create
asset menu this takes some optional
parameters again I cover them in detail
in the dedicated script and objects
video for now let's just leave all the
parameters as empty just use defaults
and close the attribute okay so that's
it let's save this and go back into the
editor and over here if we go into the
project window click on the plus icon
and right up top yep we do see a kitchen
object so
so if we selected if there you go it
creates a brand new object inside of our
project files let's name this one tomato
and obviously let's keep our project
nice and organized so we don't want this
inside the scripts folder instead let's
make a proper folder so create a new
folder come with our scriptable objects
and then inside let's put a different
folder for each type so let's make
another subfolder call it the kitchen
object so and let's place the tomato
inside of it okay now with the Tomato
selected we can look in the inspector
and you can see yup it does have all of
the fields that we Define okay great so
now we can just assign them so this is
the tomatoes let's drag the Tomato
prefab for the icon Sprite let's find it
so there are Sprites included in the
regular assets so here is the Tomato
Sprite so it's inside the acids then
inside textures icons and we have all
the icons and finally for the readable
name let's just call it tomato alright
so that's it here we have a really nice
scribble object containing all the data
required for our tomato okay awesome
with that then we can now go back into
our clear counter script and here
instead of having a field for our tomato
prefab instead of this let's sort of
reference of type kitchen object so and
let's go on with kitchen object so and
then when spawning let's go inside our
scriptball object and just spawn the
prefab reference so this is going to be
the kitchen object transform then over
here in the editor let's go inside the
clear counter and let's assign the
Tomato Kitchen object okay so let's save
it and test
so here we are on let's approach hit any
up there you go it still spawns eat
tomato okay great now let's make another
type for our cheese block so let's
create a brand new kitchen object so
called the cheese block and again let's
assign first of all the prefab there it
is then for the Sprite of the cheese
walk and finally this is the cheese well
okay so now for example let's go into
the second one and on the second counter
let's override and say this one spawn a
cheese block so let's test so here we
are approach this one yep there's tomato
this one any of there's some cheese okay
great so everything is working so far
however the original problem that we're
trying to solve identifying the spawn
prefab we still don't have a solution
for that basically when we spawn a
prefab we need to know from which script
No Object this prefab came from so
essentially what I like to do is just
attach some reference to the scripting
object in our prefab however again
remember that scripting objects are not
mono behaviors so if I select the prefab
and I try dragging the description
object nope it does not work so what we
can do is just create a new script so
let's make a brand new c-sharp script
let's call it kitchen object
let's attach this to both prefab so both
the cheese and the block attach the same
one to both of them and let's open
and over here very simple let's just add
a serialized film for our kitchen object
so a serialized film of type
kitchen object so for the kitchen object
the cell
then let's also make a quick function to
expose it so we're going to return
kitchen object as so get kitchen object
so and we just return the kitchen object
as well yep just like this so now here
in the editor for the Tomato yep we've
got the film so let's say this one is a
tomato and the cheese block this one is
a cheese block now here obviously we
need to make very very sure to drag the
correct reference to the right scriven
object if you drag the wrong one like
for example over here on cheese you
would say this one is a tomato if you
did that then obviously you would get
some very weird results so make sure to
check and double check that you drag the
right preferences both over here on the
prefabs make sure they are referencing
the correct Circle object and on the
script module itself make sure they are
referencing the correct prefont okay so
now if you go here on the clear counter
we spawn our object okay great then on
this object we can do get component of
type kitchen object and then we can just
ask it to give us the kitchen object as
well so for example let's do a debug
download on this one
so inside you get the kitchen object to
sew and then let's print out the object
name all right so here we are let's
interact with this one and if there you
go interacted and spawn the tomato and
on this one yep interacted and spawned a
cheese block okay awesome we spawned a
transform prefab and we identify the
spawn object is indeed this type of
object all right so here we'll learn
about one of the most powerful ENT
features scribble objects these are
extremely useful for defining a type and
then creating multiple instances of that
type with whatever that we want so there
can be some ingredients like we have
here or it could be some weapons could
even be some NPC data maybe some Quest
data and so on it really is an insanely
very useful feature definitely go ahead
and watch a dedicated video on script on
objects then if you want you can also
watch some more videos where I've used
scriven objects for example in the
Minecraft crafting system using
scripting objects or the hydrogenated
crafting system which again also uses
scribdon objects okay so this is done
it's working great now let's continue to
the next lecture where we're going to
help the kitchen object know where it
belongs and help each counter know what
kitchen object is on top of it
hello and welcome I'm your code monkey
in this lecture we're going to create a
kitchen object parent meaning that the
kitchen object will know where it is and
the counter will know if something is on
it this is important so that later on we
can pick up a kitchen object from one
place and drop it in another okay so
here we have our player I can move
towards this counter interact with it
and yep spawn a tomato then on this
one's want some cheese okay great but I
cannot do anything else in fact if I
interact a bunch more times really all I
did was just spawn a whole bunch more
cheese so instead I want to be able to
spawn some cheese and then pick it up so
let's think about exactly what that
means we want a kitchen object to
essentially be placed on a specific
Place based on the design that we're
trying to implement we're never going to
have a kitchen object just randomly
thrown around the world we're not going
to have tomatoes all over the floor
instead the objects will always need to
be placed somewhere and that somewhere
can be either a counter or it can be
being held by the player so essentially
that means that each kitchen object is
going to have some kind of parent that
it's attached to we're going to make
sure the counter knows if there is a
kitchen object placed on top of it and
we're also going to make sure the
kitchen object itself knows where it is
so first let's do that logic over here
on the counter
so on the clear counter script let's
keep a field for a kitchen object
so just a simple private of type kitchen
object kitchen object
then when the player interacts with it
by the way we can get rid of these debug
transforms debug logs in all you need
them okay so when the plane interacts so
if the kitchen object is known
if so then we're going to spawn it then
when we spawn it let's assign it so this
one equals the kitchen object get
component of type kitchen object okay
so if that one is no we spawn it and we
assign it and just with this we should
have fixed the issue where we can spawn
infinite objects
so over here I can interact and now I've
interact a bunch more times
and now look in the hierarchy inside the
clear counter
and I go inside the counter top Point
nope there's only one tomato okay great
so with this basically we made the clear
counter know if there's something on top
of it
now let's do the other side so let's go
into the kitchen object and make sure
that it knows where it is so over here
on the kitchen object script
let's add a simple field for a counter
so private of type clear counter for the
clear counter
and now let's just basically make two
functions one to set it and one to get
it so a public void set clear counter
and we're going to receive a parameter
of type clear counter okay great and
then we're going to have a public return
a clear counter for the get clear
counter
and we're just going to return our clear
counter and on this one just set this
dark layer counter equals this layer
counter
all right so on this function we're
assigning this field and on this
function we're returning this field
so now back on the counter script we get
the kitchen object reference so on this
one let's call set clear counter and
pass it in this one
and if it is not known so if there's
something on top of this let's just do a
debug.log let's go on to the kitchen
object and get the clear counter
so we should be able to click once and
spawn an object and click twice and the
second time we should be able to see the
name of this layer counter
all right so over here let's approach
and click and yep it's spawn now click
again
and if we've got the message this one is
on the planet counter okay great so far
so good
so the counter knows if there's a
kitchen object on top of it and the
kitchen object itself knows where it is
now let's add some logic to be able to
change a parent counter it's over here
on the clear counter script we basically
just need to call the set layer counter
function with a different counter
reference so just for testing let's add
a serialized film for the second counter
so clear counter for the second clear
counter
now we're doing this just for testing
just make sure the logic Works before we
come up with a more General system
so just for testing let's come up with
some input and again for testing using
the lazy input manager to get something
quickly up and running is a great thing
so let's quickly get a button input on
the counter so let's make a private void
update
and for testing we only want the testing
to work on one counter so let's also add
up here just a ball testing
and then on update if we are testing and
we have the input.getkeydown on let's
say the T key
so if you have that then we can run some
kind of testing code so let's say for
example if the kitchen object does not
know so if we have something on top of
this kitchen counter let's go into the
kitchen object and call set counter and
let's pass in the second clear counter
so basically with this we should be able
to interact to spawn an object and then
press the T key and we should be able to
see that object be set to a different
parent
so here in the after I'll let you set
down let's say this one is our main
counter so let's drag a reference to the
second one the second higher counter
drag it and make this one the testing
script and also just to verify that it
worked over here and lets you a get on
the clear counter all right so let's
test and see
okay so here we are let's approach this
one interact and there you go spawn
tomato and now if I interact again yep
it says the tomato is on the similar
counter now if I press the testing key
if there go the Tomato was moved onto
the other counter
okay so the parent change the logic
worked however obviously we have two big
issues the first one is just a visual
you can see the object is still placed
on top of this counter even though
technically now it belongs to this one
and the second issue is that this
counter still thinks that it owns this
kitchen object and this other counter
does not know that it now owns this
object so we need to sort all of that
first for the visual it's actually very
simple
here when spawning we are spawning it
inside the counter top point and then
setting the alarm position to zero so
whenever we move to a different second
parent when we do that we can just ask
that second parent to return the
countertop point and move it there so
for that let's make a function to return
that
so public we're going to return
transform so get the kitchen object
follow transform so it's going to be our
countertop point
so let's return the counter top point
then let's go into the function on the
kitchen object when we set the clear
counter so over here on the kitchen
object on this function so we set the
color counter
then let's modify this transform.parent
go into the nuclear counter in order to
get the kitchen object funnel transform
and again let's make sure to set the low
composition back into Vector 3.0
okay so with this when we set the clear
counter to a different one it should
automatically teleport to the other
counter so let's test so here we are in
first let's interact with this one there
you go it's Pawn now if I press C
testing key and if there go it does move
visually okay great so far so good
however the counters still have the
wrong data by the way here's a quick
empty tub on the inspector you already
know that you can only see the public
and the serialized Fields however there
is actually a way to look at private
fields on the inspector on the top right
there's these three dots and if you
click on it over here you can modify it
into a debug inspector
and when you go into this one Yep this
one does show all the private fields
so you can see for example on the clear
counter so that's the right one this one
over here the kitchen object is indeed
assigned and we can go into the other
one and we can see this one has it as
null so debug inspector is really useful
in these kinds of cases if you want to
inspect any kind of private Fields you
can go to this and see it now let's swap
back into the regular inspector and
let's fix that issue by notifying the
counters that the object has changed
so over here basically we have two
options over here on the calendar
counter when we modify the parent when
we tell the kitchen object to go to a
new parent when we do that we can make
the new parent responsible to updating
itself or we can just make the kitchen
object itself be the one responsible for
notifying the new parent both approaches
can work personally I think it makes
more sense for the kitchen object to
handle itself
so we just call this function to set the
new parent and when this happens
basically this kitchen object needs to
tell the old parent that it is no longer
there and needs to tell the new parent
that it is on there so on the counter
let's make some function to set and get
a kitchen object
so over here on the calendar counter
script let's go down
let's make first one to set so public
void set kitchen object and receive a
kitchen object
and just do this dot kitchen object
equals this kitchen object okay great
then let's make a getter so public
return a kitchen object get the kitchen
object
and just return this kitchen object okay
then let's also make one just to clear
it so probably avoid clear kitchen
object
and this one just sets the kitchen
object into null
and finally just a nice sample function
to test if this counter has anything on
top so just a public Bowl has kitchen
object
and over here we just return if the
kitchen object is not known
okay so some four very simple functions
now if we go into our kitchen of the
script
over here when we tell it to change the
parent let's first go into the current
parent and clear it
so let's first of all do a quick test
for null so if this documentary counter
which is the current parent so if this
one is not null then we go into the
current parent so the clear counter and
we tell it to clear the kitchen object
and then we go into the new parent
and we tell new parent to set the
kitchen object and the kitchen object is
this one
now here will be very very important
don't make the mistake of clearing the
wrong counter keep in mind that over
here this documentary counter this
refers to the previous player counter
whereas the one in the parameter this is
the one this is the new one so make sure
you clear the kitchen object from the
previous clear counter before you assign
it and then you set it on the new clear
counter so be very very careful here
make sure you don't make mistakes
between the quote unquote old color
counter and the nuclear counter
okay so that's it basically we have this
function to set the nuclear counter so
set the new parent we clear the kitchen
object from the old player counter we
added a new one and we update the visual
now we can also add some nice safety
checks here just to make sure we never
make a mistake the kitchen object should
never be set to a parent that is already
holding something so before we set the
kitchen object before we do that let's
make sure that one is empty
so over here just do an if if the clear
counter so that's a new one if this one
has a kitchen object then it already has
something on there this should never
ever happen so let's see what debug.log
error and say counter already has a
kitchen object
we're going to eventually add tests to
make sure that this never ever happens
but having the air here won't be helpful
just in case we missed something
so far as the kitchen object we're going
to fire an error but this should never
happen so we just set the error update
to visual and so on
okay so finally let's just go over here
into the clear counter script and down
here we have the interact action so we
instantiate the kitchen object we're
currently repositioning it and then
we're setting this field assigning it to
this one now we made the kitchen object
responsible for doing all that for
modifying the position and for setting
the field so we don't need to do this
instead we really just need to go and
get the component of that
and just pass in set for your counter
and pass in as this one
so we no longer need all this now our
code is much more simple also
importantly up here we were previously
setting the color counter and then doing
a debug.log but when we set it a new one
that is actually going to clear this
field so if we leave this then this is
going to throw a null reference
exception so let's just get rid of the
slog here we normally need it okay so
let's test and see if all of our logic
is working
all right so here we are let's go to
this one interactive spawn it okay great
and once again we can look in the debug
inspector so let's put it on debug look
at this layer counter so that's the
right one and yep there you go it does
have the kitchen object and if I'm
looking the other one Yep this one has
no okay great
now if I press the testing key yep
visually it did change and if you look
at the counter so if you look at the old
ones that's the right one this one is at
no okay that's great correct and if you
look at the new one Yep this one does
have the reference all right awesome
so now that we are correctly changing
the kitchen object parent for example we
can now interact again with this one and
yep it does spawn a brand new one and of
course if we try moving it to the other
one then we should have our error as
intended this one is currently already
occupied the kitchen object so we should
not be able to drop something on there
but if I press the testing key if there
go nicer okay so that's great
we're basically going to fix this error
later on when we check to make sure the
object can only be spawned when it can
be spawned but for now all of our basic
logic is working we can spawn an object
and change a parent alright so with that
here we have added a really important
feature to our game that is the ability
to know where a kitchen object is now
the next step is to enable the player to
be able to pick it up and drop it
somewhere so let's do that in the next
lecture
hello and welcome I'm your code monkey
in this lecture we're going to enable
the player to pick up a kitchen object
and in doing so we're going to learn
about another awesome c-sharp feature
called interfaces
okay so right now with our game I can
already move the player I can approach a
counter and try to spawn an object and
with the testing key I can move it to a
different parent
so all of that logic is working now
let's make it work actually with the
player let's say when we interact once
we want to spawn it and if there's an
object already on top of it and I
interact again then I want to give it to
the player
okay so here on the clear counter script
we've got our interact function in order
to make that work we need to have a
reference to the player so I just passed
it in over here as an argument for our
interaction so just pass in the player
reference
now over here let's do the logic that I
send so if the kitchen object is known
so if there's nothing here then let's
spawn it okay great but if there is
something
then let's give the object to the player
so how we change the object parent is
just like what we did up here so let's
go into that one set the clear counter
and pass in deploy a reference except of
course this obviously does not work the
parameter on this function is supposed
to be of clear counter it does not work
with the type of player recently on the
logic that we built for setting the
parent and change the parent this whole
thing only works with the counter so it
does not work with any other type so we
cannot set the player as a parent now to
solve this problem is exactly where
c-sharp interfaces come in again I have
a video going through them in detail
definitely watch it and learn everything
about interfaces basically what it is is
a contract you define some functions in
the interface and then any type can
Implement that interface and you can
write some code that works with the
interface which in turn means that the
code won't work with any type as long as
it implements that interface
so in this specific example we're going
to make an interface to represent a
kitchen object parent then we're going
to implement that interface on both the
counter and the player and that way both
of them won't be able to be parents of a
kitchen object so let's do exactly that
now the first thing we do to Define an
interface is Let's Make a c-sharp script
so let's right click create new c-sharp
script and now the standard is to start
interface names with the capital I and
then the name so in this case let's name
it I
kitchen object parents
and let's open it okay so now to make an
interface first of all this does not
extend mono Behavior nope and secondly
this is not a class instead this is an
interface now like I said an interface
is essentially a contract where each
class that implements that interface
must follow that contract
what that really means is you can define
a bunch of functions here by the way
quick note you can also define
properties but not Fields I cover all of
that in the dedicated interface video
but for now here we just want some
functions like for example let's just
put all of the parent functions that we
made previously on the counter
so over here on the corner counter a
while ago we made all these functions
that we needed to make it work as a
kitchen object parent
so we got the transform set kitchen
object get it clear it then has it so
let's just copy all this and paste it
over here on the interface
however one important note is on the
interfaces you don't actually include
any function implementation
the implementation is up to the class
that implements this interface although
again I should also point out another
quick note as of c-sharp 7 you can
include a default implementation but
that's for more advanced use cases so
for here let's just use the basic and
not apply any default implementation
right here so we just defined the
function
and put a semicolon so just like this
just the function definition with the
exact signature so just like this okay
so now that we have defined our
interface and all the functions that we
want to have with this now let's go on
to the counter script so over here on
the clear counter script over here let's
implement the interface and the way we
do that is pretty much exactly the same
as by extending a class so over here we
are already extending Model Behavior
then let's set a comment and let's say
we are also implementing the ikitchen
object parent interface
so right now you might be wondering so
this is pretty much the same thing as
extending a base class and kind of
except for one huge difference
when extending a base class you can only
have a single Base Class like for
example over here we have monobehavior
you cannot extend multiple base classes
there can only be one however when it
comes to interfaces you can Implement as
many interfaces as you want so over here
we have defined our interface and right
now we don't even have any errors that's
because we already implemented pretty
much all the exact functions also Visual
Studio has a really nice software icon
over here on the left side it is
basically saying that this function this
implementation is based on the interface
but let's see what happens if I decide
to comment out these functions so if I
comment out all of this
and if there we go over here we have an
error it is telling us that this class
does not implement the members for the
interface like I said an interface is
like a contract so you must write all of
the functions included in the interface
so we must Implement these so let's get
rid of the comments okay
with this our interface is perfectly
working over here on the calendar
counter
now let's just go into the kitchen
object over here on this script
for now we're still working with the
type clear counter so let's just
refactor this to instead of working with
a clear counter let's make it work with
a kitchen object parent
so let's just change this from type that
to Kitchen object parent let's also
rename this so let's use Ctrl RR for the
kitchen object parent
then we've got a function to return the
kitchen object okay that's good for this
one instead of setting your counter and
let's once again rename this to set
kitchen object parent
and inside again we receive of type I
kitchen object parent
then let's also rename the parameter to
Kitchen object parents
okay so all the names here I have
changed okay they're all correct we set
it we assign it over here instead of
counter let's say kitchen object parent
already has that so just like this
and finally down here let's return I
kitchen object parent and rename this to
get kitchen object parent
and we return that
all right so we have changed everything
I can even do control F to search for
counter and nope there's no instance of
any counter so all this code has now
been Rewritten to work with a kitchen
object parent
something like this everything should be
working it's only the same as previously
we have no errors here
and over here on the clear counter we
just have this error on the player and
let's fix this in a little bit for now
let's just comment it let's just test it
out to see if everything still works
exactly the same as previously also one
final thing since we modified the
interact function over here on the
player class when we have the interact
we just need to pass in this reference
okay so let's test
all right so here we are let's approach
this one interact yep there it is now
let me press the testing key and if
there go it does move okay so everything
is still working exactly the same as
previously once again another successful
refactoring now here comes the magical
moment so right now again everything is
still working exactly the same as
previously so we can only have counters
as parents but now let's go over here
onto the player script and over here
let's also implement the same interface
so let's implement the eye kitchen
object parent
and again as usual we have our error so
we need to implement this
also again Visual Studio is very helpful
so we can click on the light bulb icon
and let's say implement the interface
and if we scroll down here it will
automatically create all these functions
so let's just actually Implement them
so for implementing this interface the
code is really going to be exactly the
same
so let's go up here into the clear
counter let's go down find all of these
functions let's copy them and on the
player let's paste them down here at the
bottom
so we just need to also pick up the
kitchen object as well as a reference to
the top point so over here on the clear
counter and let's just grab both those
so let's just grab the kitchen object so
go into the player and over here let's
add a film for the kitchen object and
finally let's add another one for the
counter top point so over here a
serialized film for the counter top
point
except obviously the player is not a
counter so this name makes no sense on
the player so let's just quickly rename
this and set call it kitchen object home
point
okay here we have our new name we've got
the kitchen object and down here all of
our functions they're all working no
errors all right now let's just assign
this in the editor
so over here let's just go into our
player there's a player script and
requires a reference to the kitchen
object home point
so for that let's do it just like we did
for the Counterpoint so inside the
player let's create an empty game object
currently the kitchen object hold points
and I always just position it just
slightly in front of the player
so let's put it on a x of 0 on a y of
1.3 and on a set of one so there you go
just ahead that's where the player is
going to be holding the objects finally
over here on the player let's just drag
that reference
okay so far so good also one note here
like I mentioned previously in order to
implement the interface it requires you
to write the function code
basically what this means is that
different objects can implement the
exact same interface whilst having
different implementations
so for example over here on the player
when setting the kitchen object
perhaps over here you could play some
kind of item grab animation or maybe
when clearing a kitchen object you could
do some kind of logging
the only thing that needs to match
perfectly is just the function signature
and the function signature that means
the return type as well as the name and
any parameters the implementation itself
that is up to the class that wants to
implement that interface but in this
case we wanted to behave pretty much
exam the same way so like this it should
be working
so we can now go back here onto the
clear counter script and okay we have
our interaction all right great
so if there's nothing we're going to
spawn it and if there is something on
top of it we want to give it to the
player so now let's go into the kitchen
object and call the function set kitchen
object parent and pass in the play
reference
and that's it no errors because again
this takes a parameter of type kitchen
object parent and the player does
implement that interface so that's all
valid
now with this let's says and see if our
code is working
alright so here we are and let's
interact with this counter and there you
go the object has been spawned and now
if I interact again if they're going to
look that the player picked up the
object and since our logic is using a
transform home Point as the parent the
player is automatically carrying this
tomato alright awesome so this is really
great
now over here on the counter we no
longer need all of this testing code we
now have the ability to actually pick up
objects from the player so let's get rid
of all this so we don't need this
testing code don't need a reference to
the second color counter or the testing
okay great so here you can see the power
of interfaces by just implementing the
interface we can now place an item
anywhere we want and importantly on any
type we want
so the counter can hold a kitchen object
the player can also hold it we could
make a dog character and make it hold a
kitchen object we could make a vehicle
hold it or anything again interfaces are
really really awesome one of the best C
sharp features definitely go ahead pause
this course for now and watch a
dedicated video on them you should be
very very familiar with interfaces they
will help you in making all kinds of
systems and games
if you want to see a clear example of
the power of interface you can go watch
my how to interact with NPC's video that
video takes advantage of interface to
make sure that the player can interact
with any kind of object alright so
thanks to interface we can now change
the parent of the kitchen object and put
it on either a counter or the player now
in the next lecture let's make a proper
different counter type
hello and welcome I'm your code monkey
in this lecture we're going to create a
different counter type from where we can
grab some ingredients
okay so far here we have our character
working and we have an empty counter and
by interacting with it we can spawn an
object but obviously that's not the
behavior we want in the final game we
want different counter types that do
different things the cleaner counter
should only be used as a place for
putting down and grabbing objects it
should not spawn anything
so let's build a new counter type
and for that one option is to make a
brand new prefab and build it on from
scratch another option is we can
duplicate this counter and change a
bunch of things or there's a third
option that was added in recent TNT
versions
you can now have what is called prefab
variants meaning that we can have a base
counter and then we can make variants
for all the types so let's do exactly
that to learn about prefab variants now
first let's duplicate this one just so
we don't lose any changes
let's rename this prefab to underscore
base counter
no I'd like to add an underscore just so
that the bass prefab is on top since
this window is sorted alphabetically
now let's go inside the base counter
let's go into the scene view so here it
is
and recently over here we only want to
have all of the things that all of the
counters will have so all the counters
will have a boxing ladder only the same
shape so that's good they will also all
have a counter top point
however for the visual different
counters will have different Visions so
let's get rid of this same thing for the
selected let's get rid of this
and on the actual object different
encounters will have different Scripts
so let's also get rid of this
okay so that's it this is the base
counter it only has all the things that
every single encounter will have so
let's go ahead save this prefab go back
outside and now let's right click on the
base counter
and go into create and over here let's
scroll down and find the prefab variant
now let's name this the clear counter
except obviously we can't have two
different names so let's put this one
into backup we're going to get rid of
this one in a little bit
so on the very end let's name it clear
counter
let's open up this variant
and now here let's add everything just
like we had on the own player counter so
since it's going to be exactly let's
actually go inside the backup one so
here let's just copy the visual in the
selected so let's copy this
go back inside the clear counter variant
and over here only let's paste it so
Ctrl V
see if there it is he selected any
visual
finally just scripts over here let's add
the clear counter script
and now let's just write the references
so the kitchen object we're actually
going to remove this in a little bit but
for now let's assign it the counter top
Point Let's drag it and on the selected
we also need to drag the kitchen counter
reference
okay so here is our clear counter as a
variant of the base counter so let's go
ahead save this and go back outside
and now we can finally delete the owned
prefab of the clear counter so let's go
ahead and delete this
and of course over here on the scene
we've got some broken prefabs so let's
get rid of both these and let's drop the
clear counter variant so let's drop it
place it over here so let's put it on X
of 0 y of zero and Z of 3.5
okay so that's the clear counter and
let's just put another one to the side
and perfectly on the side so on an X of
minus 1.5 okay now we can begin making
our container counter
so for that once again let's make a
variant so right click on the base
counter and go into create and let's
create a prefab variant
call this the container counter
and let's go inside of it now here first
thing we need is the visual so let's go
inside our assets we've got the prefab
visuals inside we have the counters
visuals and let's find the container
counter so let's drag it inside again
for the low composition make sure it's
on zero zero zero okay great
then we need to make the selected so
let's duplicate this visual let's rename
this to selecton
let's go inside on all of these
then let's modify the material for the
selected material so let's click on the
circle icon and select the counter
select material okay we've got our nice
little ghost icon
and just like we did previously let's
start with these disabled so all these
game options disabled so they are hidden
and on the selected let's make sure the
scale is one percent bigger so 1.01
also in the selected this one does not
need an animator so let's get rid of
this
now let's add the selected counter
visual and obviously for this one we're
eventually going to need to refactor it
to support multiple visual objects as
you can see this selected has multiple
but for now just make sure that it works
let's just drag just the first one okay
great
so our container counter has been built
the only thing that we need is the main
logic script so let's do that
let's go into our scripts folder let's
create a brand new c-sharp script
name it the container counter
and let's select the main game object
attach a script and let's open it
alright so now here let's first think
what we want for this counter we want
the player to interact with it and when
it does we want to spawn an ingredient
and give it to the player so that means
that we're going to want pretty much the
exact same behavior that we made over
here on the clear counter so when the
player interacts we spawn and we give it
to the player so let's actually copy all
of this code let's go into the Container
counter and over here let's face this
we just need to grab the references to
the kitchen object and the kitchen
object as so so again just like we did
on the container counter let's copy all
these references
and over here let's paste all of them
and of course here we have an error in
order for this work this needs to
implement our interface and let's do
exactly that so let's implement the eye
kitchen object parent
and back in the clear counter let's just
copy the exact same code so all of these
functions let's just copy them and on
the container counter just paste them
okay great
so we don't have any more errors here so
everything should work we should be able
to interact with the container counter
and we should be able to see an object
being spawned on top of it
over here in the editor let's just make
sure to assign it so let's assign a
default kitchen object so let's say
tomato and the counter top Point Let's
drag the reference and okay everything
else should be working so over here on
the selected we've got the visual game
object on the container counter we've
got this okay great so let's go outside
into scene View
and over here let's just Place some
container counters so let's drag one up
there
let's place it on an X of 1.5 on a y of
0 and Z of 3.5 and let's also Place
another one down here so let's rotate it
to face it upwards
okay so on position zero zero minus five
okay great
and let's make them spawn different
things
so on this one up here let's actually
spawn a cheese block and on this one
down here let's one tomato so let's also
modify the icon here
so from cheese block and let's put a
tomato icon so here it is
okay we've got two counters and two
clear counters so let's test
so here we are and if I approach a
container counter and I press the
interact button and nope nothing
happened we cannot interact with that at
all even the selection visual even that
one is broken so as I approach note the
visual is not showing up
now the reason for this is actually
pretty obvious
if we go over here on the player script
down here when we're handling our
interactions so let's go into the handle
interactions function
over here we are doing a recast and we
are trying to get component of type
clear counter
so basically we're not doing anything if
that object has a container counter
instead of a clear counter so again we
have a similar issue to the one that we
had in the object parent logic basically
we have two types a clear counter and a
container counter and we want the player
to be able to interact with both them
so as a solution for this exact same
problem we could also Implement an
interface just like we did that would
work that would enable the player to
interact with multiple counters but in
this case since the counters are all
very similar very related objects
they're all going to be kitchen counters
as opposed to object parents where the
player and encounter are completely
different
in this case since they are all very
similar a better approach is actually to
use inheritance now here I should point
out that inheritance is one of those
things that is simultaneously very
powerful but also very dangerous usually
beginners get really excited when they
first hear about inheritance but after
gaining some experience they start to
see the massive downsides
one funny joke about it is let's say you
want to write some code that all it
needs is a Banana class but because of
messy inheritance you end up with a
monkey and the entire jungle behind it
basically the banana extends a monkey
which extends a tree which extends the
jungle and so on so you just want a
small thing but because of a complex
inheritance you end up picking up a huge
object some of that to say inheritance
is something you must use very very
carefully it's a powerful tool
definitely but you need to make sure
that you absolutely use it in the right
approach for the problem you're trying
to solve now in this case like I said
since all of the counters are going to
be very closely related in this case it
does make sense
and of course in the future if that does
change we can always refactor
if you're a beginner definitely go ahead
and research a bit more on c-sharp
inheritance the pros and cons
I don't have any dedicated video on that
topic myself but if you search I'm sure
you'll find tons of content again it's a
very powerful but also very dangerous
tool so definitely use it wisely
over here let's make sure we rise so
let's use it
first thing we need to do is to find the
base counter class so let's create a new
c-sharp script let's call it the base
counter
so over here on the script let's get rid
of the functions we don't want any
default functions and let's also make
sure that we do extend mono Behavior we
do want that we still want to use this
as a component
so let's leave the script just like this
let's save it
then let's go over here into the clear
counter script
and on this one instead of extending
Model Behavior let's extend the base
counter
okay that's it that's the only change
and now let's go into the Container
counter and over here same thing let's
extend the base counter inside of Model
Behavior so now both these counters
extend the exact same base counter
script so now if we go into the player
score so here we are on the player
script and on the handle interactions
function over here instead of trying to
get a component of type player counter
let's try to get component of type base
counter so let's also rename the so
control RR to rename rename this to base
counter and of course we need to rename
all these references that expect a clear
counter instead of the base counter so
over here for the selected counter let's
modify the type to base counter then
also up here when we've got the event RX
let's modify the type okay
so over here we have the interactor
let's leave this for a bit let's go down
and let's fix this issue so let's go
down into that function to set the
selected counter instead of this time
let's receive a base counter
okay so all of these errors have been
solved there's only one left and it's
this one the interact
we see this error because obviously the
base less does not have any kind of
interact method so let's add that
now for adding methods to a base layer
it's sectionally very simple it's really
just like any other method so first the
accessor for the interact we want the
player to be able to access it so let's
make it public
and also since we're talking about
inheritance I should probably mention
the other accessor now you already know
about public and you also already know
about private but there's another one
you might not know which is called
protected
basically this one means that whatever
function we defined with this successor
it is going to be accessible to this
class and any class that extends it so
for example if we had a function that
was protected the clear counter could
count this function because it does
extend this Base Class however the
player would not be able to call this
because it is protected now in our case
for the interact action we do want to
play the comet so let's make it public
just like we had previously then another
keyword for every function that we want
the chunk lesses to be able to implement
in their own way we can Define it as
virtual
and finally the function signature as
normal so for the interact we made a
return void call it interact and we
received a player argument
okay so that's it that's our basic
signature
for the implementation let's leave it
empty over here on the base counter so
by default it's not going to do anything
in the game design that we're building
we're never actually going to end up
with anything like this
so if you want for safety we can just
add a debug.log error
to say just base counter.interact
because this should never be triggered
also I shouldn't point out for a more
advanced method
instead of making it virtual you could
make it abstract and basically what that
does is that forces all the classes to
implement their own implementation
so you would make this extract and just
put it just like this as if this were an
interface but in doing so you would also
need to define a base counter as
abstract and so on so basically this is
a more advanced method so don't worry
about it for now let's keep it a bit
more simple so let's make it just
virtual void interact okay great
so we have this let's save this and now
if we go on the calendar counter
over here on the interact notice how we
have a green screen line
basically this is a warning it's telling
us that we are hiding the base function
now in reality we don't want to hide it
instead we want to override it so before
the void before the return type we just
have the keyword override
and Yep this will now override the base
function so when the player interacts
with an object of type based counter and
that object is actually a clear counter
when the player calls the interact
function instead of running this code
it's actually going to run this code
now let's do the same thing on the
container counter so over here let's
also add the
keyword override to override the base
function okay great so we have no errors
here and on the player we also don't
have any more errors since that one does
now implement the interact function
so with this one it says and everything
should still be working so over here
let's approach the entire counter and
let's interact with it any up it does
work it spawn some cheese and down here
yep it's on the tomato and then if we go
on to the empty counter and interact and
yep it still works okay so here we added
the ability to interact with two
different counter types alright great
now knows how the selected logic isn't
really working well you can see the
container counters they are both
selected even though the player is not
looking at them and actually if I
approach it then it actually becomes
deselected basically the reason for that
is because these selected square of that
one is still referencing the clear
counter inside of the base counter
so right now it's only being selected
when the sunlight the counter is known
so that is why as I approach it actually
hides itself so let's fix this let's go
inside the container counter prefab and
inside we've got the selected any up
over there we have a reference to that
so let's open up this script and over
here all we need to do is just modify
this time so let's make it a type base
counter and let's rename this to base
counter
okay that's the only change we need
and by the way since we're here let's
also fix the other issue the issue we
had where we need to support more than
one visual game object
so instead of having a field of type
just game object let's receive a game
object ring
so let's modify this to game object
array
and then down here on the show hide is
actually very simple so let's just do a
four inch game object for the visual
game object
in the visual game object ring we go
inside set it to true and on this one we
set it to false
okay that's it super simple
now let's just update the prefabs so
first over here on the container counter
let's write the container counter
reference as the base counter okay great
and for divisions let's just drag all of
them
so let's write the counters only drag it
on top then the counter hole drag it on
top then the single door drag it and the
black drag it and also by the way over
here on this counter this one actually
has an objects right
this is the actual Sprite in there but
for the selected we really don't want
that so if I enable this game object
here we've got the object Sprite let's
actually delete this
we don't need the actual icon Sprite to
be highlighted so let's leave it just
like this so we only have these four
objects and all four of them are on the
list
okay that's right so all the references
in here they're all working perfectly
so let's go back outside let's save the
prefab let's go inside the empty clear
counter
and on this one same thing on the
selected let's Drag The Insider
reference and for the base counter let's
also drag that reference
okay so let's go outside save it and
let's test
and now let's see if the selected Works
once I approach this one yep it works
yep it works and on this one yep it
works and down here yep it works all
right awesome so we can interact and we
can highlight our selection okay
everything is working great so now that
all the code is working we can inspect
the code to see if we can refactor
anything
we can see for example if there's any
kind of common logic that all of the
counters share that we should probably
write in the base counter
and you can see right away that both the
clear counter and the container counter
both of them implement the kitchen
object parent interface that behavior is
something that all of the encounters
will share
so instead of defining it on each
counter itself let's actually do it on
the base class instead
so let's get rid of the interface
implementation here and also on the
container counter let's get rid of that
and set on base counter and let's
Implement that one so I catch an object
parent and for the functions let's do
the same thing so let's cut this one
from here and let's paste it on the base
counter
it's okay now we need these two points
so let's go ahead copy all of this let's
go into the base counter and paste in
except for the base one doesn't need a
kitchen object so so just the counter
top point and the kitchen object
okay so there are no errors on this one
let's go into the container
let's get rid of the kitchen object and
the counter top Point okay great
now we see an error but before we worry
about that let's actually go into the
clear counter and let's do the same
thing so let's get rid of this get rid
of this and down here get rid of all
these functions
okay so now the counter scripts are much
much more simple
all of the common code is now written
directly on the base counter
now for solving this the container
counter needs to know if there's a
kitchen object on top of it so now here
we have an interesting question with two
possible approaches
basically we need access to this object
so one approach would be to make this
protected like I said protected means
that any classes that extend this base
counter class any of those classes can
then modify that field something like
this yep there is no more errors that's
one approach
and the other approach is to instead
keep this one as private and whenever we
want to interact with it we simply
interact through these functions both
approaches can work and when in doubt as
usual you should probably go with the
more limited option so let's leave it as
private and work with these functions
and send
over here on the container counter
instead of testing if the kitchen object
is no let's just test has kitchen object
so if it does not have a kitchen object
then we're going to spawn it and for
spawning over here we could grab the
actual transform funnel
so this one up here we could call this
function to get it or since that is
actually going to be handled
automatically when we call this function
to set the parent then let's actually
not use this at all
so we just spawn it and set the kitchen
object parent okay great
so now let's just look at the clear
counter for this one like I said it's
not really meant to spawn anything solid
sectionally remove all of this code
this one is only going to serve to pick
up and drop items we're going to handle
that in the next lecture but for now
let's just go back into the Container
counter and let's do the proper logic
that I mentioned in the beginning
basically on this one we want to spawn
the object and we want to immediately
give it to the player so when we call
set kitchen object parent instead of
passing in this let's pass in the player
reference
and that's really it for the container
counter this is all we're going to do so
the player interacts and it spawns an
object and gives it to the player okay
so that's it with this as you can see
the code for all of our counters is much
much more simplified so basically it
only handles the logic related to that
specific counter everything else is on
the base counter so let's test this
so here we are and if I approach the
counter interact any of their go spawn
some cheese and gave it to the player
okay great now just for fun when I made
these assets I shall include a nice
animation
so if you go inside the container
counter over here on the visual note how
this already has an animator with an
animator control and attached to it
you can double click to open it up and
over here you can see it's very simple
basically just has two animations one is
the container close and one is container
opening and closing these transitions
are basically triggered by this
parameter this is a trigger parameter so
when triggers goes into the open close
and when this one ends goes back into
closed so let's just quickly add these
nice animations however again as usual
let's make sure to write some good clean
code so let's not add the visual over
here on the logic script instead let's
make a proper new script over here let's
create a new c-sharp script
call this the container counter visual
okay now we want to attach this only to
the visual game object so only this one
let's attach okay
and over here the first thing we need is
to get the animator
so let's sort of film for the animator
and since it's on the exact same object
we can just make an awake and get
component of type animator
and we just assigned this field okay
so with this we have the animator now we
just need to know when we should play
the animation so let's go over here on
the container counter script and
basically let's make an event that we're
going to fire when the player grabs an
object
so let's make a public event of time
let's stick with the standard so let's
use event handler inside using system
okay
let's name this on player grabbed object
then down here when the player interacts
and gets an object let's fire off this
event so invoke
let's invoke with this and event RX dot
empty
okay so we are firing off this event
and over here on the visual first we
need the film for the container counter
so let's set it up here let's add a
serialized field of tribe container
counter
okay we have this build now let's listen
to the event but again we're accessing
an external reference so let's make sure
to do it on start and not on awake
so let's go into this one and listen to
the on player grabbed object event okay
so here we have the event and it's over
here that we want to access the animator
and call set trigger in order to play
the animation again when working with
animator parameters suddenly we do need
to use strings there's no way around
that but at least we can make it a bit
more clean by defining a constant
so here a private con string call it
open close and let's make sure to use
the exact same parameter name so open
close
and then down here on the set trigger
let's call this trigger
okay so that said some very simple
visual logic
and now over here inside the prefab all
we need is to drag the container counter
reference so let's drag it also make
sure that it has the animator and the
animated controller so with that
everything should already be set up so
let's go back into the scenes save the
changes and let's hit on play
so here we are and if I go towards the
tomato and interact any of that I go it
plays a nice little animation alright
awesome okay so here we created a brand
new counter type and we refactored our
interact code to be able to interact
with any counter type the player can
interact with the container counter to
pick up an object now the next obvious
thing that we need is to enable the
player to drop an object on the clear
counter so let's do that in the next
lecture
hello and welcome I'm your code monkey
in this lecture we're going to enable
the player to pick up and drop objects
okay so we already have the player
working I can approach this container
counter interact with it and yep the
player picks up something now that's
left is being able to put our shade
clear counter and being able to drop
this object so let's do that
let's go over here on the clear counter
script and when we interact with it
we're going to do a bit of logic first
let's just check if this counter is
empty meaning if there is no kitchen
object on it so let's test if has
kitchen object or if not so let's say if
we don't have a kitchen object then
there is no kitchen object here
and if not then there is a kitchen
object here
okay these are the two valid options
so if there is nothing here then let's
check the player itself so we go into
the player and we can ask the same
question so it has kitchen object
so if the player is carrying something
so over here the player is carrying
something
if so then basically we just want to
drop that object from the player and
drop it in here so that's very simple we
just go into the player we get the
kitchen object that the player is
holding and we just modify the kitchen
object parent onto this object
all right so that's it just with this it
should already be working let's do a
quick test before we handle the rest of
the interactions
okay so here moving the player and if I
just interact with a clear counter and
nope nothing happens okay great since
the player is not carrying anything nope
nothing happens all right great
now let's pick up something from the
container counter okay so now the player
is carrying a tomato approaching clear
counter press a button and yep there you
go there it is alright Awesome
everything worked
now this is an excellent point to know
just how easy this was to implement and
the reason why it was so easy was
because we focus hard on running some
good clean code for how the object and
the appearance system works because we
took some time to think about that it
was now very easy to implement this
brand new action so this is a very very
clear example of the power of writing
good clean code okay so with that now
let's implement the rest so over here
there's no kitchen object here and the
player is carrying something but if not
we've got the L so player has nothing
so if the player doesn't have anything
so let's not do anything so player not
carrying anything
so those are all the possible States up
there and then down here if there is a
kitchen object on this layer counter if
so then let's check if the player has a
kitchen object
so in this deep layer is carrying
something
and if not
then the player is not carrying anything
so basically if there is a kitchen
object here and the player is carrying
something if so then we don't want to do
anything since we can't give the player
two items however if there is a kitchen
object here and the player is not
carrying anything then we want to give
it to the player so let's just get the
kitchen object the one that is on this
clear counter
and let's do the exact same thing so set
the parent and set the parent onto the
player okay so that's it as you can see
some very simple logic so let's test
okay here we are and if we interact nope
nothing happens okay great now pick up a
tomato go there drop it yep there it is
now if I interact again yeah there you
go I picked it up again so I can go
somewhere pick it up drop it and
everything works perfectly all right
awesome
now the last thing that we need to fix
is the container counter
right now it's giving out an object
every time even if the player has
something so if I pick up the other
works now if I pick up again there you
go we've got our nice helpful error this
should never happen
so let's add some nice checks
so over here on the container counter
okay we have our interaction
and before we spawn anything let's just
see if the player can pick up something
so once again very simple let's just go
into the player and we check does the
player have a kitchen object if so we're
not going to give it anything but if the
pointer does not have a kitchen object
then yep the player picks it up and we
give it the object
okay so that's it it's this simple Let's
test
so here we are let's pick up some cheese
okay great now pick up another one and
nope nothing happens okay great we're
already carrying something so we cannot
drop anything now drop it in there now
pick up a tomato any of it works I can
pick it up drop it and yep everything
works okay great let you see one more
thing
over here the container counter is
spawning the object and the object is
the one that we assigned
so over here in scene view we've got the
container counter this one is placed on
the scene and we made an override to
spawn a cheese block
technically we could keep doing this
pretty much just duplicate objects
modify the Sprite modify over here the
kitchen object that would work but
another better approach would be to
Simply make some prefab variants and yep
that does work you can make a variant of
a variant so let's do examine that over
here on the container counter let's
right click going to create and let's
create another prefab variant and let's
say container counter this one will be
the Tomato now let's go inside the
prefab and over here make sure it has
the kitchen object for the Tomato okay
great and over there on the Sprite so
let's find the object Sprite and choose
the Tomato Sprite so there you go this
one okay let's exit and Save
all right now once again let's right
click on the container and let's make it
another one this is going to be the one
for the cheese block
so let's go inside of it and over here
modify it for the cheese block and
inside the actual visual let's modify
the Sprite and sectionally down so the
cheese block okay great let's go back
outside
and since we're here doing this let's
make all of the other grab my objects
from the containers
so let's first make the kitchen object a
so so let's go over here we can right
click go into create create new kitchen
object so let's make one for the brand
then let's see if we get this one we're
going to have a cabbage and finally
we're going to have the meat Patty
uncooked
all right so now let's make sure to
assign all the data for all these script
along objects
first we need to make the actual kitchen
object so let's duplicate tomato name
this one bread let's go inside of it
and first for the kitchen object the
song Let's make sure to drag the correct
one okay there's the bread and for the
visual this one is not a tomato so let's
go inside our visual acids inside the
prefab visuals let's pick up the bread
visual okay there it is
that's all we need so let's go outside
save the changes and then select the
bread scripting object drag the prefab
reference okay for the Sprite this is
the bread and finally just call it bread
okay let's do the same thing for the
other one so next up for the Cabbage
let's do the Cabbage drag the Cabbage
script object let's go inside and modify
the visual so the Cabbage visual
okay that's it
then on the Cabbage scorpion object drag
the reference for the prefab let's
assign the Sprite and finally give it a
name cabbage
and finally the meat Patty and cooked so
let's do that one so let's duplicate it
name it meet Patty uncooked
let's go inside modify the kitchen
object so for this one and for the
visual let's select here it is the meat
Patty uncooked
okay let's go back outside and on the
escort mode object
let's just drag the prefab
assign the Sprites so this one is the
uncooked so it's this one
and finally meet Patty uncooked okay
great so we added all of these squared
more objects
we also have the pre-files with the
visuals and the electric scripts now
let's just make the container counter so
once again let's create another variant
so prefab variant this one is for let's
say for the brand
then let's make all the other ones
already so let's go make another prefab
variant
this one is going to be for the meat
Patty uncooked
and finally another variant also here
make sure you're creating a variant of
the container counter don't make an
accident of creating a variant of
something else let's make another
variant one final one
and this one is going to be for the
cabbage
okay we have all the variants now let's
just sign them so let's go inside the
bread and over there modify the
description object for the brand and for
the icon modify for the bread icon okay
let's go to the Cabbage save the changes
modify that one for the cabbage
go into the icon and modify the icon and
finally the meat Patty uncooked let's go
ahead modify this one for that one and
the icon put it on that one all right
everything is working
now let's just place them over here in
our scene so let's get rid of the ones
that we made some overrides
so let's get rid of that container
counter and set for that one let's drag
the cheese block put it right in there
let's put it on X 1.5 y of 0 Z of 3.5
okay
then down here for this one let's put
the Cabbage next to it let's rotate it
to face upwards
so like that let's put it on next of
minus 1.5 y of 0 and -5 on the Zen then
for tomato let's get rid of this one and
use the proper tomato one
so let's rotate it put it on an X of 0 y
0 and -5
okay next we want some bread so let's
put the bread up here on the left side
let's put it on X of minus three zero on
the Y and 3.5 on the Zen
and finally the meat Patty and Coke
let's put it over here a bit more on the
side
let's put it over here on X of 7.50 and
3.5 alright so we have positioned all of
them let's just make some more clear
counters so we can actually place the
objects so let's put this one over here
on minus 4.5 this one over there let's
also put some counters let's say one on
the right side and a bunch more down
here let's rotate them upwards
let's put this one on 1.5 minus 5.
and one more over here on the side
okay great so we have all of our
container counters as well as a bunch of
clear counters so let's test and make
sure that everything works okay so here
we are let's go down pick up a tomato
yep there's tomato now a cabbage yep
there's a cabbage now some bread there's
some bread and some cheese there's some
cheese and some meat and yep there's
some meat all right Awesome everything
works
so with this over here we added the
ability to pick up and drop objects on
an empty container and spawn them from
all kinds of container counters now in
the next lecture let's build the counter
we can interact with in a very
interesting way
hello and welcome I'm your code monkey
in this lecture we're going to create a
cutting counter so this is going to be a
counter where we can place an object
like for example tomato and after doing
a secondary interaction we can slice it
however before we do that let's just fix
one slightly annoying issue
so right now the player is walking
around okay that's great I can approach
a counter and interact with it that's
great however if I approach account from
the sign look how the player is pointing
towards the right and if I press the
double key I can indeed select it but
the player does not rotate to face the
counter so that's just a minor visual
issue but still I'd like to fix it so
let's do that very quickly basically the
issue is over here on our player script
so we scroll down and find our handle
movement function okay
so here we were doing a bunch of
Capstone cans in order to fix the
problem with the diagonal movement so
you try to move in One Direction if not
try to move in just one of those and if
we can move then we assign a move
Direction and then move it basically the
problem that we have here is that if I
press W to face towards the counter then
over here when we do this logic so it's
going to first attempt the X movement
only and the x is going to be zero so
the move there X is going to be zero
zero zero so it won't actually move
anywhere which means it won't be able to
move so this one becomes true which then
sets the move direction to zero zero
zero which then down here when we have
our rotation it's not actually going to
rotate to anything so we want the player
to still not go through any objects but
we only want to modify the move there
over here if we actually move in any of
these directions so the solution is
actually super simple it's over here for
the can move we can move if there's
nothing on there and if the move
direction.x is not zero
so that's really it if we are attempting
to move in the X at all and if there is
nothing on there then we can move which
means we then assign the move direction
if not then we don't touch this and same
thing down here so we can move if
there's nothing on it and if the move
there dot Zed is not zero
so that's it just this one simple change
and now the player should be able to
rotate
so here we are and if I look over there
and the player is currently unlocking to
the left and if I press W to point
towards the container counter and if
there you go the player does rotate a
little bit so that feels a bit more
natural
all right so that's just a tiny visual
thing that I wanted to fix okay so let's
keep going
now let's handle the actual cutting
counter
so first of all as usual let's make a
counter variant so let's right click on
the base counter create a new prefab
variant call it the cutting counter
let's go inside of it
and over here first thing we need is the
visual so let's pick up from the assets
The Cutting countervision so here it is
then we need the selected so let's
duplicate this one let's rename this one
to seal lectin and on the animator let's
get rid of it and instead at the
component the selected counter visual
okay great now let's write divisions for
the visual game object array and by the
way here's a quick tip on the right side
on the inspector you can see this nice
little lock icon
so if you click on it then that means
this inspector will not change as you
select other objects
so I can click on and select something
different and this one does not change
it is still showing the selected object
now this is this one when you want for
example to drag multiple things so you
can unlock the inspector then the
hierarchy you can use shift click to
select multiple objects and then just
drag them all directly inside the array
that's it just a nice quick tip so
everything is done let's unlock it there
it is okay so that said let's just
assign the selected material so the
counter select material let's make it
just one percent bigger so let's select
them all 1.01 okay and let's start with
all of them disabled okay
so the basic setup is done
now let's make our script to run this so
let's go down let's create a brand new
c-sharp script for The Cutting counter
let's select the apparent game object
and attach a cutting counter and let's
open
now here as usual instead of all this
let's start off by extending the base
counter okay
once again thanks to how we set things
up using such clean code this is pretty
much all we need to make a counter
with this the counter already works as a
counter then next thing we need is to
customize any logic specific to this
counter by just overriding the interact
function so that's it now over here we
can put whatever logic we want just for
the cutting counter and for this one for
star is actually going to be just like
the empty counter meaning we're going to
be able to drop objects on this
so let's just go directly into the clear
counter so here it is and let's just
copy all of this code go into the
cutting counter in Payson okay so the
exact same logic so checks if there is a
kitchen object or not checks if the
employer's carrying something or not and
picks up or drops in with this let's do
a quick test just to make sure this one
is working exactly like the clear
counter
so over here let's just make sure to
drag in less references so on The
Cutting counter let's make sure to drag
the countertop point so drag that
reference and then on the selected Drag
The Cutting counter reference okay
everything is good let's exit this
prefab make sure to save all the changes
and over here in the scene view let's
Place one of our cutting counter so
let's Basin right in there let's put it
on X of 4.5 0 and 3.5
okay so let's test
all right so here we are now if I
approach and I interact nope nothing
happens okay great pick up some cheese
and drop it on there any of there it is
I can pick it up I can pick up some
bread drop it and yep everything works
okay so far so good
now the next goal is to use the knife
and actually slice the object that is on
there and for that the first thing that
we need is we're going to need a
different input right now we only have
the movement and the interaction so
let's add another alt interaction
for that let's go into our input action
so let's open it up
let's make another action so create a
new action call it interact alternate
and for The Binding let's put it on
another key so let's listen and I think
on F makes sense
so let's go ahead select this one
then as usual let's make sure to save
the asset which in turn is going to
generate C sharp plus and compound the
code okay great
now we can go here into our game input
class and let's do the exact same thing
with it for the interact action so first
of all let's listen to it so let's go
inside the player input actions inside
the player action map so this one is the
interact alternate and let's listen to
the performed event
okay and when we have that let's fire
off an event pretty much the same thing
so interact alternate action
and down here let's just fire off this
event so
let's invoke using this and even RX dot
empty
okay so we have the input for the
interact alternate
now let's go on the player to listen the
same way we're listening to the regular
interact action
so over here on the player script let's
see how we're doing things so we go into
game input and listen to that so it's
the same thing game input and on
interact alternate action let's listen
to this one and when this one happens
lets you pretty much exactly the same
thing except we're just going to call a
different function
so instead of interacting let's call
interact Alternate which in turn
obviously means we need to Define this
function
so let's go into our base counter
so here we are on the base counter we've
got the interact and let's make another
one exactly the same just different name
interact alternate
okay that's it and now we are only going
to implement this in the ones that need
implementation
so for example on The Cutting counter
over here let's write down so public
override
and let's override the interact
alternate
and now here let's check check if
there's something placed on here so if
there's a kitchen object placed on this
counter
if so then let's basically cut it
and for cutting it the simplest way is
really to destroy whatever object is on
there and just spawn the slice object
so let's handle destroying a kitchen
object
for handling that let's go over here on
the kitchen object script
and let's make a simple function for
this object to destroy itself so let's
go up here make it public return void
and for name I like to use the name
destroy itself to make it destroy this
object
and really all we need to do is just
destroy and call destroy on this game
object
however before we do let's make sure to
clear the parent so let's go into the
kitchen object parent clear it and then
destroy the game object okay that's
great it's really this simple
and then on the cutting counter let's
get the kitchen object that is on here
and tell it to destroy itself okay so
let's raise the object
and after we do let's just spawn the
slices object so for now just keep
things simple let's make a direct
reference up here let's make a
serialized film
let's make it a type kitchen object so
and for the cut kitchen object the cell
okay so we have this then here in the
editor and let's make sure to drag the
reference so let's go inside the cutting
counter and let's open up the prefab and
inside let's assign this one that means
we need to create the object so let's
actually do that first
so let's create a brand new kitchen
object to sell let's come out for the
tomato slices
then if we do this we need to create the
prefab so let's once again do the same
thing tomato slices make the prefab
let's go inside this prefab let's modify
the visual so use the tomato slices
visual okay and drag the reference for
the other kitchen object for the tomato
slices okay
so the visual prefab is good and let's
just go into the kitchen object let's
just make sure to drag the prefab
reference then let's assign the tomato
slices icon and just come with tomato
slices
okay so we have the kitchen object so
now we can go into the kitchen counting
counter and over here let's open up and
set this one to the tomato slices
okay so we have all the references let's
go back outside save it
and back over here in our code so we
have this now we just need to spawn this
object
so we're really just going to spawn it
pretty much exactly like we did over
here on the container so we just go into
the description object spawn the prefab
and set the appearance so let's do
exactly that
over here we destroy the object then we
instantiate the cut kitchen object and
instead of getting into the player let's
put it on this
okay so that's it we should be able to
place a tomato directly on top of the
cutting counter and it should be able to
transform from a tomato into a tomato
slices
okay so here we are let me pick up a
tomato go up there drop it and okay that
works now if I press the onton track key
press it and if there go it did work the
Tomato was destroyed and the tomato
slices were spawn and I can pick them up
place them anywhere and yep everything
works alright awesome so with this the
basics are fully working let's just
briefly clean up this code
we already saw a little bit of code
duplication so the cutting counter is
going to spawn an object and the
container counter is also spawning an
object so we're copy pasting these two
lines of code in multiple places so
instead of doing that let's put it in
just one place
and actually a good place to put this is
on the kitchen object list itself so it
makes sense that this one is responsible
for spawning more objects
so let's put it over here however let us
not make it a regular function instead
let us make it a static function again
just like we saw for The Singletons by
making it static it means that the
function is going to belong to the class
itself as opposed to any instance so
let's go all the way down to the bottom
of the file personally I like to put
settings at the end and over here let's
make public make it static we're going
to return a kitchen object and let's
call it just spawn kitchen object
and for our parameters let's receive the
kitchen object that so
and let's also receive the kitchen
object parent
okay so that's it and we're going to do
the exact same thing so let's go into
the cutting counter and copy the code
that we're using and over here just
paste it in there so we go inside here
spawn the prefab and set it on this
parent
and finally let's return it
so let's return the kitchen object over
here let's pick it up so the kitchen
object
we get it and then we do kitchen object
set the parent and finally we return the
kitchen object
all right so that's it here we have a
super simple function that we can call
very easily it won't automatically spawn
an object and set to parents so now
let's just call this from somewhere so
over here on the cutting counter instead
of doing all this let's just go into the
kitchen object again remember let's go
through the class name itself and not
any instance and over here let's call
the function pass in the cut kitchen
object the cell and for the parent it's
going to be this
all right so that is now much much
simpler and let's do the same thing over
here on the container counter so if the
player is not carrying anything
let's give the player this object and
give it to the player just like this
as usual when we do some kind of
refactoring let's do a quick test make
sure everything still works exactly the
same
okay so here we are and if I go to the
counter and pick it up yep it does work
to spawn the object now I can drop it in
there I can cut it and yep there you go
everything does work all right so far so
good
so with all this basically we have
created a brand new counter where we can
cut objects however right now there's
obviously one huge layering funnel if I
now pick up a cabbage and I drop it on
the cutting counter and I interact with
it that cabbage has suddenly magically
turned into tomato slices now that is
obviously not intended so for that let's
define a proper cutting recipe and let's
do that in the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to create
another scriptable object type this one
is going to be for handling our cutting
recipes
so here's our game I can pick up a
tomato drop it on the cutting counter
cut it there you go slice Tomatoes
however if I could pick up a cabbage go
there cut it and there you go cabbage
turns into tomatoes so we have an
obvious issue The Cutting object is
currently hard-coded instead of being
based on the object we put on top of it
so to solve that let's make another
scribble object type like I mentioned
scribble objects are excellent for
storing and organizing data so it's
perfect for this use case basically we
want a script mode object to hold a
reference to the regular object and the
cut object so we can then identify the
input in order to spawn the output okay
so let's build that let's create a brand
new c-sharp script
call it the cutting recipe so
and let's open it
okay so now here on let's do exactly
that so something extremely simple so
instead of modern behavior this one is a
script mode object let's add the create
asset menu and finally for the fields
let's do just an input and output so
we've got of type kitchen object so
let's go for the input and another one
for the output
okay so that's really it super simple
now here in the editor before we create
and let's keep things organized so let's
make another folder
let's make it for the cutting recipe so
and inside let's frequently create a new
cutting recipe
let's call it tomato two tomato slices
and over here let's select the reference
so the input is going to be our tomato
and the output the tomato slices
okay so this is how we're going to
handle things
so let's go ahead and make actually the
final kitchen object that sews
so let's make yet another one a kitchen
object to sell
let's make it for the Cabbage slices
and then let's have another one for the
cheese slices
okay so now let's make these so as usual
let's if we get tomato make the cheese
slices and another one for the Cabbage
slices
let's go inside of it and first of all
drag the kitchen object as so so this
one is the Cabbage slices
and let's go modify the visual so
instead of this one the Cabbage slices
okay
so we have this let's save the prefab go
outside then the other one we made the
cheese slices so let's swap this out
let's find the cheese slices
and modify the kitchen object as well
okay
so finally just assign the references so
on the cheese slices drag the cheese
slices prefab let's assign the icon and
call it cheese slices
okay so finally on the Cabbage slices so
these are the Cabbage slices
let's pick up the icon and let's drag
the prefab reference okay so far so good
we have created our new icons
and over here let's just make all of the
other cutting recipes so we've got two
more so one is going to be the cheese
block onto cheese slices and the other
one is going to be cabbage onto cabbage
slices
so we need is just to drag drop the
scriptable objects so for this one
cabbage let's drop the cabbage on the
input cabbage slices on the output for
cheese mug that's the cheese Wok on the
input and the cheese slices on the
output
okay great all of our data is now stored
in some really nice script mode objects
so now let's go here into our cutting
counter
instead of having a hard-coded kitchen
object let's receive a field of type
cutting rest BSO except we're going to
have multiple so let's actually make an
array of this
call it the cutting recipe so array
now for the interaction this is picking
up and dropping things so let's leave
that the same for now and over here on
the alternate
basically we need to find out which
recipe we should apply to this
so how I didn't find that is pretty
simple so we've got the kitchen object
that is placed on this object and we've
got a list of cutting recipes which in
turn has the input so we just need to
cycle through all the recipes in order
to find the one where the input matches
okay so let's go down here make a
function to do just that let's make it
private we're going to return a kitchen
object as so let's come with get output
for input so we give it a certain input
and Returns the one that matches that
one
so it turns a kitchen object as so for
the input kitchen object as well
here on let's cycle so do a for each
cutting recipe so in the cutting recipe
so right so let's cycle through all
these and just check if the cutting
recipe so if this one dot input matches
the input that we received
if so then this is the one we want so
let's return the cutting recipe
so.output and to make sure that the
function Works down here let's return no
okay so that's it we give it an input
and we get back the output
so now here we just need to make sure to
do it before we destroy the current
kitchen object
so let's store a kitchen object as so
for the output kitchen object SL and we
just get the output from the input and
for the input pass in the get kitchen
object so that's the one inside of this
cutting counter and let's get the
kitchen object this out so that gives us
the output and then we just spawn that
output
okay so that's it let's test
finally back in the scene let's just go
inside the prefab and over here on
cutting counter we need to make sure to
add all the recipes
so let's add so the cabbage
then a second one for cheese Mock and
finally for the Tomato okay so there are
of our recipes let's go outside save the
changes and let's test okay so over here
let's pick up a tomato go up there slice
it there you go got some tomato slices
now pick up some cheese go here slice it
and there you go got some cheese slices
and finally the Cabbage go up there
slice it and there you go some cabbage
slices all right awesome
so everything is working perfectly
however now let's say that I want to
pick up some bread and bread should not
really be able to be cut so if I go
ahead and I cut it and there you go
there's our air we have no recipe that
takes bread as an input So that
obviously leads to a known reference
exception
now here we have two options for solving
this problem
one option is simply over here when we
do the interact alternate
we get the output for the input and if
this one returns null then we just don't
cut it
so we don't destroy it and we don't
spawn it or alternatively we can
actually add some Foundation over here
when dropping objects so we can make
sure that we only drop valid cutable
objects now both approaches are valid
and actually we do need to implement
both them we'll see why in a bit
so let's do both starting off with the
validating the drop
so first we check if there is no kitchen
object on this cutting counter then we
check if the player is carrying
something and then we drop it from the
player on this
so over here let's just check if there's
any recipe that has whatever the player
has as an input
so let's go down here make a function to
do that private let's return a bone and
call it has recipe with input
and we're going to receive a kitchen
object episode for the input kitchen
object lesson
and over here lets you pretty much
literally the same logic so we have this
and if we find a match then let's return
true so there is a recipe with that
input if not return false so now up here
when the player is carrying something
let's check
if has recipe with input and give it the
player get the kitchen object the player
is holding and get the kitchen object as
so
so if there's any recipe that takes
whatever the player is carrying as an
input
if so then we drop it
okay so like this let's test and see if
we can drop the bread
okay so let's pick up some bread go
ahead drop it and nope does not work
pick up some cheese and yep that one
does work
however now we actually also need the
other validation that I mentioned the
reason is because if we place a valid
option like for example the cheese there
so that works and I can cut it and yep
that does work however Now the recipe
the cheese moth became cheese slices and
now cheese slice is no longer an input
to any cutting recipe so now if I try
cutting again
I've got another no reference exception
so we need to validate putting objects
on top of it and also actually cutting
them Technologic is also pretty simple
so let's go down to the interact
alternate so we just check if there's a
kitchen object on The Cutting counter
and has recipe input
and let's get this kitchen object get
kitchen object as so just like this
so we're only going to cut if there is a
kitchen object here and it can be cut
okay so let's test
so first of all the other one let's pick
up bread and nope cannot travel okay
great now pick up some cheese and I can
drop now interact cut now cut again and
yep there you go no more errors all
right awesome okay so here we have
everything working perfectly I can pick
up a cabbage go up there cut it into
slices I can slice some cheese and I can
even slice some Tomatoes everything
works perfectly now the one thing
missing from our design is we don't
actually want this action to be instant
we don't want to just press a button
everything slices instantly instead we
want to have the player press the button
a few times in order to actually cut so
let's do all that in the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to add the
mechanic for the player to be able to
cut multiple times in order to actually
cut an object
okay so we have our cutting counter I
can drop a tomato and press button there
you go it cuts it straight away now we
want the exact same logic but we want it
to take a few Cuts before the cut object
is spawned
so let's start off by going here onto
the cutting counter and basically let's
keep track of some kind of progress
basically the way we do that is pretty
arbitrary it's up to you to decide for
example you could use a normalized float
however for cutting since this is going
to be a discrete action let's actually
count the numbers with an end so let's
store a private end just call it cutting
progress
okay so now let's begin by actually
initializing this progress so when the
player drops something on there let's
set this one to zero
and then down here when we have the
interact alternate we do our logic and
when we do let's just increase this by
one
and now we need to know if the object
has been cut so we need somewhere to
Define some kind of maximum
and for that we can actually do it
directly on the recipe so so inside the
cutting rest PSO over here we've got the
input we've got the output and let's
also Define an end
for The Cutting progress Max
okay that's it
and back here in the editor let's go
into the Tomato to tomato slices let's
say this one takes just three Cuts then
for the cheese let's also take three
cuts and for the Cabbage let's say it's
a bit thicker so let's say it takes five
cuts
okay so back in the cutting counter here
down here we are adding to our cutting
progress
so then we just need the recipe so in
order to grab the maximum so on
sectionally go down here and actually
make a different function so this one
just returns a Boolean this one a
kitchen object or so let's make another
one this one is going to return a
cutting recipe so
so get the cutting recipe so with input
and we're going to receive as usual the
kitchen objects so for the input
I'm really going to do the exact same
thing that we did up here next time
instead of returning the output let's
return the recipe itself
okay so now that we have this more
logical one we can actually get rid of
all this copy paste code
so over here we just get the cutting
recipe so
and we just get it and pass in the input
so we have this one over here if this
one is not no then we're going to return
this on the output
and if not we're just going to return
null
okay so we're doing the exact same logic
just a bit similar okay and up here
pretty much the same thing
so has recipe with input let's get the
cutting recipe a cell
and basically just return if this one is
not known
okay so we have our three nice sample
functions so let's just use this one to
get the cutting rest BSO so let's
actually copy this and go up here so we
do the cutting progress then let's pick
it up the one for this input so the
input is going to be this one the object
currently on the cutting counter and
over here we already know that there's
going to be a recipe with this input
since we've gone through this if
so then we can just check if the cutting
progress is bigger or equal to The
Cutting recipe so and let's grab the
maximum
if so then yep we do spawn it
okay so that's it some very simple logic
Let's test
so here we are let's pick up a tomato go
up there and okay now I'm going to press
enter direct okay press once and yep
okay so far so good nothing now two
times and Alpha press a third time boom
any up there you go got the nice slices
now for cheese same thing one two three
yep it works and finally for the
Cambridge this one should be five so one
two three four and five any up there you
go everything does work perfectly all
right awesome
so with this we now have progress in our
cutting logic although of course just
like this it's not very good for the
player the player has no way of knowing
what exactly is going on so we need some
kind of visual feedback so for that
let's add a really nice visual progress
bar and for doing this we're also going
to learn about a really awesome Unity
feature these are World canvases
so before we make the world canvas on
The Cutting counter let's actually set
something up over here on the scene
itself
let's first create a regular canvas
we're only going to use this in a couple
of lectures but let's first do that one
just for now
so let's go on the plus button go into
UI and let's create a brand new canvas
okay so there you go that creates a
canvas and an event system
like I said we're only going to worry
about this in a little bit but for now
let's just leave those as is
and also since we're here creating some
objects let's also take some time to
organize our hurricane
Unity suddenly doesn't really have any
folder objects so you can't organize the
hierarchy in any folders however you can
use empty game objects essentially as
folders
so let's make a brand new empty game
object let's call it counters
and now very importantly for empty
folder objects make sure you put them on
zero zero zero so nothing breaks
so make sure you put it on there before
you drag the counters
and now let's just drag on the counters
inside so all the clear counters put
them outside this one also drag it
inside and all of these counters put
them all inside so there you go now
hierarchy is quite a bit more clean
okay so now let's make the cutting
progress so let's click on the cutting
counter
and let's go inside our prefab so let's
go inside of it
now over here let's right click on the
hierarchy and we're going to create a UI
let's create another canvas
now for this one let's give it a name
let's name it the progress bar UI and
for this one over here on the inspector
for the settings instead of being screen
space overlay let's make this one a
world space canvas
basically screen space means that it
would occupy the entire screen whereas
World space means that this exists in
the world in whatever position it is
so let's make it World space and over
here the fields actually unlock so let's
put the positions on zero and for the
width and height let's also put it on
zero
so basically the canvas is going to be
exactly over here by the way the
shortcut that I just used was the F in
order to focus on the object
so this useful if you're zoomed out or
zoomed in way too much okay
so we have this and we want the bar to
be a little bit above so let's actually
lift it up on the Y by a little bit so
over here let's put it on y of 2.5 okay
now I said the going with this is to
make a progress bar so inside the
progress bar UI let's create a new UI
image let's name this one our bar
let's put it with a width of one and a
height maybe of 0.2
so there you go just a really thin bar
and for the color you can play round
tinted with any color you want now for
progress I think maybe a blue or a
yellow something like that makes sense
so let's go with the yellow kind of like
this
okay so there's our really nice progress
bar
and for this let's actually use one
really nice trick for making a super
easy progress bar the image component
has a really easy way of making a slider
image however it only actually works if
you assign an image over here
so let's assign one in order to be able
to see those options
and for that in the project files
there's a texture white one by one this
is literally just a one by one white
pixel
so here it is just a one by one image if
only white
and as soon as we assign it we do see
over here the image type so we see a
bunch more options and the one that we
want is to set the Sprite as filled this
one lets you do some really cool really
easy effects for example you can make it
radial and look at what happens in there
as I modify over here on the film Mount
so as I go down look at that it's
radiantly filling so for some kind of
circular progress bar this would be
excellent but in our case what we really
want is just a horizontal bar so we're
here for the film method instead of
Radion let's go with horizontal
and if there you go now by playing
around this we have a really nice
progress bar
then if you want you can modify on left
to right right and left but yep like
this it looks great
now in order to modify this visual
really only we're going to need is
modify over here the film Mount this one
is a normalized value so between 0 and 1
so 0 is commonly empty one is commonly
full however one issue with this is when
the bar is empty then we can pretty much
not see so we can see the actual size of
the bar we can see what size it should
be
so with this it's pretty difficult to
see how far along we are but something
that is pretty simple we can really just
add some kind of background
so let's duplicate the bar let's name
this one the background
for this one for the image type we don't
want anything so let's leave it on
SIMPLE and for the color let's put it on
kind of a dark gray okay great and now
here's one very very important thing is
over here on the hierarchy let's click
and drag and place it above the bar
the reason why that is super important
is because the Sorting order and how it
works in unity basically when it comes
to UI elements inside a canvas the
Sorting order is based on The Horde in
the hierarchy basically it renders from
top to bottom
so the bar on top the background this is
going to render first and then the one
below it the bar is going to render
afterwards which means it's going to
render on top
so for the background we want to be
behind so place it above on the
hierarchy and that way it renders the
background and then renders the bar also
by the way for 2D Sprites Unity has
another different sorting method it's
all based on sorting layers and sorting
orders
I have video on that topic if you're
interested in 2D games
okay so with this we have the background
and then we have our film bar this way
we can see if the progress is being
filmed or not
also one more tiny thing that I like to
add is Unity has some really nice really
easy to add effects
so you can go into that component and
let's search for a shadow
this one does exactly what you expected
as a nice drop shadow over here on the
effect distance let's put it on 0.1.1 in
order to see
next one let's not do it on this one
we'll do it on the background so let's
get rid of this instead of going to the
background over here let's add the same
shadow
so if you put it on point one and minus
point one you better go a nice simple
and drop shadow or the other one that I
prefer so instead of the Shadow let's
add a really nice outline once again for
the effect distance 0.1.1 or maybe
actually 0.05 just to be just a tiny bit
and let's raise it on the alpha so there
you go nice little outline tour bar this
is just a visual thing so you don't have
to add this but personally I find that
it looks pretty good
so with all of this we have our Visual
and perfectly set up we've got our nice
bar all we need to do is play around the
filament in order to fill it
so now all we need to do is to connect
this to the logic but as usual let's
make sure to write some good clean code
so we do not want the cutting counter to
directly touch on this image
instead let's make a script to handle on
that so let's right click create a new
c-sharp script call it the progress bar
UI
and just personally as a rule I like to
open the UI to any UI script
you don't have to do that it's just a
rule that I personally find helpful to
follow that way just by looking at these
scripts I can immediately see this one
is a UI this one is script and logic and
so on
so on the progress bar UI on the main
game object let's attach the script and
let's open it
okay so now here we're going to need a
reference to our image
so let's add a serialized field private
and we're going to need the image type
and importantly this is inside using
Unity engine.ui so let's go up here
using Unity engine dot UI so we have our
image component okay great let's call it
the bar image
so we have a reference and now with this
obviously we need to have some kind of
reference to the counter so we know when
the progress changes so it's really the
same thing that we've already done so
many times throughout this course so
let's set a film up here serialize film
private cutting counter for our cutting
counter
then over here in the editor let's write
new references so drag the reference to
The Cutting counter and another one to
the bar image okay great
now we just need some kind of event to
update the bar image
so let's go over here into our cutting
count script let's make an event to
spawn that so public event let's use the
event handler the default standard
let's go with on progress change
and let's also make a nice event artist
to be able to send the current progress
amount
so let's make a public class on progress
changed event arcs and let's extend
event arcs
and then inside and let's put the
current progress
however let's also pass in the progress
as normalized since that's the what the
bar will use
so public Cloud progress normalized
and we're going to make this event of
this type
okay great so we have our event
now whenever we modify the progress we
just need to fire this event so over
here when resetting the progress let's
fire it so let's invoke pass in this
instantiate our event args and pass in
the progress normalized and to get the
normalized progress sectionally very
simple basically we just need to divide
the current progress by the maximum so
cutting progress divided by cutting
progress Max which is actually inside
the rest BSO so we need to pick that one
up
so let's go down there to pick up the
cutting progress recipe
so we picked this one up and we go in
there and get the maximum
however over here we also need to be
very careful because there is one sneaky
issue here this has to do with how
c-sharp works and how instar divided
with other ends
for example if we had a cutting progress
of one and cutting progress Max of five
you would think one divided by 5 would
equal 0.2 however if we actually did
that over here we would actually get a
zero and the reason for that is because
we are dividing two ends cutting
progress is an end cutting progress Max
is also an INT and if you divide an end
by an end then the end result will also
be an end
since you cannot Define 0.2 in an end
the decimal gets cut down and you end up
with just zero so that would not be
correct in order to get the right value
from this calculation we need to make
sure to convert one of these values onto
a float so that's really simple we just
cast one of them so just cast this one
to the float just like that
basically now this one will first be
cast to a float and then we're going to
have a float divided by an end and the
end result won't be afloat so if you
ever do some math and you get some weird
results always make sure to check the
type of your numbers
okay so here we are correctly firing the
event and then down here when adding our
progress let's do the same thing let's
also fire on the event
so now we can go back into our progress
bar UI
and over here let's listen to the event
and again remember that if we're
accessing an external reference let's do
that around start and not an awake
so cutting counter listen to the on
progress changed event
when that happens let's just go bar
image and set the fill amount to what we
received from the event so the progress
normalized
okay so that's really it and also appear
on start let's initialize it as 0f so
the bar is nice and empty
okay so let's test
back in the editor let's just go back
into the scenes make sure the prefab has
been saved and let's head on play
and right away yep we do see the bar yep
it is empty now pick up some cheese drop
it and if I cut and if there go add a
little bit of progress now a bit more
and there you go there's our cheese
okay great everything does work now
let's add just one more tiny bonus thing
we can add some extra logic in order to
hide this visual if the bar is either
completely empty or completely full that
is actually pretty simple
over here on the progress bar UI script
let's just make some basic show and
height functions
so private void show and then we're
going to have
a private void Hind
on these one just game objects that
active this one set it to true and this
one set it to false
now on start we subscribe to the event
and then let's hide it okay
also here it's very important make sure
you hide it after you listen to the
event if for example You Can't Hide on
awake that would disable the game object
and the start would never run so it
would never listen to the event
so if you have reset the game object as
inactive make sure you do it only after
you're listening to whatever events you
want so we have this that's great and
then when the progress changes
let's just do a basic test so if e dot
progress normalized equals zero f or if
the progress normalized equals one F so
if the bar is similarly empty or
completely full
if so then let's hide it and if not then
let's show it
okay that's it let's test
okay and yep by default starts off
hidden let's pick up the Tomato go up
there and yep still hidden now I cut and
there you go there it is cut again and
yep there you go it hides itself okay
great so we've got a nice little visual
let's do just one more final thing let's
add a really nice animation
if we go inside the cutting counter and
we'll look at the cutting counter visual
over here note how it already has an
animator
just like we did for the container
counter it's all very simple
so basically just has a cut parameter
when that happens it just cuts the
counter so just plays a simple animation
since it's going to be pretty much
exactly like the container counter and
let's actually duplicate that script so
let's go down find that script so the
container comes to visual let's
duplicate this so Ctrl d
let's rename this to The Cutting counter
visual
okay let's open
and over here let's rename the script so
the cutting countervision okay great
then for the parameter let's rename this
instead of open close is going to be
called cut
and for the string it's cut again make
sure you write it case sensitive make
sure it's all correct
then instead of having a container come
through we've got a cutting counter and
a cutting counter
and finally we just need to listen to
the correct event so technically we
couldn't listen to the unprogressed
changed however that one also gets fired
over here when the cutting progress is
zero we don't want the current mission
to play when this happens so let's just
make another simple event so a public
event event handler
let's call this just on cut
okay and then down here when we have our
cutting progress so we cut and let's
just invoke this event
okay that's it super simple
so now on The Cutting counter visual
let's go into the cutting counter and
into the uncut event let's listen to
this and we're going to set the trigger
example like this so get rid of the
container counter like this
okay there you go a very simple script
so now here back in the scene view
inside the container counter prefab
let's just go inside the visual let's
attach The Cutting counter visual just
need to drag The Cutting counter
reference and that's it let's exit the
prefab save it and let's play okay so
now let's pick up a cabbage go up there
drop it and aren't interact and if there
you go we've got a nice little animation
all right awesome so I can drop things I
can cut them and everything works
perfectly
all right
so here we added a cutting progress to
our cutting counter and we also learned
about yet another very useful ENT
feature called World canvases
and at the same time you might have also
noticed that the canvas is looking at
the camera in kind of a weird way
basically just pointing straight forward
this can sometimes make it difficult to
see so let's work on that in the next
lecture
hello and welcome I'm your code monkey
in this lecture we're going to build a
very simple but very useful script to
make an object look straight at the
camera with various options
okay so we previously made the cutting
counter and when I placed something yep
there's a nice progress bar
so now that this is working let's do one
more thing right now look at how the bar
is oriented it's looking quite a bit
slanted that's because we have a
perspective camera and it's looking from
top down
now this is one of those things that is
kind of personal preference so maybe you
don't like it just like this
but a lot of the times you want these
World UI elements to face the camera
just like a regular UI
one example of this problem is for
example let me pick up the cutting
counter duplicated and let's put one
down here so rotate it upwards
okay let's put it on 4.50 and minus 5.
now if I place something on there and I
cut it yep like that the bar is Now
inverted so let's make a simple script
to solve this problem
let's go into our scripts create a new
c-sharp script call it look at camera
let's go on to The Cutting counter
prefab let's open it up go inside on the
progress bar let's attach the script so
the unlocked camera okay now let's open
so from here let's use an interesting
function so let's use a private void
late update so not update we have the
late update so if this is the first time
you're hearing about this like the name
flies this one is going to run after the
regular update so every single update
and all the objects is going to run and
then on the late updates so kind of like
you've got awake and start you have
update and late update why this is
useful specifically for this script is
because for this element you really want
us to run the orienting logic you want
that to be done after whatever that
object does in the update in this case
this object will never move so it's not
really an issue
but for example if you had some kind of
moving vehicle with a warm cameras on
top if you have that you would want to
set the Warren canvas and location to
unlock the camera after the vehicle had
moved otherwise the canvas would not
look perfect so anyways because that
here we're doing on late update and now
we can just look straight the camera so
we can just do transform dot lookup
and for the Target passing the camera
Dot main.transform
this function makes this transform look
at another transform or another point so
this will make it look straight at the
camera
also by the way one quick note here in
some other tutorials you might see
people telling you not to use
camera.main the reason for that is
because this field did not used to be
cached so every time you use this it
would cycle through every single game
object in the scene until it found the
main camera so that was obviously really
bad for performance but nowadays this
field is now cached by default on the
ENT backend so you no longer need to
Cache it yourself accessing it directly
just like this is now fine
okay so with this let's test
just make sure to save the prefab and
let's hit on play
let's go ahead pick up a cabbage put it
up there and if they're young look at
that how it's looking straight at the
camera and for this one down here same
thing cut it any up there you go both of
them are looking straight at the camera
okay so that's great
you can also see exactly what it's doing
if we try to move the camera again we're
using cinemachine so let's move the
virtual camera
so over here if I just play around with
the position.x look at that look how as
I move the camera yep the objects are
perfectly looking straight at the camera
so that's great that's what we want but
also you might notice one thing notice
under the bars are actually inverted
instead of going left to right they're
actually going right and left basically
this has to do with how the canvas by
default assumes you are essentially
going to look at it from behind instead
of looking forward so that is why when
this game object is pointing straight at
the camera it's essentially inverted
so to sum this is actually quite simple
we basically just need to look in the
exact opposite direction
but at the same time sometimes we might
want this exact Behavior having
something looks right at the camera
maybe we do want it to be inverted
sometimes so for that let's make a nice
complete script with all of our possible
options and for the finding options it's
also an excellent way to learn about one
more thing which are c-sharp enums enums
are an enumeration meaning a fixed set
of options that you can have of
something
so these are really useful when you have
a fixed set of something like for
example maybe a fixed number of options
so for example up here let's make it
private make it an enum and let's call
it mode and then inside we can Define
all of our options so let's say we have
the regular look at it and then look at
inverted
okay so we have these two options in our
enum now let's do a field of this type
and expose it in the editor
so let's make a serialized film private
of type mode and call it mode
okay let's save this and look what this
looks like in the editor and if we go
inside the cutting counter and we'll
look at the progress bar
even look at that the mode shows up and
it shows up as a really nice drop down
menu so since we have a limited number
of options we've got a really nice menu
where we can choose each round if you
want
so that's really awesome that's one of
the benefits of enums they are really
easy to use over here in the editor
now back in the code here and let's
decide which one to use
so on The Late update let me just do a
switch on our mode in case we are on the
regular look at mode then let's see
exactly this let's simply look in in
case we are on the look at invertent
for this we just want to look at the
inverse position so that's actually
pretty easy we just calculate the
direction Vector from the camera to this
object
so a vector 3 call it deer from camera
and to get direction from the camera we
start from this object so this
transformed that position subtract the
camera dot main transform position
so this gives us the direction pointing
from the camera and then just to
transform down look at
and instead of looking at the camera
let's look at the opposite position so
let's look at transform that position so
our current position points the
direction from the camera so we're going
to be looking at the exact opposite
point
okay so that's it let's test
and right now by default we have the
regular look at so let's just see it
let's just play some objects okay so
right now it's still inverting
and something real nice is you can play
around the enums even as the game is
running so let's go inside the cutting
counter on the progress bar UI for this
one let's swap from Lookout to unlock
inverten anything like that that one is
now looking perfectly
so this one is using Lookout and this
one using look at inverted
okay great it's all working
however yet another thing that is all
about personal preference
note how the visual has a slight slant
this is due to how the visual section
looking directly at the center of the
camera
so you can really see it if I move the
camera left and right how it Slants
going left or going right
again the Zone personal preference it's
just a visual so maybe you do want this
look but let's see another method so
over here in our modes let's add two
more let's add camera forward and Camera
forward inverted
and then down here on our late update
let's add those so the camera forward
and then we have the camera forward
inversion
so for this one for the camera forward
super simple let's just take this
transform use the forward which again
you can get or you can set it and let's
set it to the exact same one as the
camera Dot main.transform.4
and for the inverting example the same
thing X7 set of four do we do minus four
okay so let's see what this looks like
okay so here's the game with both
counters they're both currently using
the unlockit mode now if we put a look
at inverting yep that one goes left to
right okay great now if I put camera 4
in give a look at that now that one is
perfectly straight
so even as I move the virtual camera on
left and right look how that one is
always perfectly facing the camera as if
it was a regular UI owned
and for the inverter does the exact same
thing but invert and so just like that
so that's it these are the four modes
again these are all just visual elements
so pick whatever you prefer for me I'm
going to be using this one the camera.4
so that everything is perfectly
horizontal so I'm just going to make
sure to go inside the prefab and on the
prefab itself modified and set it as
camera.4
and now if I add the cheese there yep
looks great and if I had a cabbage here
and yep it also looks right
all right so here we created a really
nice useful generic script to make an
object look straight at the camera in
various ways note how this one has
nothing to do with canvas or a progress
bar or anything it's really a generic
script to look at the camera so you can
apply this to anything where you want it
to look at the camera
okay so with that the cutting counter is
fully done
now let's handle the trash counter in
the next lecture
hello and welcome I'm your code monkey
in this lecture let's create the trash
counter this one is actually pretty
simple it's how we're going to drop
something and just destroy it okay so
making the trash counter is going to be
super super easy once again going to be
another great practical example of the
power of writing good clean code and
having good organization in your project
so let's do the same thing that we've
already done a bunch of times so first
of all let's make the prefab variant so
let's right click on the base counter
and create a brand new prefab variant
come with the trash counter
okay let's go inside and first of all
let's drag the visual so find the visual
prefab on the trash counter okay then
let's duplicate it to make the selecting
so let's rename this to selected
let's add the selected counter visual
let's add the visual inside of it and on
the visual let's select the other
material so the counter selected and
finally on the selected put it one
percent bigger 1.01
and start off with visual disabled okay
so that's the basics just like we've
already done so many times now let's
make this script to run this so let's
frequently create a new c-sharp script
call it the trash counter
and by the way here we're already
starting to have quite a bunch of
scripts so we should probably organize
the scripts folder so let's make a new
folder let's come with counters
and let's make another one and call it
scriptable objects
so on the counters let's drag the base
counter clear counter the container the
container visual The Cutting The Cutting
visual then down here the trash counter
okay let's drag them all onto the
counters folder and on these critical
objects let's put the cutting recipe and
the kitchen object as so okay now our
phone there is a bit more organized so
let's open up the trash counter
and over here as usual let's begin by
extending the base counter okay great
then let's implement the regular
interaction so override the interact
and on this one again it's going to be
super simple we just check if the player
is holding something and if so we
destroy it so just check if player that
has kitchen object so if the player is
holding something go into the player get
the kitchen object the player is holding
and simply call destroy itself
and that's it it's this simple back in
the editorial let's just attach a script
let's make sure to drag the countertop
Point reference and on the selected drag
the base counter reference
okay with this it should be working so
let's exit the scene let's save the
prefab and let's drag it over here onto
our scene so let's drag the trash
counter and put it maybe somewhere over
here on the corner
so let's put it here on an X of 7 y 0
and -3.5
then let's also fill out these spots
down here so let's duplicate the clear
counter put one in there put another one
in there
let's put another one on the side and
for the crash counter and let's align it
so let's put it a bit more to the side
so on 7.5 okay great and let's put it
inside the counters and now we can test
okay so let's see if we can interact
with it and yep as I approach yep I do
see it highlighted okay great and if I
interact obviously nothing happens since
the player isn't holding anything now if
I pick something up let's say a tomato
and I don't want this tomato so I want
to trash it and if there you go it does
get trashed all right awesome so this is
literally it like I said this is once
again another excellent example of the
power of writing good clean code this
was super simple to implement because we
have a really nice structure for how all
of our Counters work also because our
interaction system is very well built
also because the kitchen object system
is very well made it's because of all of
that great very clean code that we were
able to implement a brand new counter in
literally about 60 seconds
so once again I hope that by following
this course you know understand why I'm
always talking about the importance of
writing good clean code it's exactly
because this if you write your code
correctly it makes developing the game
so much easier at first it might seem
like the quick and dirty approach is
faster and usually in the beginning it
is faster but as soon as you add some
complexity the quick and dirty approach
suddenly won't scale whereas the
well-built clean code approach this one
will continue scaling very well so here
we have a fully functional trash bin so
we can dispose of unwanted objects next
let's build a much much more complex
Hunter let's build a stove counter which
also requires building a really nice
State machine so let's do that in the
next lecture
hey again another quick intermission
you're past the halfway point so
congrats again by now I really hope
you've already learned a ton from the
course we've already covered lots of
topics and built a ton of systems I hope
you've been following the website as you
go through the lectures and I hope
reading the frequently asked questions
that I sent you in some way let me know
in the comments how you've used the
course website did you just read the FAQ
or did you also download some project
files let me know I'm curious to know if
you enjoy my teaching song also look at
my other courses after finishing this
one especially the turn-based strategy
course that one is an excellent
follow-up for this one okay there's
still quite a bit more for us to build
and learn so let's continue in the next
lecture
hello and welcome I'm your code monkey
in this lecture we're going to build the
stove counter so we want to place some
uncooked meat then we wait for a bit for
it to be cooked however if we weigh too
much it's going to get burnt so let's
Implement that alright so as usual let's
first begin by making our counter so
let's go inside the prefabs the counters
let's right click on the base counter
and create new prefab variant call this
the stove counter and as usual let's go
inside of it let's find the visual so
inside the prefab visuals it counters
visuals here is the stove counter so
let's drag it then let's duplicate this
rename this one the selecton let's set
the component the selected counter
visual
then let's go inside on all of these and
by the way this visual actually has some
nice visuals that we're going to
implement in a little bit but for the
selected we really just want the static
objects so let's pick up all of these
and let's select the counter slide
visual okay nice and white then let's
lock over here the parents so I can
select all of these and drag all of them
okay great and start off with all of
them disabled okay so that's the basic
setup as usual
just for the Counterpoint
since this one has a nice little sub on
top let's lift it up by a little bit so
put it on a y of 1.456
okay that looks pretty good just move it
a little bit to the center okay great
so now let's make our script so let's go
inside our scripts folder we've got our
counters so in here let's create the
brand new c-sharp script for the stove
counter let's wait for it to compile
let's attach the script and open okay so
here as usual let's extend the base
counter
now like I said the going for this one
is to be able to cook our meat and for
that it's going to be based on a timer
and to actually cook the meat we're
going to need to know which one is the
uncooked meat type and which one is the
cook me type
so for that we really want the exact
same logic that we did for the cutting
action we want some kind of place where
we can store an input and output as well
as a cook timer so for that let's
actually just duplicate so let's go
inside our scribble objects for The
Cutting recipe and let's duplicate this
one so Ctrl D and let's name this one
the frying recipe so
okay let's go inside
and over here let's rename the object
then we have an input we have an output
and then a set of progress let's have
the frying timer Max and since this one
is a timer instead of an in let's make
it a float okay so that's it pretty
simple then back here in the editor
let's create our script mode object so
let's go inside let's make a nice folder
so a folder for the frying recipe so
and inside let's create one so let's
create a brand new frying recipe so for
this one let's call it meat Patty
uncooked into meat Patty cooked
then for the inputs let's choose the
meat Patty uncooked now we have to make
the other one so let's go ahead and make
that one let's duplicate this one rename
it to the meat Patty cooked
and the object name meat Patty cooked
let's select the different Sprites so
this one is going to be the meat Patty
cooked okay
and finally for the prefab let's also
make it so for the meat Patty cooked
let's go inside of it and also make sure
to save changes on our stove counter
it's okay now in here let's get rid of
this Visual and use the other visual so
we want to meet Patty cooked and let's
make sure to drag the script monk object
okay so it's all good here and let's go
back outside save it and finally over
here on meat Patty cooked let's just
grab the prefab reference so there you
go that one okay so this one is working
and since we're here and let's actually
make the other one right away
so let's make the meat Patty burned so
the prefab and let's also duplicate this
to make the meat Patty burned then on
the text let's rename this to Burnt
let's choose the burn icon
and for the prefab let's go into our
meat Patty burned and swap it out for
the burned one so there you go nice and
charred and over here swap it for the
meat Patty burned okay let's save it and
finally down here just make sure
everything is correct
object the transform prefab just like
that okay so all of our burn references
over here all of our cooked and over
here all of our uncut and again when
going through this process always make
sure that you match all the references
on the certain objects and also over
here on the kitchen objects so meet
Patty burn yep meet Patty burn for the
uncooked the uncooked and for the coke
there it is okay everything is good
great so now we can go back over here
into our frying recipe so and for the
output let's output the meat Patty
cooked and for the frying timer let's
put it on three seconds
okay so that's it great now back in the
code here on the stove counter let's add
an array of our frying recipes so a
serialized field private it's going to
be an array of frying recipe so frying
recipe so array make omelette frying
recipe so a ring okay great then back
here in the editor let's go inside the
stove counter let's make sure to drag
that so let's drag the mid Patty from
uncooked into cut okay let's also drag
the counter top point and finally since
we already made the script over here on
the selected we can also drag the
selector okay so our stove prefab should
be working okay let's go outside make
sure to save the prefab okay now let's
continue with the rest of the script
so let's make our override so override
the interact action
and when we interact with it let's
validate dropping the object just like
we did on the cutting counter
so let's go over here into our cutting
count script and let's just copy pretty
much the exact same thing so let's copy
all of this interact code let's go over
here in the stove counter and just paste
it now we also need to copy in our
recipe
so over here on the cutting counter
let's copy paste those functions so
these functions go into the cell counter
and over here on let's face them they're
going to work pretty much the same thing
so we get an input except instead of
being a cutting recipe so we're going to
have a frying recipe so so let's replace
all the cutting recipe references with
frying recipe reference
then for the array this one is the
frying rasps array and obviously let's
rename these so Ctrl R to rename all of
them into frying recipe so
let's also rename the function instead
of get cutting rest BSO it's the frying
recipe so okay so there's no more
mentions of cutting over here so let's
use this function up here and up here
and just make sure to rename these the
frying recipe as so
and down here on same thing so the
frying recipe so okay so down here we
have no more mentions of any cutting
let's just go up here and solve all
these problems so first we check if
there's no kitchen object here and if
the player is carrying something then we
see if what the pointer is carrying
matches any kind of frying recipe if so
then the player is carrying something
that can be primed then we set the
parent and for now let's not worry about
the progress
so let's just get rid of all this just
like this okay so with this we should be
able to drop but only in uncooked meat
so back in the afternoon let's just set
up our scene so let's drag a stove
counter onto our scene let's put over
there on X of 6 y of 0 and 3.5 alright
so let's test okay so now if I pick up
some cheese I go up there and I drop it
and nope doesn't work okay great but if
I pick up some uncooked meat and I go
and I drop it and yep that does work
okay great so it works and I can only
drop the actual objects and matchy
recipe now unlike the cutting counter
this one will not be based on a player
alt interaction and actually over here
and let's fix this minor issue
basically we added this debug.log error
to the base interact because pretty much
every single counter is going to
implement this interact function but not
all encounters are going to have the
interact alternate action
so this one lets us do nothing let's not
spawn error okay just a quick fix
so like I said the stove counter this
one is going to be based on a simple
timer and for making some time based
logic basically we have two approaches
one approach is to use a simple foil
timer or you can also use a co-routine
now a lot of tutorials will teach you
how to use a co-routine and that's not
necessarily a bad practice it does work
it does achieve desired result so to do
that you would just make a function like
Freight timer
so you'd make a private you have to
return I in numerator
then call it something like handle fry
timer
then inside you can do a yield return
and return a new weight for seconds
and to start this co-routine you would
do maybe on start you would call start
Co routine
and start the handle for right hammer
so this one approach this is definitely
perfectly foundly timer code
however personally I am not a fan of
co-routines it's not because of
performance or anything it's simply
because I don't like the pattern that
they force you to use I don't like being
forced to make a function that returns I
numerator I don't like using yield
return I don't like having to use the
start core routine function I don't like
being forced to use this on a
monobehavior object those are all
requirements for making a CO routine
work and personally I find those are way
too many requirements that create a very
strange pattern that I really don't like
so that's really the only reason I don't
like Co routines because I find this
pattern to be quite a lot convoluted so
instead of core routines what I like to
use are simple basic flow timers so just
make a simple and private void update
then we just need to keep track of a
certain timer so for example a simple
private float frying timer
then on the update let's first check
that we have an object so it has a
kitchen object if we have a kitchen
object then let's increase the timer by
time dot of time by the way here when
working with a timer you can increase or
decrease it's pretty arbitrary both ways
work the obvious difference is only if
you test if it's above the max or if
it's under zero in here for frying it
does make sense to start at zero and
then the defraying timer Max
so either that and if the frying timer
if it is bigger than the maximum
so let's get the frying rest PSO frying
recipe so
let's get the frying recipe so with
input so let's get this kitchen object
and get the kitchen object itself okay
so we go into the frying rest BSO and we
get the frying timer Max okay so if it's
above the max then this one has been
fried so here I'll let you see what we
did on the cutting counter
so let's get this kitchen object and
tunnel to destroy itself
and then let's go into the kitchen
object class in order to spawn another
kitchen object let's go into the frying
recipe and spawn the output
and we're going to spawn it inside of
this counter
right so that's it this should already
be working we don't have a visual yet so
let's add a debug log
so here just say debug.log on the frying
timer
and up here let's also just reset the
timer so frying time now let's put it on
zero f and let's also do a debug.log and
say fried
however like this you might already be
guessing that we're going to have a
bunch of bugs but still let's just test
it just like this
okay so over here I can move around I
can pick up some uncooked meat I can
drop it there and after a little bit
there you go there's the timers and if
there you go it did work you can see the
timer increase until three then it was
fried then it was reset and then we've
got a known reference exception
basically this is the exact same problem
that we had on the cutting counter where
first we put an object like tomato and
that is indeed an input for a recipe so
we cut tomato into slices but then the
slices are not an input for any recipe
so over here we put some uncooked meat
so that's great we frying which means we
destroy the uncooked meat and we spawn
the cooked meat but then next time the
cooked meat is not an input for anything
so obviously this one is going to return
no one thing we can do to sort of solve
this problem which is also going to be
beneficial in terms of performance is
simply caching this field so let's go
here to find a frying recipe a cell
frying recipe so
instead of constantly getting it on
every single update which might be a bit
costly in terms of performance instead
of this let's just get it over here when
the player drops something so the player
drops something and we assign the Frank
rest BSO so we sign it cache the value
and then do this okay that should have
fixed the non-reference problem but we
still have a bunch more problems but
still let's test it out okay so here
let's pick up some meat put it there and
let's look at the timer and if there you
go everything is cooking great any of
their yo it finished it cooked and the
time was reset and now it's finishing
it's cooking and so on so this is
obviously another pretty serious problem
basically it's constantly frying the
meat and spawning more and more objects
instead of constantly spawning from the
same recipe what we want is for the
stove to First fry the object but then
if the object is fried then we want to
burn it so really that means that we
want the stove to have multiple States
meaning that we're going to need to make
a simple State machine so let's do just
that now if you're a beginner the
concept of a state machine might seem
daunting at first but it's actually
extremely simple at least to make a very
basic one all we need is really just a
bunch of saints so to define those
States let's go up here and make a
simple enum so let's make a private enum
call it state
and now let's put all the states for our
state machine now for the server let's
say we have idle when there's nothing on
top
then let's say we have a frying state
for when the ingredient is actually
being fried then we have fried for when
the ingredient has already been cooked
but it's still getting some heat and
finally if we leave it too long in that
state then everything ends up burned
okay so these are all of our states for
our state machine
and how to make the actual stick machine
it's actually quite simple first of all
we just need to store the current state
so here make a private of type State and
sort the current state
and then on update let's just do a
switch on the current state
okay now here basically we're going to
do different logic depending on the
state that we're at
so let's say if we're I don't we do
something then if we are frying we're
going to do something else then if we
are on the front also something else and
finally if we are on Burn do something
else
so here are all of our states and the
logic that we did down here this is the
frame logic so let's actually just copy
on this
and let's face it inside the frying
logic and for the seed machine we're
only going to run any of these states if
there's a kitchen object inside of it so
it's actually put that switch in there
just like this
okay so that's it so when I don't we're
not doing anything and when frying we're
going to run our frying timer we're
going to fry the object let's also get
rid of the low we no longer need this
then we destroy the current object and
we spawn a brand new object now what we
need is to handle over here the State
field we need to modify this winching in
Saints so first of all let's handle the
start so let's make a private void start
and on start let's begin with the state
on state DOT Idol okay great then down
here when we interact when the player
drops something when the player drops
something that can be fried
over here on let's set the state and put
it on state DOT frame
and over here we should also probably
reset the timer so let's set the frying
timer back into zero f okay we set the
timer and we reset the state finally up
here let's not reset the timer since
we're resetting the timer down there
since it makes more sense down there so
we do the frying the frying timer we end
the frying and then obviously we need to
modify the state so modify State and put
it on state DOT fright
okay so that's the basics of our state
machine with this everything should be
working just the same as previously
except we're only going to fry once so
let's actually just put them out here
debug the hog
object Pride
and let's put one down here outside of
the save machine just do a debug.log on
the state
okay like this let's test
okay so here we are let's pick up some
meat and drop it on there and there you
go it goes from idle directly into
frying and then it's fried and after you
go now it stays on fried so it no longer
goes on frying and it's no longer
spawning any more objects it went from
frying into fried and yep everything
worked alright awesome
so we have the Frank State working
perfectly now let's handle the burning
in terms of logic it's really going to
be the exact same thing
we're going to have a frying timer so
let's copy this code and paste it down
here now technically we could reuse the
exact same float timer but that would be
a bit confusing so let's keep our code
as clear as possible and really just
make a different timer with a more
descriptive name
so pure a private float called The
Burning timer
then let's initialize this timer so when
we go into the fried State let's set the
timer the burning timer into zero then
down here let's use this Burning timer
okay great when timers and lapse and the
object is spawn let's go into the
Burnside
and obviously we need another recipe
so let's make another scriptable object
back in the editor let's find the frying
recipe so let's duplicate this call it
the burning recipe so
then over here let's modify the name
instead of frying timer Max let's call
it burning timer Max okay great so now
over here on the stove let's use pretty
much the exact same thing and let's make
over here private of burning recipe so
the burning recipe so
then down here we just need a function
to get the burning recipe so so let's
copy this and paste it over here this
one's going to return a burning rest BSO
so let's replace this and this
rename this into burning recipe so we're
going to need an array and over here
let's just change the name instead of
frying recipe so the burning recipe so
let's just find a new array so let's go
all the way up here make another array
an array of burning recipe so and this
is the burning recipe SL ring and
finally if we go down here let's use
this array okay that's it so now let's
use this function to set our burning
rest BSL so when we set it to find let's
set the burning recipe so and let's get
it with the input and the input is going
to be the object that is on here so the
kitchen object dot get the kitchen
object.so
okay so we're initializing our fright
State and setting up the burning recipe
so and over here we use that one dot Max
and we get into that one and use the
output so over there object frying over
here object burned all right so that's
pretty much it we modified everything to
say burning timer over here we are
correctly initializing so we go through
the burning timer through the burning
rest PSO which we are grabbing up here
then we spawn the output on the burning
rest BSO and we go into state.burn okay
so all that's left is just filling in
this array so back in the editor over
here on let's make the object so let's
make a brand new folder for the burning
recipe and so and now inside let's
create a new Burning recipe so call this
one the meat Patty cooked into meat
Patty burned and over here let's set the
input so the meat Patty cooked onto the
meat Patty burned and for timer let's
make it take a bit longer to burn so
let's say five seconds okay that's great
let's just drag the reference so let's
go into the stove counter and let's make
sure to open up and go inside the prefab
and over here on the prefab just write
the burning recipe okay that's great
let's go outside save the prefab and
let's test alright so here we are let's
pick up some meat drop it on there and
look over there it's frying and after a
bit yep it's right there you would spawn
that one and now if we wait for five
seconds it should go from frying to burn
any up there you go that one is charred
everything is burned everything is great
all right awesome so everything worked
as intended with this song of our logic
is working now let's handle on picking
up objects from the stove now
technically it's already working so I
can approach yourself and pick it up the
object and there you go drop it in there
so that does work however if we look
over here in the log the state machine
is now in the wrong state so over here
let's do a quick fix let's go down into
the interact action okay so here it is
so if there's no kitchen object then the
player places it okay that's good but if
there is a kitchen object so if there's
something on the stove counter when the
player picks it up let's also manually
set the state
and put the state back into idle just
like this okay that's it so let's test
okay so over here let's pick up some
meat put it in there it's cooking and
let's wait until it gets finished yep
there you go it's done pick it up and
there you go out now if I want I can put
another one and if there you go the
logic is reset and everything is back to
normal okay great so often logic is
working perfectly now let's just get rid
of our logs so we don't need this so
let's get rid of that debugging log this
one and this one okay great everything
is nice and clean and now let's add some
nice fun visuals so if we go inside the
stove counter and over here is the
visual and I include these two prefabs
inside the visual so one of them this
one the stove on visual this one is just
a glowing red square now again there's a
weird bug on this specific empty version
so post processing isn't showing over
here on scene view but if I leave it
enabled and I go back outside
and now from work in the game view if
there you go there's a nice glowing red
square if you don't see glowing make
sure you add the balloon post Crossing
effect
so if you missed something you can go
back into the post-processing lecture
and make sure everything is set up
correctly so there's a nice glowing red
square and there's also a bunch of
particles so you can name on this one
press on restart and there you go just
some nice particles just jumping up this
was made with the unity particle system
so for example on the hierarchy you can
right click go up here into effects and
you can create a particle system
so that's what this is it has a particle
system over here you can see all of the
various settings for these particles
they just jump up and fall down so for
jumping up that is the emission you can
actually see a visual over there of the
cone that is the spawning cone which you
can find over here on the shape so in
the shape it has the shape of a cone
then you can see the radius radius
thickness and so on so that is from
where the objects are being spawned then
up here you can see the lifetime of each
object so each particle is going to last
for 0.7 seconds
you can all see the speed so that's
speed at which they come from there the
start size that's how big they are on
start
and note how the particles are spawning
jumping up and falling down
so that Falling Down is over here the
gravity modifier if you put it at zero
then they just keep going up and if you
put a two yep they go up and they fall
down
next down here on the emission this is
how many are being spawned so if I put
this on 200 there you go tons and tons
of particles next is over here the size
of our lifetime so this one has just a
basic curve so they started off on font
size and over the x-axis this one is in
a lifetime so as the particle goes from
the beginning until the end their life
they basically go down on size so that
is why they become quite a bit smaller
also by the way this one down here this
one is called an animation curve this is
another really useful ENT feature I have
a dedicated video on animation curves
and finally down here just have the
renderer so it's just using some basic
particles so we can inspect the material
simple in the assets and there you go
we're just using the default particle
material just with the alpha on half and
that's pretty much it so as you can see
just a very basic very simple particle
system now all we really want to do is
just for both of these we want to enable
or disable them depending on if the
stove is on or not so let's make a
script to handle the visuals so let's go
down and create a brand new c-sharp
script let's go with the stove counter
visual then let's go into the stove
counter Visual and let's attach the
script
so here it is attach it and open right
so now here we just need references to
those two objects so as usual let's make
a basic serialized film let's make it of
type game object
for the stove on game object and the
other one is the particles game object
okay let's save and back here in the
editor let's drag the references so the
stove on Visual and the sizzling
particles okay great so now all we
really need to know is know when to turn
these on or off and for that is really
going to be based on the state over here
on the stove counter so if it is on the
state frying or fried then we want to
show them if it is on idle or burned we
want to hide them but as usual we don't
want to mix the logic and Visions
directly so let's do that through a
really nice event
let's make a public event let's use a
standard event handler let's call it on
stay changed
and let's also include the state on the
event Arc so let's make a public class
call it on state change event args and
let's expand event arcs and then in here
let's just put a public state
for our state
however here we also have a really nice
error so this one is telling you there's
inconsistent accessibility basically
that's because we made this one public
so any class link for his Mr visual
class can indeed see this class however
from outside that class cannot see the
private state
so that is why we have inconsistent
accessibility we cannot have something
public which inside has something of a
specific type which is private
so in order to make this work we need to
modify this state and make it public so
that the other classes can see it okay
so that's great now let's just fire this
event whenever the state changes so over
here when you go into the frying State
let's go and invoke and as usual just
this
and I actually forgot to add that so
let's go up here let's use the one with
generics so the on state change event
arcs okay great so then down here we
invoke the event let's create of this
time
and inside passing the state equals this
state
okay so this one we need so then down
here go into the burn State let's fire
the event and down here frying fire the
vent and on idle fried event alright
that's it so we have all of our state
logic and over here on the stove counter
visual obviously we need a reference to
the counter so let's add that so a
serialized field private
maker of type stove counter for the
stove counter and then we can do an as
usual for accessing external references
let's do it on start go into the stove
counter and let's listen to the on say
change event
and over here it's going to be very
simple we just want to show if it's on
the state frying or fried and if not we
don't want to show so let's define a
bone called show visual
and this one is going to true if the E
dot State equals the state DOT frying or
E dot State equals
the state DOT fried
so if it's either of these then this is
going to be true if not it's going to be
false so then let's just go into the
stove on game object
and constant active and pass in this
and same thing for the other for the
particles game object okay that's it
super simple let's just drag this
reference so over here inside the prefab
just drag the reference let's leave the
prefab save the changes and let's hit on
play and all right so it starts off
disabled okay so there's no visuals now
if I pick it up and I drop it and there
you go a nice visual so the glowing red
hot and the particles and now it's
running and if I leave it until it burns
when it burns and it's going to turn it
off and if there go turns off
all right awesome so now if I pick it up
wait until it gets cooked so let's go
pick it up and the other you go turns it
off
all right awesome we've got a really
nice visual all that's left is to have a
proper visual progress bar and with this
we actually have another interesting
clean code question
right now the progress bar that we made
over here on the cutting counter that
one is great so we would like to reuse
that however if we look over here on the
progress bar UI we can see this is only
working with the specific type cutting
counter
so by default this will not work with a
stealth counter so as usual we have
multiple approaches to solving this
problem one option would be to Simply
commonly duplicate the script then we
would make a completely different
progress bar UI class that would work
only with the stealth counter so that's
one approach that would work and that
approach might be good if you want the
progress bar to behave very very
differently
but over here I want both of them to
behave exactly the same so instead of
having some code application we can
write some good clean code but doing
exactly what we did with regards to the
kitchen object parent meaning we can use
a nice interface we can then Implement
on anything that has some kind of
progress so let's do exactly that first
of all let's actually go inside the
cutting counter so let's go inside the
prefab then over here we've got the
progress bar and this one is just a
regular game object but since we're
going to reuse this let's make this a
proper prefab so let's find over here
all of our prefabs and just drag the
progress bar UI inside the prefabs
folder okay great so this is now a
proper prefab now let's define our
interface so let's create a brand new
c-sharp script as usual interface start
with I so let's go on I and for this one
we wanted to represent anything that has
progress so let's just call it literally
has progress
personally I like to use the word has to
indicate that a certain object has
certain Behavior so in this case objects
that implement this interface will have
some kind of progress Behavior so now
over here for the interface let's first
make it so this one does not extend
amount of behavior instead of a quest
this one is an interface okay great so
now for the functions that we're going
to need if we look in the progress bar
and we'll look at the cutting counter
references we can see the only one is
literally just this so we just have to
listen to the event and then the rest of
progress bar Works inside of it so real
and interface is the only thing we need
to Define so let's actually go inside
the cutting counter so here we have the
unprogress change event and then we have
this so we can literally just copy this
go into the I has progress and let's put
exactly this
okay that's it that is literally all we
need now if we wanted we can also make a
function to expose the progress amount
but since we included over here on the
event then we really don't need it just
this is enough now let's go over here on
the progress bar UI script instead of
working with the type cutting counter
instead let's work with a type that has
I has progress so let's rename this Q
has progress
and it's going to have the exact same
event the only difference is over here
instead of the event RX being the one
inside the cutting counter is the one
inside the eye has progress so let's
make sure to change this I has progress
okay so the signature matches let's just
obviously rename this
so let's rename instead of cutting
counter let's rename has progress on
progress change and that's pretty much
it we don't have any more errors so
everything over here is now working
nicely with our interface and back here
in the editor once we're still inside
the cutting counter
suddenly interfaces do have one downside
when it comes to Unity
if we look in the progress bar UI down
there we can see the progress bar UI and
previously we had the counter field
exposed in the editor however now by
changing into an interface there we have
the issue the film does not show up here
interfaces do not show up in the editor
because Unity basically has no way of
knowing that the interface won't be
implemented by some kind of game object
so sadly this is the one thing that
doesn't work very well with unity the
solution that I normally do is actually
pretty simple instead of exposing the
interface which does not work and said
let's just make this a regular private
field
and then let's make a serialized film
and for this one let's make it a type
game object and let's call it has
progress game object
okay so like this we have a regular
serialized field with a regular game
object so if you look here yep we do
have that field so now we can indeed
Drag The Cutting counter reference and
then over here in the code in order to
get the has progress that is super
simple has progress we just go into the
hash progress game object and get
component of type I has progress
okay so that's it now our code does work
however of course one big potential
issue with this is that over here we
have a field of type game object meaning
that we have no guarantee that this
field does have a component that
implements the interface so we cannot
make sure that we drag the correct
reference we can drag any reference
doesn't have to have our progress
interface so in order to keep our sound
safe let's add a nice safety warning so
over here if has progress equals no so
if this one is known that means that
that game object does not have any
progress interface if so let's do a
debug download error
and let's say the game object and let's
pass in this game object
does not have a component that
implements I has progress
so this way if we make a mistake we
won't have a nice error message
basically this is the one workaround
that you need to use since Unity does
not support dragging references in the
editor if they are interface references
okay so with that everything is good so
all of our progress bar UI this should
all be working perfectly we just need to
go over here into our cutting count
script and let's make it so that we
Implement our interface so I has
progress and we got an error just
because even though we did Define that
interface remember the on progress
change again keep in mind that the types
depend on not just their name but where
they're at so this type that we have
here is the one that we Define here
which is not the same one that we have
here so even though they have the exact
same name because they are in different
places they are actually different types
so we need to make sure to use the type
in the interface over here let's just go
into the I has progress and use that
exact type and get rid of this one okay
so that's it that's the change we need
and down here when firing let's just
fire with that type and down here the
same thing with that type okay great so
like the this The Cutting counter should
still be working exactly the same as
previously again when refactoring any
code always do a quick test and let's do
that let's make sure to save our counter
save the prefab go back outside head on
play now let's pick up some cheese put
it there cut and there you go the
progress bar still does work okay great
now let's apply it to the stove and that
is actually going to be very simple
first let's go inside the stove so let's
find the stove counter let's open it up
go inside the prefab and over here let's
drag the progress bar UI prefab so let's
drag that then down here we already have
the has progress game object so let's
drag the stove counter and that's it
there's nothing else we need to touch
here we just need to go over here into
the stove counter and as usual let's
implement the interface so the eye has
progress
and now let's implement it pretty much
just like we did on the cutting counter
so we can actually just copy this so we
just need to implement the event so
that's it and now for firing the event
let's go down and see where we are
modifying all of our timers so let's go
down to when the player drops something
so we do the on say change and now let's
invoke this event so this and for the
progress bar for the progress normalize
this one is very simple so just frying
timer divided by the frying recipe so
dot frying timer Max
okay that's it we are modifying the
progress now let's go up here when we
are in the Frank State and when we do
let's fire off the on progress change
event okay great and finally down here
when we have defined over here let's
also fire except obviously we have the
burning timer and the burning timer Max
and then just to make sure that the bar
actually hides itself when we go into
burned let's also find an event this one
doesn't have a timer so let's just put
it on xeraf okay that's really it
we don't need to touch the progress bar
UI at all Let's test this just make sure
to save the prefab let's go back outside
and hit on point and right away yep the
bar is indeed hidden now if I pick up
some meat and I drop it and there you go
got a really nice bar going up any up
going up on the burning site and let's
get to the end let's see if the bar
hides so it gets to the end and you have
to go the bar that's high all right
awesome and if I pick up something
actually this was the one event that we
forgot so let's fix that so let's just
copy the one where we set the progress
normalized to zero and over here if the
player picks up something let's add the
progress back into zero
so here we are let's pick up some meat
drop it on there okay let's wait for it
to be cooked okay it's cooked now before
it burns pick it up and there you go the
bar is gone all right awesome okay so
here we have again another example of
the power of writing good clean code we
made a nice generic progress bar and we
very easily made it work with a
completely different counter which of
course would also work with literally
anything that implements that interface
doesn't have to be a counter now let me
make one note here basically I showed
you how to make a generic progress bar
and reuse it but let's say you want to
do something specific just for the solve
well one approach like I mentioned is to
duplicate the code and make a progress
bar that works only with the solve but
another approach is to Simply add more
elements on top
for example during the Polish stage
we're going to do exactly that
we're going to add an extra UI element
that won't show up to one of the player
when the food is about to burn so I just
want to point out how you can mix and
match both them you can have both
generic components coupled with specific
components
but for now our progress bar everything
is looking pretty good so let's leave
that burn warning just for the police
age now the next very important thing we
need is some points so let's do that in
the next lecture
hello and welcome I'm your kudmaki in
this lecture we're going to create the
plates counter this one is just going to
spawn some points which we can then pick
up to grab some objects okay so let's
begin making the counter as usual so
let's go inside our prefabs inside our
counters right click the base counter
make a new prefab variant
called the plates counter
let's go inside and let's drag the
visual for the plates counter let's go
into scene view so we can see it okay
let's duplicate this make this the
selected let's go inside and we can
actually hide the Eternal Sprite we only
need this one so on this one let's
modify it for the counter selected on
the selected let's make it just one
percent bigger and let's add the
selected counter Vision okay then inside
obviously drag the reference for the
kitchen counter okay that's our basic
setup now let's make our script to run
this so let's create a brand new c-sharp
script for the plates counter let's
attach the scrub to the plates counter
and open okay now here as usual let's
extend our base counter and then first
let's handle the spawn timer logic so
basically we want to spawn some plates
every once amount of time
somewhat sorry simple float for the
spawn plate timer then let's make a
simple update on timer let's increase
the spawn point timer by time dot of
time
and then just check if it's above a
certain maximum
so if it is above something in this case
we're going to have a fixed value
but still like I mentioned in the very
beginning of this course let us not use
magic numbers here you should never use
magic numbers
instead if you wanted to make it edible
you could also make it up here as the
serialized field but in my case for
design that I'm going for I'm perfectly
content with having a fixed value so
just appear pretty simple the spawn
complete timer Max and let's define it
to 4f
and let's use it over here okay great so
this is what we want
however for spawning it's actually going
to be a bit tricky the plate is supposed
to be a kitchen object the player should
be able to carry the plate and right now
for design that we Define is that each
kitchen object can only have one parent
and each parent can only have one object
but over here we want to spawn multiple
objects now let's quickly see what
happens if we try spawning multiple as
usual so let's just go into the kitchen
object spawn a kitchen object which
means we need the plate so so let's do
it up here as usual a serialized film
private kitchen object so for the Plate
Kitchen object SL
so we're going to need to make this and
then we're just going to spawn this
object on this
okay so this is going to throw an error
but so let's see let's first create the
object
over here let's go inside our objects
our kitchen objects let's create a brand
new kitchen object call it just the
plate for the object name this one is a
plate for the Sprite let's go with the
plate Sprite and for the prefab let's
make it so let's duplicate one of these
called the plate
let's go inside it and obviously make
sure to change say the changes then over
here let's drag the plate visual get rid
of the tomato and on the plate let's
make sure to assign the plate and
finally let's exit this let's make sure
to save it and on the plate let's drag
the plate prefab okay so we have the
kitchen object so now let's just go
inside our plates counter and over here
let's drag the reference so the
reference to the play kitchen object
let's also drag the reference to the
counter top point then on the selected
drag the reference to our base counter
and finally start off with a selected
disabled okay so this should be working
let's just add a plate counter over here
onto our scene so let's pick up a police
counter and put it somewhere in here
over there on the side so on an X of 7.5
then 0 and let's say on zero Maybe
let's make sure we have space for one
more counter over there so let's
duplicate this empty counter and let's
put it over there pointing to the side
so this one is on 7.50 and -2
okay so now let's just make sure that
they perfectly match so let's put this
one on a set of minus 0.5 okay so let's
test all right so here we are and look
at that and after four seconds if there
go it spawns the object and then it
immediately tried to spawn another one
and there you go we have the error
kitchen object parent only has a kitchen
object basically the way we designed our
game and set up the code assumes that a
single encounter will only hold a single
kitchen object so we cannot have
multiple plates on the same counter now
when solution for this problem is
actually quite simple when we spawn the
plates instead let's not spawn a kitchen
object instead we're just going to spawn
a dumb visual then when the player
interacts with the counter that is when
we're going to spawn the proper kitchen
object so let's do that although again
let's keep the logic and division
separate so over here let's first just
handle the logic so we just need to keep
track of how many points respond so for
that let's start up here you private end
for the plates spawn amount and let's
also do another private end for the
plates Pawn amount Max
and let's say we can spawn at most four
plates
okay so over here instead of spawning
the object let's first of all actually
reset the timer
so let's put it back to zero zero and on
the plate spawn the mount let's check if
this one is under the plate spawn Max
and if so
let's go into the plate spawn amount and
increase it by one okay so that's logic
super simple now let's send the visual
so let's first make our script so let's
create a brand new c-sharp script for
the plates counter visual
now let's make sure that the visual so
let's go inside the prefab and over here
we've got the visual let's attach it
okay open now here basically the first
thing we need is we need to know where
to spawn the visuals
so let's actually add a reference to our
counter top point
so let's add a serialized film for
private transform for the counter top
point then let's also add a reference
for the prefab we're going to spawn so
let's call it the plate visual prefab
then here in the editor let's drag the
references so the countertop Point Place
it in there and for the plate vision
prefab let's go a pair and find the
visuals for the kitchen object so these
are just the visuals and let's write the
plate visual so the plate visual not the
Plate Kitchen object okay now back in
the code here we obviously need to know
when I play this Bond so let's go into
the plates counter and make a nice event
so fun week event event handler as usual
on plate spawned
and down here let's just find the event
so we just invoke
with this and eventar is not empty
okay that's it very simple and then on
the other script over here let's just
listen to it which also means that we
need a reference to our counter so let's
add up here the plates counter for the
plates counter so we're going to need to
drag the reference and then on start
let's listen to the on plate spawned
event
and when that happens then let's spawn
so let's call instantiate on the plate
visual prefab
let's put it inside the counter top
point so this is the transform for the
plate visual transform and that's pretty
much it okay so unlike this it should be
working
when the plate is spawned we should be
spawning a brand new visual back in the
editor we just need to drag the plates
counter reference like that let's exit
save the prefab and let's test okay so
here we are and if we wait for four
seconds we should be able to see a play
spawn yep there you go and if we wait
for a little bit more we should also be
able to see some more play Swing spawn
except we can't really see them that's
because we're spawning them on the exact
same spot every time but if we pause the
game and over here I'm looking the
hierarchy and find the plate counter and
inside the counter top Point yep we do
have four visions and if we wait for
longer then nope it's not going to spawn
anymore it's only going to spawn four
plates okay great
so some of the visual let yourself set
them by a tiny bit to know how much we
shouldn't offset let's keep track of how
many plates haven't spawned
so let's store up here on the visual
script in list of Game object
call it the plate visual game object
list
let's also make sure that you initialize
this so it lets you on awake let's
initialize this list
and then when we spawn them okay so here
we have the object that we spawned now
basically we just need to modify the low
composition
and let's put it on new Vector 3 on the
X so let's put it on zero then on the Z
we're also going to have zero and then
over here on the one let's offset it by
a certain amount and basically it's
going to be based on how many plates
have been spawned
so let's define up here a float for the
plate offset y let's put it at save 0.1
f
and over here we're going to offset it
by this much multiplied by how many
plates have been spawned so we can go
into our visual list account so you can
delete this and then we just need to add
it to the list so let's add this plate
visual transform.game object okay so now
each game object should respond at a
different height so let's see so here we
are and if we wait for four seconds we
should be able to see a plate and there
you go and now after four seconds we
should be able to see another one placed
slightly above and yep there it is okay
great
so everything is spawning perfectly both
in the logic as well as the visual now
let's actually pick up a plate so on the
plates counter as usual let's implement
the interact
so let's do a public let's override the
interact function
and now for picking up let's first see
if the player is actually empty-handed
so if and we check the player has
kitchen object so if the player does not
have a kitchen object
then the player is empty-handed okay
great then let's see if we have a plate
that we can give them so if the plate
spawned the mount if it is bigger than
zero
then there's at least one plate here and
if so let's give it to the player so how
we do that is one over here for logic
let's just increase it by one then let's
actually spawn the object so on the
kitchen object let's spawn the Plate
Kitchen object so and spawn it on the
player
and finally we just need to update the
visuals so let's make another event
so up here on plane spawn and on plate
removed
okay we have this event and then down
here on let's just whenever the player
picks it up let's invoke this with this
an event RX dot empty
okay great so now the visual let's
listen to this so we're here on start
for the plates counter listen to this
event
and when this event happens we just want
to destroy the very last plate
so let's grab the game object for the
played game object and recently just
going to go into our list so the plate
visual game object list
and let's pick up the very last one
so let's go into the list.count minus
one so this is going to be the very last
element of the list then let's remove
this one from the list so Point dot
remove this one that we just grabbed and
then we simply call destroy on this one
all right so that's it super simple
so we're here on the plates counter we
do all of our checks we cut it down by
one
we spawn the actual kitchen object then
we fire the event and over here the
event listens and updates a visual okay
let's test
so here we are let's wait for a play to
be spawned and when this phone there it
is I'm going to pick it up and if there
go the player is now carrying a plate
let's drop it here and there you go
there's another one now let's wait for a
bunch more to be spawned okay so the
plates counter is full now if I pick up
it should only eliminate the last visual
pick it up any of there you go it'll
eliminate that one now I can drop it in
there any other ones one all right
awesome okay so that's really it for the
basics of the play counter it
periodically spawns some points which
the player can then pick up
now in the next lecture we're going to
add the ability for the player to be
holding a plate and pick up another
object onto the plate
hello and welcome I'm your code monkey
in this lecture we're going to add the
ability for the player to be carrying a
plate and pick up objects onto that
plate okay so here we already have the
plate counter working it has some basic
logic after a bunch of time it spawns a
plate it spawns up to a certain maximum
and I can pick up a plate and if the
player is carrying a plate so I can put
it anywhere
then I can for example pick up some
Tomatoes slice them and pick them up
however now I am not able to place the
tomatoes on the plate so let's add that
logic let's begin over here on the clear
counter script first we're testing if
there is no catch an object here and the
player is carrying something that the
player drops something in there but then
we're testing if there is a kitchen
object here and if the player is
carrying something so it's over here
that we want to check if there's
something that the player is carrying if
it is a plate now our plate is also
going to have a bit of custom logic so
to help both identify and hold that
custom logic let's make a proper script
to handle it
so back in India let's create a brand
new script currently the Plate Kitchen
object
and let's open this now over here on
this one instead of extending Model
Behavior we're going to extend kitchen
object
so the plate is really just a more
specific type of a kitchen object
again like I mentioned quite a while ago
you want to be very careful with
inheritance you need to have a very good
reason to do it here we want the play to
behave exactly like a kitchen object
just with a tiny bit of extra logic so
in this case it makes perfect sense
let's just go ahead and save this and
wait for ENT to compile and over here
let's find our kitchen object with the
plate so here it is the prefab as you
can see we have a kitchen object now
instead of having that one let's replace
that with the play kitchen object and
since we are extending kitchen object we
have the same Fields so let's make sure
to add the kitchen object as so and get
rid of the other one okay great so now
back here on the on your counter when
there is a kitchen object here and the
player is carrying something we can
check if the player is holding a plate
and for that we can check the type
so if let's go into the player and let's
get the kitchen object the player is
holding and we test if this object is of
type Plate Kitchen object
if so then that means player is holding
a plate and if that is the case then we
basically want to give the player
whatever object is over here we want to
add it to the plate so let's go into the
plate script to add that function so
over here let's make a public Point
let's call it add ingredient
as a parameter we're going to receive a
kitchen object as so we really only care
about the type we're going to destroy
the actual kitchen object like we've
been doing when creating different types
so the plate is really just going to
store in list of types so here let's
store a list of kitchen object a cell
for the kitchen object that sell list
then when we add the ingredient let's
just add it to the list so this kitchen
object is so let's also make sure to
initialize the list so let's see what
I'm awake let's initialize our list and
now from the other side we just need to
call this so over here on the clear
counter if the player is holding a plate
let's first get the type of plate so
play kitchen object or the Plate Kitchen
object we go into the player to get the
kitchen object and we cast this as a
plate kitchen object
okay so we have this and then over here
let's call add ingredient
and let's add whatever is currently on
this counter so let's get the kitchen
object and get the kitchen object itself
okay so we're adding it to the plate and
then let's destroy what is here so get
kitchen object and destroy itself
okay so that's it so if there is
something here and if the player is
holding something and that's something
the player is holding as a plate if so
we're going to add that ingredient to
the plate and then destroy the object in
here so let's test okay so here let's
pick up a tomato let's slice it let's
put it on a clear kitchen counter
because that's the only one where we
added logic so on this one let's pick up
a plate and now whilst I'm carrying the
plate and if I approach and I interact
with it and if there you go it does work
the object vanished from the counter and
supposedly was added to the plate again
we can use a really nice debug inspector
to see it so let's pause the game Let's
select the plate let's see the play
kitchen object so here it is this one
and let's change the inspector into
debug mode and down here yep we do see
the kitchen object that's on list and it
does have some tomato slices okay
awesome so with this here we have our
basics
we can have some ingredients and we can
basically pick it up from a plate now
one thing about our plate this is where
we're basically going to carry the final
recipe that we're going to deliver to
the customers and based on the design
that I defined I want something pretty
simple meaning for the design that I'm
going for there won't be any kind of
double burgers or double cheese so each
final recipe will only have at most one
of each ingredient
so let's add some basic logic just to
prevent adding duplicates over here on
the Plate Kitchen object when we add an
ingredient
since the function will now not
necessarily succeed every time let's
actually rename this and again use a
very useful Visual Studio shortcut so
you can press Ctrl RR or right click and
let's rename
since this function will no longer
succeed we're just going to try to add
an ingredient so try add ingredient and
then let's also make it return a buoying
basically for any function where you're
not sure if it won't succeed I like to
add try and make it return ball so this
way it works pretty much exactly like
the try again component that we've
already seen so many times so it tries
to do something and returns whether it
succeeds or not so over here instead of
always adding the ingredient let's see
if this one is a duplicate so let's do
an if and let's go into the list and
check if the contains and if the list
summary contains this kitchen object as
well
if though then already has this type so
let's return false and if not
then that means it's a brand new
ingredient
so let's add it and return true okay so
that's it now let's go over here onto
the clear counter so we try to add the
ingredient but then we only want to
destroy if this one succeeds so let's
put this one inside an if so if we do
manage to add the ingredients
then yes let's destroy itself if not
then we don't destroy anything okay so
let's test
so let's go ahead and slice two tomatoes
so one slice it put it here then another
one slice it and put it here now let's
pick up a plate go up here try to pick
up this one and yep it does work now for
this one and I hope it doesn't work okay
great now one more thing in our logic we
only want to pick up certain things like
I said only things that won't be used in
the final recipe
for example no customer is ever going to
request a full entire tomato the recipes
only have sliced tomatoes so we should
not be able to drop a foam tomato
directly on top of a plate so let's
change that so over here on the plate
script let's basically just create a
list of our valid ingredients
so let's make a serialized film private
make it a list of kitchen object SL
ope and call it the valid kitchen object
SL list okay so we have this list and
over here in the editor let's just write
the ones that we want so let's first of
all select the plate object okay here is
the flight prefab and over here we've
got all of our kitchen objects so let's
just write the ones that we want to add
to the point
so the final recipes will have some
bread yep but they will not have entire
cabbages they will only have cabbage
slices same thing no cheese only slices
for the meat we're only going to be able
to add meat cooked but also meat burned
then we're not going to be able to add a
plate onto a plate of course not and
finally inside of a tomato just tomato
slices okay that's our Vellum list and
over here again it's very simple
so we can just go if the evaluate
kitchen object that's on list if this
one contains the one that we want to add
then we can add it but if not then let's
return phones
not a valid ingredient
okay so let's test alright so let's pick
up a tomato and also some tomato slices
and now if I pick up a plate and I go
into the Tomato nope doesn't work but
the slices yep it does work okay great
so here we have all of our basic plate
rooms everything is working perfectly
but it's only working over here with the
clear counter so let's do a little bit
of code cleanup and then let's add this
logic to all the other counters so first
to clean up this cone over here we are
testing if this is a plain kitchen
object then we cast to an object and
then we count the function so let's
simplify all this
and let's do it just like yinty does
with their try and get the component
function so let's make a custom function
that takes an output parameter the best
place to put it is on the kitchen object
so here we've got the kitchen object
script okay great let's scroll down and
make a nice function here so let's make
it public we're going to return Boolean
in case this succeeds or not let's
currently try get plate and over here
let's make an out parameter so don't
forget the out keyword let's return of
type Plate Kitchen object for the play
kitchen object then over here we do
examine what we did so we test if this
object is a plate kitchen object
if so then let's set the play kitchen
object equals this as a play kitchen
object and we return true but if not
then this is not a plate so let's return
false and one thing when working with
output parameters you always need to
make sure to set the output before you
exit the function
so over here that's the error that it's
telling us
we must assign it to something when we
return so over here we don't have a play
kitchen object so to solve this we just
set this to no okay great now over here
on the clear counter instead of doing
all this basically let's ask the player
if this is a kitchen object
so let's try to get the plate
out Plate Kitchen object for the Plate
Kitchen object
so you try to get it then we try to add
the ingredient and so on now obviously
we could further simplify things by
making a function that would try to get
the plate and try to add the ingredient
that could work but since some counters
are going to have a bit more custom
logic I think keeping them separate like
this makes more sense so first we try to
get the plate then we try to add the
ingredients so let's apply the same
logic to The Cutting counter
so over here on the cutting counter
let's scroll down to where there is a
kitchen object here and the point is
carrying something so on the earlier
counter we just want to copy all of this
so let's go over here and we do the
exact same thing okay that's it and the
other counter from where we can pick up
things is from the stove counter
so here we are on the stove let's scroll
down until we find the interaction okay
there's something here The Player's
carrying something so it's over here
let's do that and do the exact same
thing except on the stove again let's
remember that this is using a save
machine so when we pick up something
let's do pretty much the same thing that
we did here so let's make sure to reset
the State Fire the events and so on okay
so those are the only counters that we
need to implement we cannot drop things
on top of a container we cannot drop
things on top of the plate counter or
the trash so these are the only three
types that we need to implement so with
this let's test okay so let's begin with
some meat so let's pick up some meat put
it on the stove let's pick up a plate
wait for it to cook pick it up any up
there you go it does work now it says
the cut encounters and let's pick up
some cheese and let's slice it pick up
some plate and go any up there you go it
does work and again if we inspect we can
make sure that it is indeed working so
let's get into the plate and let's put
this on debug inspector and if there we
do see this one has a meat Patty cooked
and some cheese slices okay great now
the last piece of logic that we need is
pretty much the opposite so right now it
works if there's a sliced object on the
plate and the player is holding a plate
object but now we want the opposite so
let's say there's a plate in here and we
slice some cheese and now I want to drop
the cheese on the plate so let's do that
and basically for this one this one is
only going to happen on the clear
counter that's the only counter type
that can have a plate on top of it so
over here on the clear counter then we
check if there is no object there but
that's not what we want we want if
there's a plate on the counter so if
there is an object there and if the
player is carrying something
then we check if the player is holding a
plate but if not so if the player is not
holding a plate
so player is not carrying plate but
something else over here we need pretty
much exact same logic except just
testing for the object on this counter
so let's do if let's get the kitchen
object on this counter this one try to
get the plate so out play kitchen
objects for the Plate Kitchen object so
if so if so there's a plate over here
that means the counter is holding a
plate
so then let's go into this play kitchen
object let's add the ingredient
and we're going to try to add whatever
the player is currently carrying so the
player dot get kitchen object
and get the kitchen object as so
so we're going to try to add this
and if we can add then we're just going
to destroy whatever is on the player
okay that's it and over here we've got a
nice error just because we've defined it
with the same name appear so up here
we're already defining the variable and
over here we're defining the same
variable with the same name
so we can either give this a different
name or just not Define a brand new
variable here so just it's a fine up
here and we're using it here okay so
while logic is working now here make
very sure that you're not mixing
references keep in mind when you're
referencing the kitchen object on this
counter and the one on the player those
are two different things so over here if
the player is not carrying a plate but
something else then you check the
kitchen counter so over here you're not
checking the player but checking the
counter then you go into that point and
try to add the ingredient and you try to
add the one that the player is carrying
and then you destroy the one the player
is carrying so again be very careful
here make sure you don't mix references
so with this it should work so let's
make sure to save our script and let's
test okay so here we are let's first
pick up a nice plate let's drop the
plate in there pick up some bread drop
the bread any of there you go it does
work alright so now we can do a bit more
natural interactions so for example
let's pick up some meat and put it on
cooking and there you go the meat is
fried so now I'm currently carrying just
some meat so I place it there then I
pick up some bread and put some bread on
top of the meat and yep everything does
work policy okay so here we created the
plate and we created some custom logic
to Define what the plate can and cannot
account no that's left is actually being
able to see what is on the plane so
let's do that in the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to add a
nice visual to our plate okay so right
now we can already pick up ingredients
under the plate so if I pick up the
plate and I pick up some cheese there
you go there's some cheese on the plate
but we cannot see it so let's solve that
and we were going to do that it's
actually in a very simple way
if you look in the included assets
inside the prefab visuals there's this
nice plate complete visual that I built
basically it's a foam burger that
contains all the ingredients what we're
going to do is actually very simple
we're just going to enable or disable
these game objects that's it so let's do
example that let's make a new c-sharp
script quality plate complete visual
let's attach a script over here and
let's also make sure to put this one
inside the plate so let's save this
prefab let's go inside the play prefab
so inside the prefabs here the kitchen
objects we've got the plate so inside of
the point let's drag that let's drag the
plate complete visual okay great so now
let's open up this script over here on
let's first have the reference to our
Plate Kitchen object
film private for the Plate Kitchen
object for the Plate Kitchen object
back in the editor let's drag the
reference okay great so now here
basically we need to update this visual
whenever the plate gets any ingredient
added to it
so let's go over here into the point
script and basically just need to fire
off an event when that happens
so let's make a public event event
handler and let's call it on ingredient
added
okay and for this one let's also make an
event RX to contain the data of what
object we added so let's make a public
class on ingredient added event args
let's extend event args and inside let's
make just a kitchen object a cell
kitchen object as well
okay great and let's make the event of
this time
all right so now let's just fire off
this event so down here when we try to
add an ingredient if we do add the
ingredient let's fire off this event so
let's invoke with this and let's create
a brand new one passing the kitchen
object as so as this kitchen I'll take
this off okay so we have our event
correctly being sent now we're here on
the play complete visual let's listen to
it again as always let's make sure to do
it only on start so the play kitchen
object on ingredient added let's listen
to this event and over here we just need
to either enable or disable the visuals
that relate to the kitchen object inside
over here the event arcs however of
course the question is how exactly do we
find them the point complete visual has
all these game objects how do we know
which one belongs to that kitchen object
now technically one way would be to do a
simple transform find and find the
channel objects by name technically that
would work but like I mentioned in the
beginning of the course strings are a
horrible way to identify things they are
very air prone so let's not do that
instead let's use a proper approach
where we can Define some kind of link
between a kitchen object a so and a game
object and we can do this very easily by
justifying a struct so here in our
script let's do exactly that let's
define a public
make it a struct
and name it kitchen object so underscore
game object
then inside it's very simple we just
have a kitchen object so field
and then also a game object field
that's it super simple by the way if you
don't know what is a struct basically
it's very similar to a class except it's
stored in different places in memory and
behaves somewhat differently
I have a very very important video on
that subject what is the difference
between value types and reference types
classes are reference types so when you
pass in a class into a parameter you are
passing in a reference to that object
whereas struts are value types so when
you pass in a struct onto a parameter
you are passing in a copy it's a bit of
a tricky thing so definitely make sure
you go watch that video for more details
so you don't get confused in the future
here I Define that as a struct simply as
kind of a teaching moment but also
because it just makes sense that if I
just want to store some data without any
logic then it should probably be a
struct and not a class although in this
case the class would work just as well
anyway so here we have a struct inside
the struct we have a field of type
kitchen object so another one of type
game object so now let's just make a
list of this type that we can expose in
the editor so here a serialized film
private let's make it a list of kitchen
objects so game object and call it
kitchen object so game object list
okay that's it super simple so let's
save and make sure this compounds so
actually let's just comment this out
just make sure our code compounds okay
and over here in the editor we see the
tricky thing when it comes to using
fields of custom types if we look in the
inspector no we don't see anything so we
cannot see our custom type in the
inspector if you make a custom time like
this front and you want to show it in
the inspector then you need to add the
attribute serializable which exists
inside system so let's go up here using
system
and let's say the attribute serializable
just like this okay so do this save and
let's look and if there you go now we do
see our custom struct so we've got a
list then we can click on the pause icon
and there you go we've got an element
and it does have a film for a kitchen
object so and one for a game object so
that's great with this now we have a
really nice place where we can link one
object to another so let's just do
exactly that so for example let's put
the bread over there and let's assign
the kitchen object as so for the one
with bread let's do the same thing for
all of the others so let's add a whole
bunch more Okay so we've got the bread
then we're going to have the meat Patty
cooked then the tomato slices then we
have the cheese slices the Cabbage
sliced and finally the meat Patty burned
so I've got number zero through five so
you have six elements and over here yep
we do got six so we have all of them we
can get rid of these last two okay great
and now let's assign the proper objects
so this one for the meat Patty cooked
then we've got the tomato slices then we
have the cheese slices then the Cabbage
slices and finally the meat Patty burned
okay great so all of the references
match now back in the code here so we
have this List fully filmed out and when
we have this really very simple we just
cycle through the list to find the right
game object it's similar to a 40 inch of
type kitchen object so game object
in our kitchen object so game object
list and we check if this kitchen object
is so dot kitchen object matches the one
that we received in the event
if they do match then go into this one
grab the game object and set active into
true
okay so that's it some very simple logic
and also we can start with them disable
them by default in the editor or just
over here just use something very simple
just do a for each second through every
single one of them and set every single
one of them to false so that they are
hidden okay so with this on the
ingredients on the plate should be
visible so here in the editor let's just
make sure all the references have been
set let's go back save the prefab and
let's set on play okay so here we are
and by default like that an empty plate
and yep it is empty and now let's slice
some cheese now let's Place some cheese
on there and there you go we've got some
cheese now let's pick up some bread drop
some bread and there you go got some
cheese and some bread
then let's cook some meat so let's cook
it and let's pick it up with a plate and
as soon as I go boom there you go I've
got a nice cheese butter
all right awesome so wait a second I'll
do a complete Burger so let's finish it
let's just add some more tomatoes so
slice them and add the tomatoes and
finally some sliced cabbages slice them
put them there and there you go here we
have a fully complete Burger okay so
that's great all of our vision logic is
indeed working however this visual is a
bit hard to see it's not very clear to
the player so just looking at it from
this distance does that have a tomato or
not
there's a tiny sliver of red in there
but you can't really see it
so we should probably add some nice
clear icons on top to clearly indicate
what exactly is on this plate so that's
exactly what we're going to do in the
next lecture
hello and welcome I'm your code monkey
in this lecture we're going to add some
really nice icons on top of our plate so
we can easily see what is on there okay
so for the icons let's do the exact same
thing that we did for the progress bar
meaning let's use a warm space canvas so
let's go inside our play kitchen after
prefab and over here on let's right
click let's create a brand new canvas
let's name this the plate icons UI then
for the settings let's make it World
space put it on zero zero everything
width and height also on zero then let's
lift it up a little bit so put it on a y
of one okay like that now inside let's
define an icon
so let's start by making an empty game
object call this just the icon template
let's put it with a size of 0.3.3 it's
okay something like that then inside
let's add a new UI image name this the
background
and make it stretch to film The
appearance so put 0 on everything okay
there's our background
for the background image instead of a
square and let's actually go with a
circle for that Unity actually has a
bunch of built-in Sprites that are
tatted in the last versions however it's
not actually over here by default
in order to see those default Sprites we
need to install the 2D Sprite package so
let's quickly just go into window
package manager let's make sure we are
in the UNT registry make sure we aren't
looking at all and over here let's find
the 2D Sprite package okay so let's
install this
okay there's the package so now if we go
into the background and we search for a
Sprite and over here make sure you click
to actually show the assets from the
packages and now we see a bunch of
default hexagons a bunch of isometric
tiles the square so on and if we search
for Circle yep here we've got a bunch of
circle so let's use this one over here
on this path so let's use it there you
go we have a nice circle now let's
duplicate this image and for the second
one let's name it icon
then for this one let's assign just a
random Sprite so let's say the bread
and again remember how the Sorting order
on the UI this one is based on the
ordering the hierarchy
so make sure that the icon is underneath
the background the hierarchy that way it
shows up on top okay so we have our icon
template that's great of course we're
going to dynamically generate all of
this through code we're going to have
multiple icons and for positioning them
Unity actually has some really useful
components let's select the plate icons
UI and over here now let's add a
component now for example a built-in
component is the grid layout group this
basically helps you position all the
charm objects so let's put the size of
the canvas over here on 0.9.9 okay so
there you go a nice Square window then
over here on the settings for this for
the cell size let's put it at 0.3.3 and
if there you go already shows up over
there on the corner
and we can see what it will look like if
we just duplicate this object so let's
make a bunch more templates and if there
you go that's what it looks like so as
you can see this component is super
useful for automatically positioning all
of the challenge objects now if we want
we can play around all of these we can
add a little bit of spacing on the XR on
the Y but let's actually leave both
those with zero let's leave everything
on defaults just over here on the
channel alignment let's put it on middle
Center okay so there you go that looks
pretty nice so you can see how this
built-in component is super useful
there's actually two more so this one
for the grid layout this is great when
you want to put things horizontally and
vertically
but if you just want horizontally then
there is the horizontal layout group and
if you just want vertically there's the
vertical layout group so all of these
components are really awesome really
useful okay so with this our objects are
placed and note how I named this an icon
template basically a template is just
what I call something that is kind of
like a prefab but not really a prefab
through code we're going to duplicate
this template and dynamically modify the
icon so we're going to use it very much
like a prefab
we could actually make this into a
proper prefab so I could just drag it
over here onto the project files and
make a regular prefab that could work
and the only reason why I prefer this
method of not using a prefab
he's just because this object this
template stays here on the object as
opposed to cluttering over here your
project files if you have tons of
single-use UI elements with tons of
objects you need to spawn you can end up
with tons and tons of prefabs and you
might not even know where each of those
is used whereas with this method the
template says exactly where it's used
and does not take an asset slot over
here on the project files so personally
this is just approach that I prefer for
spawning UI elements but like I said
prefabs work as well so if you prefer
using prefabs go ahead and make it okay
so let's make our script to run the
plate icons UI so let's go into our
scripts and on the scripts folder let's
create a brand new c-sharp script for
the plate icons UI over here let's
attach a script and open it okay so now
the first thing we need is a reference
to our plate
so let's begin by making a serialized
film private for the played kitchen
object for our play kitchen object
okay let's save it and drag the
reference so over here there's the point
icons let's just drag the plate
reference okay great now on the plate we
already made this event when an
ingredient is added so basically we just
need to listen to this in order to add
the new icon so over here on the UI
let's do as usual private void start and
on start let's go into the Plate Kitchen
object and listen to that event
and when that happens let's spawn an
icon although here let's actually use a
different method from the one we used on
the plaint visual over here on the plate
visual whenever we had the event we
really just modified the object that was
added so over here the equivalent would
be to spawn a new icon whenever that one
was added but instead of doing that
right now let's listen to this event and
when this happens let's update all the
icons in this display basically this
other method is useful when the contents
can be added as well as removed now in
this case they are never going to be
removed so in this case both methods
were fine but still I want to show you
the second method just so you can use it
when you need it so for that method we
just need to know exactly what is on the
plate so over here on the Plate Kitchen
object we just need to expose the
kitchen object as some list so let's do
example that so fun week we're going to
return a list of kitchen object SL
let's go and look get the kitchen object
the sewn list and we just return the
kitchen object that's always okay very
soon then over here on the planet icons
UI let's just make a function to update
the visuals so private Droid let's call
it update visual
and when we have the event let's call
our update visual okay
so now here let's basically just cycle
through all the ingredients so let's do
a 40 inch kitchen object so in the plate
and get the kitchen object the sewn list
okay so we're cycling through all the
ingredients on the plate and then we
want to duplicate our template so that
means we need a reference up here so
let's add a serialized film private type
transform complete the icon template
okay and let's save the code
and over here in the editor let's drag
the reference so let's drag the icon
template by the way I'll have the others
over here that's not a problem since
these are going to be destroyed those
we're going to see in a little bit the
only one that matters is the first one
okay so here we have the icon template
so to spawn it we do it just like we do
with any preform so we just call
instantiate pass in the icon template
and then transform parents so let's put
it as a child of this object this part
is important we need to make sure the
object is spawned as a child of this
object if over here you put something
like no then the template won't be
spawned as a mobile object so it won't
be somewhere in the world so in order to
make it positioned properly let's make
sure to use transform to become a child
of this object okay and then since we're
using the other script the green layout
group this is already going to be
automatically positioned so just like
this it should be spawning the icon and
with the icon spawned all that's left is
really just setting the image and now
again the quick and dirty approach would
be over here when we spawn let's say we
pick up the item transform
and over here we could go inside and do
a find in order to find the image in
order to get the component of Type image
and so on so that is one approach that
would be the quick and dairy approach
but again we want to do things properly
so let's do it the proper way instead so
instead of this
let's make a proper script that we're
going to run on the icon template so
let's create a new script so a new
c-sharp script come with the plate icon
single UI so this one represents just a
single icon let's go ahead and attach it
to the template so over here let's drag
it and now when using this template
method really the only one we need to
worry about is this one the other
duplicates we can just leave them they
don't really matter but don't just
avoiding confusion I'm actually going to
delete them it's okay we just have one
icon template okay and it has our script
okay let's open now over here let's
basically just make a function to set a
kitchen object or so so public void
let's go on set kitchen object so
we receive parameter of type kitchen
object that so okay great so then we
need to set the image so let's just go
into a serialized film private of Type
image which is inside the unity
engine.ui
so for this one for the image we have a
reference and then we set the
image.sprite go into the kitchen object
and grab the Sprites
okay so we need to do is drag this
reference so over here in our template
let's drag the icon image okay great so
now back here on the plate icon Ty so we
spawn it that's great then let's we get
component in order to get our script
so the plate icon signal UI okay and
then we just call set kitchen object so
and pass in this okay that's great this
is much better now again you might be
thinking that this method is a lot more
verbose than just setting the image
Sprite here we had to create another
completely new script we had to write
this logic and over here get it and use
it the quick and dirty approach would
indeed be quicker but remember that
while the equationary approach might be
faster at first it will mess you up over
time so just take a few extra seconds to
do things properly this approach is much
more scalable let's say for example on
this function you want to change not
just Sprite but also trigger some kind
of Spawn effect or animation with this
it's very simple we've got this function
right here we receive the kitchen object
of so and we can do whatever we want
with it so like this we have this grip
that is responsible for anything related
to the single template and if you've got
the general one which just spawns him
and just gives them the kitchen object
so so all of our logic is nicely
separate okay so just like this it
should already work however like this
you might already be thinking want to
spawn way too many icons and yep it will
basically every time we add an
ingredient we're updating the visual
where we're cycling through every single
one and spawning all of them so with
this we're constantly going to spawn
more and more items this is not what we
want over here on the update visual we
do want to update and spawn all of the
icons but before we do that we actually
need to clean it up we need to clean up
the icons from the previous event
so before we do that let's just cycle
through all the children on this
transform so that's pretty simple you
can just do a for each transformed child
in the transform
so this way Cycles through all the
children and then just call destroy on
this channel that game object so that
won't work that won't destroy all of the
previous children however of course we
also have one issue the icon template
itself is also a child
so if we do this we're going to destroy
the icon template which then over here
we're going to have an error because
we're going to instantiate no so we want
to destroy all the children except for
the template so over here that's pretty
simple we just check if the child equals
the icon template if so then let's just
skip it so we can just call continue and
there you go it skips
okay great so just one more final thing
if we leave the template like this
meaning the game object is enabled like
this the template will always be visible
plus whatever ingredients we have we
don't really want the template to be
visible this is just meant to be a
template that we can instantiate so
that's pretty simple to fix let's make a
private void awake and on a week let's
grab the icon template grab the game
object set active into false okay so now
the icon template won't be disabled so
it won't be visible and then over here
when we are instantiating the
instantiated ones will also be disabled
so let's make sure we go in there and
enable these all right that should do it
so all of our logic should be working
there's only one more tiny thing we need
to take care of this one is a world
canvas so like we saw with the progress
bar we need extra logic to make it look
towards the camera and thankfully we
already wrote an excellent generic
script to do just that so let's go into
the point icons UI and let's add a
component and let's add our very nice
look at camera something like this and
let's set the mode the same that we use
so let's put it camera.org okay so
everything is great everything should be
perfect so let's finally test let's
leave the scene save the prefab and hit
on play all right so let's go pick up a
plate and there you go there are no
icons visible okay that's great now I'm
going to place a bread on top of the
plate and there you go I've got a nice
bright icon okay great now let's make
some meat cook it and as soon as it's
done going to pick it up and there you
go I've got a bread and some meat now
let's put some cheese slice it put it
there and there you go now I can easily
see that plate has some bread some meat
and some cheese now let's just add the
rest of the ingredients to make a foam
Mega Burger so let's add some tomatoes
and add some nice cabbage slices any of
there you go it works perfectly so here
we have a complete burger with
everything and we can easily see on the
icons everything this contains alright
awesome
okay so here you'll learn how to make
yet another Super useful element that
you can easily add to all of your games
personally I use this kind of logica ton
in all kinds of UI things for example in
my upcoming steam game total warm
Liberation the items in the inventory
they're all added using this method so
there's a template and I duplicate that
template same thing for all of the
action buttons all of those are based on
having a template and duplicating it
it's a really easy way to do this kind
of thing with all that here we have a
phone plate and we can easily see what
is on there so with this the next
obvious step is to actually deliver some
orders so let's do that in the next
lecture
hello and welcome I'm your code monkey
in this lecture we're going to build the
delivery counter this is where we're
going to drop some items that the
customers have requested in order to
complete the orders also just for fun
we're going to learn how to use Shader
graph to make a simple custom Shader
okay so let's begin by making our
counter so let's go into our base
counter let's create a new prefab
variant for the delivery counter let's
go inside and now let's find the visual
the visual for delivery counter let's
duplicate it to make the selecting let's
go inside modify the material then on
the selected make it one percent bigger
one zero one add the component the
selected counter visual let's drag the
kitchen counter like that okay that's
our basic setup and also start with the
kitchen count disable okay great now
let's make a script to run this so let's
go into our counters folder and let's
create a brand new c-sharp script for
the delivery counter let's attach it and
open okay so now here as usual let's
begin by extending our base counter
class all right now let's override the
interact function
and for now let's actually do it it's
not like the trash counter meaning let's
just destroy the object so we just check
if the player is holding something so if
the player has a catch an object let's
go into the player the kitchen object
then let's destroy it
however another room over here for an
Oliver counter is this is only going to
accept plates so let's see if the player
is carrying a plate object so player get
kitchen object and test try to get the
plate so out played kitchen object for
the Plate Kitchen object
we try to get this and if it is a point
then we destroy it
okay that's it here in the editor let's
just compound the script and drag the
references so the countertop point and
on the selected let's drag the counter
reference and let's exit this save the
prefab and let's drop it over here on
the corner so let's find over here the
delivery counter and let's put it over
there hang on it on this side put it
like this let's also just quickly
reposition all of our counters since we
already have all the types that we're
going to use so on the lever counter
let's put it over here on this corner so
x 7.5 0 and Z of two then next to it
let's put the plates counter so over
there okay
then next week let's put a clear counter
after that let's put the trash counter
and then let's also put another empty
one there so let's duplicate this one
move it up to about this and put it like
that now we just need to move all of
these down here so just select all of
these counters and let's move them down
by about this okay so on minus 5.5 like
this okay so everything is nicely
positioned just over there right now we
cannot access that container so let's
actually modify those as well which by
the way over here there's the canvas in
front so as I click I'm actually
selecting the canvas in the hierarchy so
here's a quick empty tab on the
hierarchy on the left side you've got
these two buttons so one of them hides
the object and the other one simply
makes it unselectable so if I click on
this and I click through any of the
click goes through the canvas so that
makes it much easier to select over here
on the items in our scene so let you
select all of these okay all of these
now just push them all to the side and
make another empty one and put it over
here okay that's a nice layout now let's
just finish the rest so over here let's
just duplicate our empty counters and
place a bunch more let's put one more to
the side
and now these ones over here so let's
put it over there and rotate it here
and duplicate another one and another
one
and another one and just one more and
get rid of this one okay great so here
we have pretty much our complete map
let's also just move the camera tiny
tiny bit just make sure that it is
nicely organized so put it over there
just so everything is nice and centered
okay so there's our map now let's get
back to working on our delivery counter
we already added this code so let's just
quickly test so here we are and if I
pick up something like for example some
cheese go into the delivery counter and
interact and nope nothing happens
because that one only accepts plates now
if I pick up a plate go there don't wait
for any of there you go it does work
okay great so this is the basic logic
that we want
for defining the actual recipe and logic
we're actually only going to do that in
the next lecture but for now let's add
one more nice thing let's add a simple
custom visual over here using Shader
graph this is a great way for you to
learn the pottery of Shader graph and
just how easy it is to use this is a
visual tool for making shaders it's
really very easy personally I don't know
how to write shaders with code but I can
build some pretty nice things using
Shadow graph as usual I have a dedicated
video on it I also have an entire
playlist showcasing how to make all
kinds of interesting effects and even
one special video covering some changes
in recent shareware versions so over
here let's learn the basics how to use
it so first here in our project window
let's create a brand new folder let's
name it just shaders and now inside
let's create one so let's create then go
up here into sheet graph then we're
using urp so let's go inside there and
here we've got a bunch of options now
don't worry about picking the quote
unquote wrong option all this does is
just create a template so for example if
you accidentally create an unlit Shader
you can then easily swap it out from it
so right right now let's go with the
English hitter and for the name let's
name it moving visual
okay there's our shade Rafael now now
let's just double click to open it and
up here we have the nice shade graph
window by the way you can make this
phone screen so you can either right
click over there on the tab and maximize
or alternatively you can just click on
this window and then use the hotkey
shift space and if there you go it does
maximize okay great now by default we
have this down the center this is called
the master stack these are the actual
properties that we're going to need to
use then on the left side we have the
properties Blackboard on the right side
we've got the graph inspector and
finally down here we've got the main
preview all of these windows can be
scaled and also if you don't see these
windows or if you accidentally hide them
they're all appear on these three
buttons so the Blackboard that's on the
left the graph inspector and the main
preview okay so now here we've got a
nice empty board so we can add whatever
nodes we want so we can right click and
go into create node and then we can
write something or just click anywhere
and press on space and there you go now
we can cycle through and browse all of
these menus to see all of the nodes that
exist there's tons and tons of them or
alternatively just go up here and use
the search bar so for example let's find
the sample texture 2D node so here it is
this one okay we've got this node what
this one does is it takes a texture and
grabs the color from it so on the left
side of the node are the inputs and on
the right side are the outputs within
the parentheses you can actually see the
types so for the input texture this one
is of type T2 so that means it's a
textured 2D then on the output you can
see there's a 4 meaning it contains four
floats which in this case refers to the
four colors so that's red green blue and
Alpha so for an input we want a texture
so let's set it over here as a property
let's click on the plus icon and we've
got a whole bunch of types for texture
we want a textured 2D so let's go with
that and then for the name now usually
there are two standard names there's one
called main text or base map main tags
used to be the more common name but when
working with urp for some reason they
decided to name the main texture as base
map so we're here let's stick within the
urp standard and just call this basement
okay there's our property and if we
click the select it and on the right
side we can see the graph inspector and
we can see all the properties for this
Actron property so we see a name
reference and a bunch more things now
the really important one is over here
the reference this is the actual name
that you're going to use if you want to
interact with this Shader through code
the name on the property this one is
just a text ring so this can be whatever
you want you can even have spaces and so
on whereas the reference name this is
the really important one and by default
when you set up a name it should already
accept the correct reference usually the
standard is to name it just like the
name both without any spaces and with an
underscore in the beginning so just like
this okay then we can give it a default
texture so let's go ahead and select
something for example over here the
bread texture remember this is just the
default this will not be hard-coded
directly into the Shader we can then
modify this okay so we we have our nice
base map property definition now we can
just drag it over here on the board and
yep there it is and now we can just
click on the server icon in order to
drag a connection and let's connect it
over here onto the sample textures to
the input and yep right away we do see
it does work so we are correctly
sampling the texture however if you look
on the main preview over here there's
still nothing that's because we don't
have this node connect to anything we
need to connect it to the final Master
sack in order to render something so
again on the output over here we can see
a four so these are all of our colors
and actually one very useful node is the
preview since so many things in Shader
graph can be hard to visualize so we can
move these nodes around and let's add
the preview node
and this does examine that so you can
fit it an input and you can see down
here what that input contains so for
example let's drag just the red Channel
and if they go over there we can see the
red channel for this texture we can drag
the green channel the blue Channel or
look at the alpha Channel yep there you
go it does work so this preview node is
super useful for being able to see what
your Shader is actually doing over here
we have the colors so let's get rid of
the preview right now in order to make
it work we really just need to connect
the rgba and go up here into the base
color and right away it should work but
you might not be able to see anything
over here on the main preview
I believe this is a rendering bug in the
current Tech version so right now
nothing is shown
so if you still don't see anything it's
actually pretty simple just go up here
on the top left side and make sure to
save the ascent okay save it great then
let's exit from our maximize View and
now let's close this tab let's click on
play just to play the game now let's
stop playing and now if we open the
Shader again if there go now we do see
the Shader compiling over there that
color that is the Shader compilation and
after a little bit it should work let's
just maximize this
see if there you go there we do see our
texture okay great
so again it's just a simple rendering
plug on the current Tech version if
you're watching this video in the future
chances are you don't even have this box
so there's no need to worry okay so
right now we do see it working we can
see our bread texture and it's currently
being applied on a sphere for a use case
we're working with 2D textures so this
would be best to be seen on the Quan so
we can right click over here on the
preview in order to select the preview
mesh so let's go with a simple quad and
if there it is we have our Knight Squad
okay great
so over here we have our basic Shader
all it does is just shows the texture
that's it now it's actually use this and
first let's always make sure to save the
asset on the top left side on the moving
visual if you see an asterisk here that
means you have unsafe changes so always
make sure to save them in my case I
don't but still never hurts to save now
over here in scene view let's go inside
art only three counters and let's open
it and now for the display for our Arrow
let's make it a flat one so let's right
click in the hierarchy and let's create
a new 3D object and let's make it a quad
let's call this the delivery Arrow
let's place this on top of the counter
so let's rotate it to face upwards by
the way on the rotation make sure the
collar is facing upwards most shaders by
default they only render one face and
not the other one so make sure you put
the face with the collar upwards and not
the other one okay so let's rotate this
one upwards so there we go 90 over there
and let's just put it just exactly on
top of the counter so just enough so
that it's visible okay great so now
let's make a material for our Arrow so
let's go inside the materials folder and
over here let's create a brand new
material
let's call this the delivery Arrow let's
make sure to use this material on the
quad so let's just drag it over there on
the mesh render okay so it's using our
custom material and over here on this
Shader graph drop down menu over here we
can select what Shader we want to use so
in our case let's go inside the founder
Shader graphs and inside yep here we
have our moving visual Shader so let's
go ahead and use this and here right
away we do see that it does work here we
have our texture being drawn exactly on
top of our material okay so far so good
now again here remember one very very
important thing that I said the texture
that you define the Shader over here the
default for the property this one is
only the default the important one is
the one that we have on the material I'm
emphasizing this point because I've seen
a bunch of people make this mistake if
you modify default texture whilst inside
the Shader like for example if I change
here from bread let's say into the
Cabbage slices
if I modify that note how it does not
modify any materials that were created
we are only changing defaults so if you
want to change the texture that is
actually used make sure you change the
one on the material that you created and
not the defaults I changed the default
but did not change this Shader however
if I now were to make another material
which by the way here's a quick tip you
can recollect directly on the Shader
file and going to create and create new
material and it will automatically
create the material using that Shader
naturally here then update default just
because I didn't save the Shader so I
modified this one for the camera slices
and now if I save the asset and now if I
right click there and I create a brand
new material and yep now that one does
have the new default but again remember
what you said over here is just the
default what really matters is what is
on the material after the material has
been created modifying default here does
nothing so always keep that in mind in
most cases you want to be changing the
property on the material itself not the
default on the Shader okay let's just
clean up both of these all right so
let's continue now here we have our
Sprite working okay except we don't want
to show some bread so let's actually use
the proper Arrow Sprite so let's select
this one
and yep it does work it is printing the
Sprite however one obvious thing is that
the arrow is not transparent like it
should be so let's solve that back in
our Shader graph in order to make this a
transparent Shader we need to actually
go into the graph settings so on the
graph inspector go into graph settings
and over here you see a bunch of
settings that relate to the graph itself
and not any selected property so let's
go into graph settings for example like
I mentioned a while ago you can modify
between lit and lit and so on so this is
where you would change that you can also
appear at multiple targets so you can
create a Shader in Shader graph and make
it work with the Universe on random
pipeline or the high definition render
pipeline or the built-in render pipeline
all of those are supported through
Shader graph now for a goal in order to
make this a transparent Shader let's
just go over here onto service type
instead of opaque and let's change to
transparent and as soon as we do look
what happens there and if there go it
adds a brand new Alpha Channel if we
just save the asset right now and open
look at that it still doesn't work it's
still not transparent basically we made
this Shader transparent but now we need
to fit in the transparent Channel over
here onto the alpha this is the one
thing that is different from a previous
version of shadowgraph previously you
could just feed the alpha Channel over
here onto the base color and Shader
graph would automatically apply it but
in recent versions you need to add it
over here separately so if you have any
issues with transparency when following
some older share graph tutorials always
remember this change I covered that
along with some other changes in a very
useful video so if you're following
along some other shade graph tutorials
make sure you watch that video to learn
what you need to do to update them to
the latest version okay so here on the
similar texture we already have the
alpha channel so we just connect this
onto the master Alpha and right there we
already see it working let's just go
ahead save our asset and here in scene
view if there go now we do see our Arrow
now one more small thing you might
notice that from some angles it's not
exactly transparent basically it
actually is transparent but since we
made this in literature sometimes the
light might make the transparent Parts
visible one option to solve that is over
here on the graph settings instead of
making it lit let's make it unlit that
would work say up with the unload Shader
the transparency is perfect but if you
really want to keep it lit then the
other thing you can do is just over here
play around with these settings you've
got smoothness AO and so on and over
here you can even modify the workflow
mode so for transparency instead of
making it metallic let's go with a
specular workflow and then over here set
the smoothness to 1 and the ambient
occlusion down to zero and now if we
save this Shader look at that and yep
now the transparent parts are indeed
fully transparent finally over here on
the right side on the mesh render if you
want you might want to play around over
here with the cast Shadows so maybe you
don't want this one to cast Shadows
maybe you don't want it to impact light
probes and so on okay so with this we
have our nice transparent Arrow
let's make sure to save our delivery
counter so let's go outside back into
scenes
and let's head on playing and if there
you go we have our transparent counter
with our nice Arrow now we want the
arrow to actually move and doing that is
actually super simple going back here in
our shadow graph let's just modify
default just so we can see the arrow
that we want to see so let's select the
arrow Sprite okay there's our Arrow now
for moving over here on the simple
texture we've got an input for the UV
the UV is what defines what portion of
the texture we're going to grab which by
default just gets the whole texture so
since this field represents where we're
going to grab from texture by playing
around with this we can grab different
parts so to do that let's just add a
standard UV node so here it is this is
the standard UV channel so if we connect
this then nothing changes everything
still renders exactly the same but now
we can modify this and to do that we're
really just going to use some basic math
remember that when working with shaders
even though you do see colors everything
is really just numbers so uv2 is just
number the converges the number the
alpha is just a number so visually
everything might look like images might
look like colors but really in the end
it's all just numbers so for example how
do we move this texture well it's
actually pretty simple we just add a
number onto it so we're here on the UVM
let's just add an add node so this just
adds two numbers together very basic so
let's take the regular UV and let's add
something on top of it for example we
can make a vector two
and let's put it on say 0.10
and let's add this one onto this one and
now if we drag this one onto the input
and look over there on the preview what
happens and if they're going like that
it moves slightly to the left so if I
modify this one put it on zero there you
go and that point one on that point two
on that and so on so you can see that by
modifying here I'm essentially
offsetting the texture I'm offsetting on
the X and over here I can also offset it
on the y basically I'm offsetting the
texture by ten percent the UV is a
normalized value this is not pixels so
that is why point one is ten percent
regardless of how big the texture is and
if we go way past one then texture
essentially Loops back so this is really
all we need
for our moving Arrow we're going to have
zero on the Y and on the X we're going
to constantly either increase or
decrease that's how we're going to have
our moving Arrow so again the only issue
here is that I'm modifying this manually
we don't want a fixed amount on the
Shader instead we want a nice animation
so for that we have the very useful the
time node
this one has various time-based outputs
the one that we want for this case is a
time which is just the total time this
one is constantly increasing since the
start of the game by the number of
seconds so if you use this over here
directly on the end and they're gonna
look that texture is constantly
scrolling okay so that's great except
obviously we have one issue we don't
want it to scroll diagonally we only
want to scroll in One Direction so for
that we can essentially create a simple
property to act as our spin so let's
over here on the Blackboard let's create
a new Vector two column Tower speed
property and for the phone let's see if
I want to say 0.1 on the x0 on the Y and
now if I drag the speed over here onto
our Blackboard okay great this is
basically a multiplier so we just need
to multiply the time by this so let's
add a multiply node also by the way
quick tip over here on each node you've
got a nice little arrow so if you want
to make it a bit more compact so if you
don't actually need to see the preview
so make that and in this case let's take
our time multiply it by our speed and
then for the output pass it into the end
okay so like that now it is indeed
moving in this direction and over here
on the speed we can play around the
values so if we put that 0.5 now it's
moving faster and if I put it on the Y
now it's moving diagonally put zero on
the X and now it's only moving
vertically okay so this is really what
we want let's just go ahead save our
Shader and now let's just select our
delivery Arrow material and over here
yep we've got the spin if you don't see
it make sure they're on the speed
property over here you have it exposed
so we have the speed instead of moving
on the Y let's move on the X and
actually like this it's reverse going
backwards so over here we can just put a
negative value so let's put it on minus
one and if there go now the arrow is
moving perfectly also here let me make
one important note just in case you're
using this Shader with a custom texture
instead of the one included in the
course if you do that make sure that the
texture that you use over here I'm using
the arrow texture
over here on the Arrow import settings
down here under wrap mode make sure it
is set to repeat if you set it as clamp
you might get some weird visuals or
nothing at all in order for the texture
to constantly Loop and constantly repeat
itself that one needs to be set to
repeat okay so here it is in game and we
have a really nice moving texture for
that we created the simple but really
nice useful custom Shader definitely go
ahead and watch the various effects that
I made in the shadow graph playlist this
tool is super useful definitely make
sure you know how to use it I've used it
for making a building effect I've made
some nice outlines a really nice wind
Shader also a really interesting the
sound of effect and even a cool
transition Shader just like in the game
Hades so this really is a super powerful
tool make sure you watch that playlist
to really learn how to use it alright so
here we'll learn about share graph and
created a really nice custom Shader
however the delivery counter still only
has a visual so let's create some proper
Logic for generating and delivering the
correct recipes in the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to build a
proper delivery manager that will
generate recipes that customers are
ordering and validate to see if the
player made the right dishes alright so
right now we have the player capable of
making dishes so for example I can put
some cheese cook some meat cut the
cheese and then pick up both of them
then let's say pick up some bread there
you go got a nice cheeseburger and
deliver it okay so that works but right
now they just vanish on delivery counter
so there's no recipe we need to follow
no validation none of that so let's add
both those things okay first of all
let's make our script so let's create a
brand new sharp script for the delivery
manager let's make a new game object to
run it so we need delivery manager
attached to script let's make sure to
keep things lean so reset the transform
and also by the way since we're here
let's go ahead and put the plates and
delivery counter inside the counter so
everything is nice and organized okay
great so let's open up this script now
here basically we need to Define some
sort of list to store all the recipes
that the customers are waiting for which
of course begs the question what type is
that going to be now technically one
thing we could do since a recipe is
around just a list of kitchen objects
over here we could have a list of list
of kitchen objects this would be our
recipe list technically that would work
but that really looks quite dirty
instead of having a list of lists we
should probably have a proper type for
this so let's write some good clean code
and Define a proper recipe Script Mod
object back in unity let's go inside
script knowledge's folder and create a
brand new one let's call this the recipe
so and over here let's make this a
script Mall object so extend script on
object make the create asset menu
and over here for the films for that
that we need well like I said a recipe
is just a list of ingredients so just
taking a list of kitchen object that
sell for the kitchen object SM list
okay that's it that's really all the
data that we need to define a recipe
just to be able to identify them for the
player let's also add a public string
for the recipe name
so just a nice name String okay great
now back in the editor let's define so
let's go inside the certain objects and
make a brand new one for our recipe so
and now inside let's create a brand new
recipe SL for this one let's call it
just burger and over here first of all
for the name just name it burger and
then for the kitchen object list well to
make a burger let's well first let's add
some meat and we want some cooked meat
we don't want to serve uncooked or burnt
meat so only the cooked meat then for a
simple Burger obviously we need some
bread and that's about it so some bread
some meat that's our very basic Burger
now let's also make another one so let's
duplicate this one and name this one the
cheeseburger over here let's name it
cheeseburger
and lightning place has bread meat and
obviously some nice cheese slices
so there you go okay we have a
cheeseburger now let's also make a mega
Burger so something with everything
so let's call this one the mega burger
and over here for the string name for
the Mega burger and for that we have
meat bread cheese let's also have some
nice cabbage slices and also some tomato
slices alright that's our Mega burger
with everything and finally let's also
make just a nice simple salad so let's
duplicate this for a salad
let's name it salad
and for the salad we don't have any meat
we don't have any bread and also no
cheese so just cabbage slice and tomato
slice that's a simple salad okay so here
we have all of our recipes so back here
on the delivery manager script instead
of making a list of lists of game
objects let's just make a list of recipe
recipe so and name it the recipe so list
this is where we're going to probably
see recipes that the customers are
waiting for so it's actually rename this
let's put it waiting recipe on list okay
so the customers are waiting for
whatever is inside this list and now we
could make this a serialized field then
set it in the editor but we don't want
to have a fixed list we want to
periodically spawn new recipes in order
to spawn new recipes we also need to
know which ones we can spawn so for that
we could add a list of all of the
recipes then we could pick a random one
from the list and add it over here to
the waiting list that would work that's
one good approach but since we already
did something similar to that various
times in this course here don't let me
teach you a different approach that
sometimes might make more sense for that
second approach we just need one thing
we need a script more object to hold all
of our recipes so let's do that let's do
a brand new c-sharp script this is the
recipe list scriptable object and then
inside this one is going to be a
scriptable object let's add the create
asset menu
and inside we're just going to have a
list of recipe so
for the recipe SLS so that's it super
simple now let's just create one object
of this type we can put it inside the
recipe as soon as since we're only going
to have one so let's make a recipe on
Lister so namely the recipient list SL
and then over here let's just drag our
recipe so we've got a burger a
cheeseburger we have a mega burger and
finally a salad okay so basically we
have a script ball object with all of
our recipes and now just for safety
since we only want to ever have a single
one of these objects a recipe on SSO for
this one we can go back here in the
script and simply comment out the create
asset menu so now back in the game over
here we can no longer create another
type of recipient list so so just say
nice safety thing since we probably only
need just one and let's also add an
underscore just so it shows up at the
top-down list okay great so we have this
and over here on the recipe manager we
can basically expose that in a
serialization so let's make a serialized
field
make it private of type recipe so list
recipe enlisted so for the recipient
list so and now here in the editor we
just drag that reference alright that's
it so basically the difference that we
did with this method is over here on
delivery manager instead of having a
list of all of our recipes we just have
a reference to one object and then that
object holds a list of all the recipes
in this specific use case like I said
this approach doesn't really have many
benefits compared to just starting the
last year but let's say we had another
script that also needs a list of all of
our recipes if we did that we would
basically have duplicate references so
this script would have a list of all the
recipes then some other script would
also have a list of all the recipes and
then if you wanted to add a brand new
recipe you'd need to add it to all the
lists on all the scripts whereas like
this any script that needs to know about
all of the recipes just needs a
reference to the recipe on SSO and
whenever we want to add or remove a
recipe we just need to update this one
object and everything works perfectly
that's one of the benefits of this
approach where you have a script mode
object to hold a list of all the objects
of some type personally I find this
pattern to be quite useful okay so on
delivery manager we have a list of all
of our recipes now let's just make a
simple timer to spawn them like I
mentioned previously in the spawn point
logic you could just use Echo routine if
you like that
core routines can be useful for running
timers but personally like I mentioned I
do not like Co routines I don't like the
pattern they force it to use so over
here I'm just going to make a simple
flow timer
so a private fluid for the spawn recipe
timer another one for the recipe timer
Max and let's say 4 seconds
then we just do a simple and private
weight update
on update let's count down the timer so
time dot down for time
and if the spawn timer is under 0f let's
reset the timer
and now let's basically spawn a recipe
so for that let's grab a random one from
the list so we go into the recipe list
so and grab the recipe as a list then
we're going to grab a random one so
let's get a random index so random.range
between 0 and the recipient list so dot
recipes dot count so you get a random
one this is going to be a recipe so for
the waiting recipe so
and then we simply go into the waiting
rest PSL list and we add a brand new
recipe okay that's it super simple let's
just make sure to initialize the list so
let's do here a simple awake for the
waiting recipes and just initialize it
okay so like this it should be working
however we're also going to generate
recipes non-stop we don't want that so
let's define some kind of maximum
so let's Define a simple end for the
waiting recipes Max
let's say we kind of have a maximum of
four recipes waiting
and then down here when camera lapses so
if the waiting recipes only stock count
if it is under the maximum then we
generate and add it okay that's it
pretty simple
now for testing let's just set allow
here to print the name so debug.log on
the waiting recipe so that we generate
so let's print out the recipe name okay
so let's test so here we are in yep one
will spawn right away so we have a solid
and after four seconds Yep they're going
out of salad and if we wait for four
seconds we should have another one there
you go a mega butter recipe and finally
after four seconds we have yep we have
another burger and now no matter how
much time passes there should be no more
since we're at the limit any uptime pass
then no more okay all right awesome so
we are correctly generating recipes that
the customers are waiting for now it's a
logic to try to fulfill these orders so
over here on delivery manager let's make
a function to deliver a recipe
so let's make a public Point make it
public since we're going to access this
from the delivery counter currently
deliver recipe
and the recipes are going to be
delivered whilst on a point so let's
receive a parameter of type Plate
Kitchen object
and over here the logic is actually
going to be pretty simple we just need
to cycle through all of the recipes that
the customers are waiting for and see if
the ingredients on this plate matches
the ones on any waiting recipe
so over here let's cycle through all of
our recipes so let's do before
entire zero going through the entire
recipe only star count I plus plus okay
let's grab the recipe so for the waiting
recipe so
and we grab from The Waiting recipes on
list on this index okay so we have that
then first let's do a quick test just to
check if the waiting recipe has the same
number of ingredients as they are on the
plate if not then we already know that
it's not valid so over here let's do a
quick test SO waiting recipe so let's
check the kitchen object that's only
it's not count if this one matches the
play kitchen object let's get the
kitchen object that's on the list and
also check the count so over here we
know that has the same number of
ingredients
so this is the first check then we need
to cycle through all the ingredients on
this recipe and all of the ingredients
on the plate and basically see if both
of them match so let's first cycle
through the ingredients on the recipe so
for each
kitchen object as so let's call it the
recipe kitchen object so in the waiting
recipe so let's go into the waiting
recipe and get the kitchen object list
okay so here we are cycling through all
ingredients in the recipe
then we need to cycle through all the
ingredients on the plate so let's do
another cycle for the Plate Kitchen
object SL and we're going to go inside
the Plate Kitchen object get the kitchen
object that's on the list like this
so here we are cycling through all the
ingredients on the plate
okay so now here basically we need to
see if this ingredient that we're
cycling through if this one matches the
ingredient on the recipe so here we
check if the Plate Kitchen object does
so if this one matches the recipe
kitchen outlet
if so then the ingredient does match
so in order to keep track if it does
match
over here before we cycle through all
the ones on the plane let's define a
bone for found or ingredient found
let's default it too false and over here
if we have match then this one becomes
true and by the way over here we can
also break out of the cycle
now if you're not familiar with break
basically this is going to break out at
the for each so let's say the plate has
10 ingredients and the second one
matches when this cycle gets to the
second one it triggers a break so it no
longer goes through the remaining eight
so basically it breaks out of the cycle
so keeps writing some code right down
here okay so we cycle through all of the
ones on the aggressively then recycle
through the plate and if we do find that
ingredient on that plate then we have an
ingredient found so over here
if we have a not ingredient found
then over here that means this recipe
ingredient was not found on the plate
so if that happens then essentially over
here we have a phenocate so the
ingredient that this recipe requires is
not on the plate so let's go up here
when we have the same number of
ingredients let's define a Boolean
called the plate contents matches recipe
let's see found it to true and over here
if we don't find at least one of them
then the plate contents do not match the
recipe and afterwards we can check this
bowl again
so if this one is true that means they
all match if just one of them does not
matches then this one won't be false
so over here we know player delivered
the correct recipe
so over here on let's do a quick debug
down log and print out a message
and after we do let's also do a return
so we stop the rest of the execution so
basically if we find a waiting recipe
that matches we don't want to keep going
and also here if we do find it let's
also remove it from the list
so let's go into waiting queue remove at
and remove at this index okay so we're
going to remove this recipe but if this
doesn't happen then it's going to be
keep cycling and it's going to cycle
through all the recipes so basically if
it reaches the end this far
then basically no match is found
so the player did not
deliver a correct recipe
so let's do another debug in here
okay so this is done for logic it looks
a bit complex but I hope this was easy
to follow when we see it in action It
all becomes a bit more clear so all
that's left is just calling this
function from the delivery counter so
let's do that over here on the delivery
counter it accepts plates and destroys
plates but before we destroy
let's go into the delivery manager which
means we need to access a reference so
again we could add a serialized field or
in this case it makes perfect sense to
make this a Singleton so let's make it
here public static of type delivering
manager call it instance with a public
get and a private set
okay then over here on awake let's set
instance equals this
all right so now over here on the
delivery counter we can go into the
delivery manager access the instance and
deliver our recipe and pass in the Plate
Kitchen object
okay that should do it let's test all
right so let's look in the log to see
what they are waiting for so there are
two cheeseburgers waiting another Mega
burger and a cheeseburger so let's make
a cheeseburger to deliver so first of
all let's cook some meat let's slice
some cheese let's pick up the meat
before it burns pick up the cheese and
we just need the bread okay this is a
valley cheeseburger so let's deliver it
and if there go the players delivered
the correct recipe okay great
now let's deliver something that nobody
asked for let's say just some meat
actually let's burn it just for fun all
right so there we have a bunch of
charred meat so nobody really wants this
but if we deliver if their yield player
did not deliver a correct recipe alright
awesome so over here everything worked
we have a bunch of recipes being
generated and then we have the logic so
that when the player delivers something
it checks if the players delivered
something correct or incorrect so
everything is great all that's missing
is obviously some nice UI so let's do
that in the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to create a
nice UI visual to display our waiting
recipes okay so our delivery manager is
already working we are randomly spawning
some random recipes every once in a
while now instead of looking at the
console let's add a proper UI so for
that over here in the editor let's go
inside the canvas and by the way let's
click on the button to unlock the canvas
and this is actually the first time
we're using the Ragnar canvas quite a
while ago we just created it we didn't
really set it up so let's quickly do
that for the render mode this one is
meant to be a regular UI so let's leave
it on the screen space overlay then over
here on the canvas scaler instead of
constant pixel size let's go with scale
with screen size then for the reference
resolution I like to use 1920x1080
and finally unlike to fully match with
the height basically this means that
objects in the canvas will be scaled if
the height changes for example let's add
inside just a quick UI image just a test
let's look in the game View
so there you go there's the image let's
just put on a different color okay so
there's the image and note how if I
modify the aspect ratio here so let's
say I put it on 5x4 there go the
horizontal side of the window change but
note how the element was not scaled so I
can put it even on free aspects so
really wide and does not change the size
whereas if I modify this if I modify the
vertical size the image does indeed get
Scaled up or down personally I like the
setup because means that I only have to
worry about positioning things
horizontally if the vericon part gets
changed everything gets automatically
scaled okay so great so over here let's
go back into 4G all right and let's get
rid of the image all right back in the
scene view let's quickly look at the
canvas so we can select the canvas press
the F in order to zoom out and also we
can press the 2D button up here to go
into 3D mode okay so here's our nice UI
now inside the canvas let's create them
to game object call it the delivery
manager UI then in the inspector let's
make it stretch to occupy the whole
thing so let's put zero on everything
okay so this window now occupies the
entire screen
now inside let's do just like we did a
while ago for the plate icons meaning
let's make a template that we can then
clone but let's also put those templates
inside of a container so first of all
let's make the containers so a new empty
game object
of currently just the container the
reason why I'm going with this approach
is because I also want to have other
objects outside of here if you remember
how we did with the templates we can
actually go there and see so let's go
inside the prefabs inside the counters
actually it's on the kitchen objects
let's go inside the plate over here for
the template basically we use the play
tokens UI this main canvas as the
container but if you remember how we did
that in order to make sure we didn't end
up with duplicate icons we always
destroyed the previous one when we
spawned a brand new one so every time we
were cycling through the children of
this object in order to destroy all of
them except the template so over here
we're going to use a container so that
we can apply the logic only to the
children of the container and that way
we can have other objects outside of the
container for example outside of here
let's say we want some nice text just
saying recipes and waiting so on
delivery mansion let's make it a
challenge down let's go into UI and
let's make a text text mesh Pro and this
is the first time that we're using text
mesh Pro so this window pops out it's
actually import mesh Pro Essentials okay
just let it import okay that's it we
don't need the examples are extras so
let's just close this window and over
here on this window let's name this the
title text let's set the text to
something like recipes waiting
let's put it up there on the corner so
let's anchor it on the top left corner
also for the text I like to put it on a
width and height of zero but of course
that makes the text really vertical so
then down here on the wrapping let's
just disable it so there you go looks
like that and let's put it over there on
that corner now in scene view we are
seeing things different so if you want
to see what this looks like just go into
the game View and over there yep we do
see the recipes and let's just make it
in bond so there you go just some nice
text okay so that's our text and then
for the container let's make inside the
delivery template so let's create an
empty game object let's go with the
recipe template and for this one we're
going to want to Anchor it to the top
left corner so with the template
selected over here in the inspector
let's click and we want to click up here
however we also want to set the pivot so
let's make sure to hold down shift in
order to set the pivot over there okay
great that's exactly what we want so we
want the template right on the corner
then let's give it a size of say 250 by
100 okay now inside template we just
need two things we want to name the
recipe as well as the list of all the
ingredients although before that let's
actually make a nice visual for the
background so a new UI image for the
background
let's make this one stretch to occupy
the whole thing let's put everything on
zero okay that's the background let's
put it on a black we're just a little
bit lower Alpha okay that's good then
for name let's make a text field so
inside the template let's create another
text call it the recipe name text then
over here let's put it a bit small so on
the font size of maybe just 20 let's put
it in bold
and let's also again put the width and
height of 0 and over here make sure to
disable wrapping okay so that's the text
so we've got it up there let's just
anchor it to the top left corner okay
great
over here we can change the name to
recipe and then what we need is the
icons on here and for that we're going
to do pretty much the exact same thing
that we done on plate but before we do
that logic let's just get this basic
setup working so let's just position
everything so first of all the container
for all the templates let's anchor it on
the top left corner and let's push it
all the way over there and for
positioning them let's use this time the
vertical layout group so inside let's
duplicate the template just to be able
to see them okay so that's pretty much
we want we can actually set the width
and height both to zero and let's set
the spacing to something like 30. okay
so that's our basic UI now let's make
the script to run this
so over here in our scripts let's create
a brand new C sharp script for the
delivery manager UI let's go into the
parent game object and let's attach your
script let's open okay so now here first
we need a field for the container
another one for the template
so let's do a serialized film private
transform for the container
and another one for the transform and
this is going to be the recipe template
then let's do pretty much same thing we
did previously so first of all let's
actually go on a way in order to hide
the template so game objects set active
into false okay so first we hide the
template then let's make an update
visual function so private void update
visual
and for updating we're going to do the
exact same thing that we did so first
let's cycle through the container and
destroy everything except for the
template so do a 40 inch transform child
in the container
and if the child is the template
if so then we're going to continue and
if not we're going to destroy the child
game object okay so we have the cleanup
now we need is the second through all of
the waiting recipes so that means that
over here on delivery manager we need to
expose our waiting recipes on list so
let's go down here make a function to do
that probably going to return a list of
recipes so get waiting recipe so list
and we just return the waiting recipes
on list
okay great
so now here on the UI we can now go into
the delivery manager xsc static instance
in order to get the waiting recipes on
list so let's cycle through this so do a
40 inch for each recipe so recipe so in
the waiting rest vsl list
for each of them let's instantiate
and let's spawn our recipe template
spawn it inside the container and then
we just need to set this to enabled so
let's read the transform for the recipe
transform we grab this one grab the game
object and set active into true okay so
like this the only thing missing is the
text but that's okay for now
let you see where we're going to call
this function to update the visuals and
as usual we want to be smart and write
some good clean code so let's not do the
dirty approach of just updating this on
every single update instead let's only
call this function when something
actually changes so over here on the
delivery manager let's just make some
simple events
so if I'm like event event handler
let's go on recipes fund and another one
call it on recipe completed
and actually as soon as I add the event
handler which also add the using system
now here we have an interesting thing
we've got a nice namespace Collision
it's telling us that random is an
ambiguous reference between Unity engine
now random and system.r random that is
because both these namespaces Unity
engine and system both of them have a
class named exactly random so the code
here does not know which class we're
trying to use to solve this component we
really just need to be more specific in
this case here we want to use the UNT
engine version so let's just write the
full name Unity engine.renom and yep
that works okay so now let's fire off
the events so first of all the own
recipe spawns over here when we spawn a
recipe let's invoke this event so this
is ventar is not empty and let's also
get rid of the log we know we need that
okay now we could also add the wedding
recipe on the event artist but in this
case we don't need it just firing the
event is enough and then down here when
the players delivers something if the
player delivers the correct recipe we
remove it from the list and then let's
fire off the event so on recipe
completing let's invoke with this and
event rx.mt okay so we have the event
and down here we also don't need analog
okay so that works and finally over here
on the delivery man GUI let's just make
a private void start on start going to
the delivery manager access the static
instance and listen to both these events
so they spawned and let's also listen to
the other ones the library manager
instance on recipe completed
when either of these work let's just go
and update the visual so just like this
let's also rename this because again
instance doesn't sound like a very good
name let's actually rename this to only
remanager and same thing up here by the
way I'm using the visual studio shortcut
control RR in order to rename this to
delivering manager
and finally we also need to update the
visual OnStar just make sure the
previous ones do not show up okay that's
it so like this it should be working we
should be able to see no Visual and then
as more our spawned we should be able to
see each one being spawned until the
maximum so let's see just over here in
the UI let's make sure to drag the
references so the container and the
template and let's hit on play and okay
right away actually it spawned one
recipe it spawned instantly then after
four seconds there you go a second one
and after four seconds we should be able
to see yep another one now four more
seconds and we should see the final one
and now no matter how long we wait it
should no longer spawn anymore and yep
that works alright awesome so the basic
logic is working now let's handle the
proper Logic on the template for that
like I mentioned previously one approach
would be over here you could go and do a
transform.find
the actual recipe name text then get the
text mesh component and set it that
would work but like I mentioned
previously that would be very dirty not
good at all we should avoid using find
at any time and we should also avoid the
individual logic from the total logic so
let's do it properly and make a proper
script to handle each spawn template so
let's create a brand new c-sharp script
call this delivery manager single UI
single just because it refers to a
single recipe and also right now we
already have quite a few UI scripts so
let's organize our project again so
let's organize new folder for the UI and
inside let's put all of our UI scripts
so if we manage is single this one
deployed icons white icons and the
progress bar so let's put all of these
nicely organized in the UI folder okay
so with the script let's go into the
recipe template and attach the script
now let's open and over here let's begin
by adding a film for our text so a
serialized field
and over here it's also very important
for the text we are not using the text
inside DNT engine.ui this is the in
Legacy text it is not text mesh Pro so
this is not what we were using instead
we want to use text mesh Pro U going
which is inside TM Pro
so we need to go up here and add using
TM Pro and now we can use this type and
also make sure you're using text mesh
Pro ugui and not text mesh Pro this one
also exists but don't mix these two
these are two very different types if we
go over here in the editor and if
outside the canvas if I just create and
create new 3D object a new text object
if I do that then if we look over here
in the inspector we see this one as a
type text mesh Pro whereas for the ones
that we're using inside the canvas if we
unlock this is text mesh Pro it's a UI
text so these are the two different
classes within text mesh Pro you have
text mesh Pro and text mesh Pro ugly
we're working on the UI so we want this
one okay so we named this the recipe
name text
okay that's it over here in the editor
let's drag our reference all right so
now this group let's make a function to
set the recipe so a public void and
let's call it set recipe SL
they're going to receive a recipe so
recipe so
then we just go into the recipe name
text and we set the text to recipe so
dot recipe name
okay so that's pretty much it now over
here on the Y script when we instantiate
our recipe transform let's get component
of type of our
delivery manager single UI and call set
recipe so and pass in the recipe so okay
so let's see if the name shows up any
operator wait does show up so we can see
that we generate a cheeseburger recipe
and right now a mega burger recipe okay
great so all that's left are the icons
on here so like I said that is going to
be yet another usage of our template
pattern
so inside the recipe template let's
create an empty game object currently
the icon container and then inside that
let's make the template and template is
just going to be an image so we can just
create an image to our way
called the ingredient image let's scale
it with a size of 40 and 40. let's put a
image by default just like that and on
the icon container let's put the width
of zero height of zero and let's put a
horizontal layout group put it over
there on the left side and we can create
a bunch more just to see how it looks
okay so that's pretty much it now over
here on the single script let's add a
serialized field private transform for
the icon container another one for the
icon template
then we do the same thing as usual so
when we set the recipe so let's first of
all clean up the container so let's do a
40 inch transform child in the icon
container
and if the channel is the template
then we want to continue and ignore it
if not we want to destroy the child.game
object okay so that's the cleanup
and then let's do a four inch kitchen
object as so
in the recipe so dot kitchen object.zone
list
second through all of this let's
instantiate our icon template
instantiate it inside the icon container
so this is going to be the transform for
the icon transform
then as usual we need to go into the
game object set active in order to
enable it
and also let's go up here make a private
way to wake and on awake the icon
template game object let's disable it
okay we don't want the template to be
visible
okay so we instantiate the template we
set it as active then since this one
just has an image we can just do a get
component of Type image
that's image not image conversion
so image so it's this one the one inside
Unity engine.ui so let's get this image
and let's modify the Sprites and set it
to this kitchen object so that's right
okay so that's it that should do it
let's test over here in the editor let's
just go into the template let's drag the
container reference and the template
reference and let's also rename this
instead of ingredient image put icon
template just to be a bit more clear and
we can get rid of the other ones or
leave them doesn't really matter okay
great so let's hit on play and see and
yep right away does work so we can see a
burger is composed of a burger and a bun
a satellite yep there you go some sliced
cabbage and sliced tomatoes then
cheeseburger same thing as the burger
with some cheese and then another Burger
let's just deliver until we see the mega
Burger so let's deliver a cheeseburger
let's cut it
get this get some bread place it in
there pick it up before it burns that's
a cheeseburger so that one should vanish
and if they're good does vanish let's
see something else not cheeseburgers so
let's keep doing until we get a Mega
burger just see that everything works
so let's deliver a regular burger okay
now let's deliver a regular salad
okay just pick up like that like that
and drop it
okay let's see
any up there it is the Mega butter all
right great so the visual logic is fully
working and the delivery logic all of it
is working
so I can deliver the right recipes and
get rid of them from the recipe waiting
list and more are spawned every time
here we can see the name of the recipe
as well as all of the nice icons okay so
with all this our game is really taking
shape everything is very close to being
done
one massive thing we're still missing is
an obvious one which is sound so let's
do that in the next lecture
hey again quick intermission you're
almost at the end so once again congrats
for making it this far this is the
second secret call out go ahead Post in
the comments a timestamp and a nice monk
Emoji it won't be fun to see how many
people make it to this point by now you
already know about the website I hope
it's been very useful to you and you
already know to ask any questions in the
comments if you need help with anything
so that's life for me to say right now
is thanks for watching the course so far
and I really hope you've already learned
a ton there's only a bunch more lectures
until we get to the final polish game so
let's continue on the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to add some
audio to our game starting with a really
nice music track okay so our game is
already looking pretty good but
everything is still way too silent so
let's begin by adding some music adding
this is actually extremely new in the
included assets over here inside the
sounds we've got a really nice music
track I hired a musician to make this it
sounds really good it's a seamless Loop
so to add to our game it's going to be
super simple we just want a constant
never-ending Loop so let's begin by
creating an empty game object call it
the Music Manager
let's reset transform keep things
organized and let's add a component and
we want the component an audio Source
here it is this one like name implies
this one acts like a source of audio
you will note how by default on the main
camera down here it already has an audio
listener so the source plays some sound
and The Listener listens to it now for
here we just need to set these fields so
for example on the autoclave let's make
sure to drag the music audio okay great
next over here and let's enable and play
on a wink we wanted to start playing
right wing and for this track we do want
to enable looping okay great then for
priority basically UNT has limited to
how many sounds can be played at once if
you play too many then some sounds won't
play and which ones do you play is all
based on priority we always want the
music to play so let's put this one on
Max priority
then for the volume later on we're going
to make a proper option screen to handle
this
but for now let's put it on something
like 0.4 or 0.5 just make a nice
background track then we have here the
spatial blend for this music track we
wanted to play the same regardless of
where the camera is so let's make this
all the way if only a 2d sound okay
that's it we don't need to play around
with any of the other settings and just
like this if we are on play any up
there's the music now if you're not
hearing anything make sure that on the
game view first of all that the game is
actually selected make sure the scene is
in Focus so over here I can move around
so the game's in Focus then on game view
we are on the top right corner make sure
this sound icon is toggled if not then
everything is muted and also again make
sure like I mentioned on the main camera
that it has the audio and listener
component with all that yep you should
be able to hear the music
now this song is playing and it won't
Loop forever just like we wanted
personally I really like how it sounds
I'm really happy with what the composer
made it perfectly matches the E5 of the
game so it really is this simple to add
some music to the game let me just point
out one thing also related to sound one
of the things you can make is an audio
mixer so for example on the project
files let's create a brand new and let's
find over here the audio mixer so there
you go here is an audio mixer then you
can double click to open up the audio
mixer window and then over here you have
the masternode
and then you can create multiple groups
so let's create a brand new groove for
something else
and then you can play around over here
with the effects with the volume all
kinds of things all kinds of effects
everything then for each sound where you
have the audio Source over here note how
you have an output and for this output
you can set it to play on the message so
it plays on everything or set it on just
one individual group so with this you
could assign a group to one individual
type of sound effect or the music or so
on maybe you could even have your music
split into multiple stems so there's a
lot you can do but for me I'm not an
audio engineer audio is probably the
part of game development that I know
least about I just stick with the
absolute Basics but if you want to learn
more definitely look into the audio
mixer this is an extremely powerful tool
but like I said for me I don't know how
to work with it so I'm just going to
stick with the basics so on the output
let's revert back into none close the
audio mixer and get rid of this and
there it is music is playing and the
wrong sounds really nice alright so here
we very easily added some music to our
game this lecture is actually super
short because it is generally that
simple now the next thing that we need
is not going to be a little bit more
complex and that is adding sound effects
so let's do that in the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to add some
sound effects for our game okay so
previously we already added some really
nice music now let's add a whole bunch
of sound effects in the project files if
we go inside the assets over here we've
got all kinds of sound effects recently
I heard the really nice sound designer
to make all of these and I think they
all sound really great so let's add them
to our game now when it comes to sound
effects there are two main ways to play
a sound one is just like we did for the
music so we can create a game object at
the audio Source component and play it
that's one approach but that basically
requires pre-preparing the sound objects
so there is another simpler way that
just requires one line of code so let's
begin by making a Sound Manager game
object so a new empty game object for
The Sound Manager let's reset the
transform now let's make our script so
let's go in the scripts folder create a
brand new c-sharp script for The Sound
Manager let's attach the script and open
okay so now here let's make a function
to play Simple sound so let's do a
private void just call it play sound and
over here the way we play sound through
code is actually super simple we just go
inside the audio Source class
and in here there's a static function
play clip at point this as you can see
it takes an audio clip a vector 3 for
the position and finally a volume so
basically it won't play that sound on
that position by default TNT already has
3D sound so if you play the sound on the
left or the right side of the camera it
won't play in the correct place also for
the volume the further away it is from
the camera the lower it will be and if
we don't want the 3D sound we can just
play it directly on top of the camera
position okay so in this function let's
receive our arguments so for the audio
clip
it's going to be our audio clip
then let's receive the vector 340
position and let's also receive an
optional one for the volume
let's just default this to 1f okay so
here we just pass this in into our
function so the position and the volume
okay great so now let's call this nice
function and for example let's start
with a simple one so let's start with
the delivery sounds so over here on the
delivery manager script down here we
have the logic for delivering a recipe
and over here we know when we completed
a successful recipe or when we failed
and the player delivered a wrong recipe
so this is where we want to play some
sounds and again here we have yet
another very important clean code
question
we could definitely call the play sound
function directly from here that would
work but of course that would make this
class tightly coupled with The Sound
Manager for a simple game on this scale
that approach can work just play sounds
directly from the logic code however
again to make things properly we should
really separate the logic from the sound
just like we separated in logic from the
visuals so instead let's not call the
sound directly from here instead let's
make two more events
so let's make one on recipe success
another one on recipe failed
okay so now let's fire off these events
so over here we have the success so on
recipe success and if we get down here
then we have a fail so on recipe fail
okay great we have two events now back
here on The Sound Manager we can just
listen to those so let's do a start go
into the delivering manager access the
instance and listen to the on success
and on failed events let's listen to
that one delivery manager instance on
recipe film listen to both of these
again let's write some good clean codes
so let's rename this one instead of
instance let's put it delivery manager
and same thing on this one also name it
correctly delivery menu
okay great so now when you have this we
want to call and play sound
and now I want to pass in a reference to
the recipe film sound so technically one
approach would be appear to add a
serialized film for an audio clip that
would work but since we've already done
that so many times in this course here
let's use a different approach that I
also like to use
let's create a scriptable object to home
the reference to all of our sounds so
similar to how we Define the script
object on all of our recipes let's just
comment this out just make sure the code
compounds okay great so back here in the
editor let's make a new script more
object type so let's create a brand new
c-sharp script
for the audio clip refs script long
object now here let's make this a simple
scriptable object with a create asset
menu
okay so now for the fields if we
unlocking the S over here the audio
design that I hired actually made
several variations for each sound so
we've got multiple chops multiple
delivery fails and so on
so back in the code here instead of
storing a reference for a single audio
clip let's store an array for all of
them so we have the chop then we have on
the other Solutions and all of the
references
so there's a job there's the delivery
fail
then we have delivery success then we
have footsteps
then the object drop then the object
pickup
then we have the stove Sizzle although
this one is just one then we have the
trash and finally we have the warning
alright so these are all of the sound
references we're going to use back in
the editor let's just create the object
so on the script mode objects let's
create a brand new one let's make it of
audio clip per episode
just name it audio clip refs so
and over here let's just write the
references so let's use that quick ENT
tip in order to unlock the inspector now
I can select all the chops and drag them
all the delivery fails drag them it's
only re-success drag it then for all of
the footsteps after that are all of the
object drops then the pickups then we
have the sizzle which is just one
finally we have the trash and the
warning okay those are all the
references so our script on object now
has all of the data we need let's unlock
the inspector okay and back in the code
here on The Sound Manager let's make
another version of this function so
let's make one play sound except instead
of receiving an audio clip it receives
an array of audio clips
then basically we just call the other
function so we call the other place on
function and pass in an audio clip from
this array so let's actually rename this
so audio clip array
and let's pass in an audio clip from
here so do a simple random.range
between 0 and the array down length
pressing the position and the volume
okay so just like this now we need is a
reference to our suitable object so it's
generalized film private of the audio
clip refs SL
okay we have this then here in the
editor and let's just assign the
reference so the audio clip refs okay
great and over here when we have the
recipe failed let's go into the audio
clip refs
and let's pick up this one instant
delivery fail
and then the other one is going to be
delivery success
for the position let's just default to
the camera dot main transform that
position
so like this it sounds like exactly on
top of the camera okay so let's test and
see if it all works okay so here we are
and let's do a wrong delivery now quick
warning if you're following along or if
you're just watching the video this
sound will probably be way too loud but
let's test
so if I just pick up the plate and I
just deliver an empty plate yep there
you go there's the sound
and now if I deliver a correct one so
someone wants a salad so let's cut a
nice salad
chop that chop this pick up the plate
pick up that one and that one don't be
the correct salad
any of that I go with those were all
right great so the sound effects work
they played perfectly but they're a bit
too loud basically that's because these
sounds were designed to be played in the
world rather than on top of the camera
so when we play the sound let's actually
play it on the position of the delivery
counter
here is the delivery counter script and
based on our design we're only going to
have a single military counter so we can
just make this a Singleton
so as usual public static of type on
Livery counter call it instance where
they probably get and a private set
then on privatoid awake
let's just set the instance equals this
okay so over here on The Sound Manager
we can just grab delivery counter
delivery counter and we just go into
Library counter and grab the static
instance
and then for the sound position we can
just go into delivery counter access the
transform that position
okay so just like this on that one and
on this one
okay so it says now it shouldn't be as
loud
okay so here we are and let's do a wrong
delivery any hope it does work
now let's be successful delivery so
let's make a nice cheeseburger so grab
some cheese slice it grab plate just
need some bread
and delivered any of there you go it
worked all right awesome
okay so this is really it this is how
we're going to play our simple sounds
now there are some that are going to
require more logic like the footstep
sounds and the stove Sizzle but first
let's begin by adding the simple ones
so let's begin with the chop sounds this
is super simple we just need to go over
here onto the cutting counter and
actually we already have the uncut event
that we made previously this was used to
spawn the visual so we can also use it
to spawn these sounds
however there's actually one difference
we're going to have multiple cutting
counters and this one as you can see
this one is not a static event meaning
each different counter is going to have
each list of listeners and we really
don't want to have to subscribe to every
single one of the counters individually
so what we can do is instead of making
it a regular event that belongs to each
instance of a cut encounter we can make
a static event which won't belong to the
entire class but we still want to leave
this one just for the visual so let's do
another one a public static event event
handler
and let's call it on any cut basically
for any static events that belong to any
object type I like to add the keyword
any we're going to fire this event when
any cutting counter is going to trigger
a cut action so where we fire this event
is exactly the same thing so over here
we've got the uncut and let's do the
exact same thing so on any cut with this
an event R is not empty okay so we have
our nice static event and over here on
The Sound Manager let's listen to it so
let's go into the cutting counter again
we're going to access through the class
name and let's listen to the on any cut
event and over here let's just play the
sound so let's play the sound let's go
inside the audio play prefsl and let's
grab the chop sound then for the
position
we want to know who fired this event and
by following the c-sharp standard over
here we already have the object sender
so we know this was the object that
fired this event and we know this is
going to be of type cutting counter so
we can just get cutting counter cutting
counter and we just grab the sender as a
cutting counter
okay so we have this and then over here
very simple access transform that
position
okay that's it great
that won't play The Cutting sound on
that position on that cutting counter
okay great now let's handle the player
picking up something and for that let's
go over here onto the player class and
the way we set up the kitchen object
parent system is actually already
perfect for this
down here we have a function so if we
scroll down Yep this function set
kitchen object this one is called
whenever the player receives a kitchen
object which means really when the
player picks up something so if this
kitchen object is not known then that
means the player picked up something so
let's do that
so up here and let's make the event
so a public event event handler
call it on pick something
and then down here just to be test so if
the kitchen object is not known so if
the player did pick up something then
let's just fire off this event so just
view our usual invoke with this an event
RX rmt
okay so that's great
then on the sound management let's just
listen to it so let's go into the player
Quest let's access these static instance
and let's listen to the on picked up
something event and again let's rename
this to a proper name so player on pick
something
and over here let's just play the sound
and for the sound go into the refs and
grab in this case the object pickup
and for the position let's just go
player
dot instance and gravity transform that
position
okay that's it next for item dropping
now we can only drop items on a counter
so over here we have the base counter
class and again we have the same thing
so we have the set kitchen object and
again the same thing as with the cutting
counter we don't want to be required to
listen to every single counter we just
want to listen to one event so let's
make it up here so if I'm like static
event of type event handler
and let's name it on any object placed
here
and then down here when we have the set
kitchen object we do the usual if
kitchen object is not known if so then
let's fire off this event
okay great
and on the song Imagine let's listen so
go into the base counter on any object
placed here when that happens play the
sound then let's go into the other top
prefs and this one is the object drop so
that one and for the position let's do
the same thing we did so we cast the
base counter equals the sender as a base
counter and then we go into the base
counter and let's grab the transformed
up position okay so we just need one
more special counter type
here we have the trash counter and this
one it never really changes the parent
it just destroys the object it's over
here on the trash counter itself let's
fire off an event but again let's make
it static even though we're only going
to have one trash but make it Saturday
just to be able to support multiple so
public static event
Handler
on any object trashed
and then over here just fire off this
event
so invoke with this and eventar is not
empty okay
so now if we go into The Sound Manager
and over here once again the trash
counter on any not the on any object
place but on any object trashed
and on this one let's do pretty much
exactly the same thing so let's copy
this the sound is going to be the trash
sound instead of a bass counter
we could just cast it to a base counter
but let's make it proper so let's make a
trash counter as a trash counter and
this is a trash counter okay great
that's it so these are all of our basic
simple sounds as you can see all the
logic is super simple so let's test and
see if it all works
okay so first of all let's pick up an
object so if I go into a container and I
pick it up and if there you go there's
the sound now if I drop it somewhere and
if there's a sound now for the trash
pick it up drop it on the trash anyhow
there's the trash down okay great
then also let's check out the cutting so
if I pick up some cheese drop it there
and cut and if there go got a really
nice cutting sound okay so far so good
now let's handle the more complex ones
starting off with the stove for this one
the sound is meant to be on looping but
only when the sub is on so we don't want
to just play once but play and stop
playing depending on the state of the
stove
so for this one instead of spawning the
sound through code let's actually spawn
it on the object itself so let's go
inside the stove object let's go on the
stove counter and open up the prefab and
inside this prefab let's create a brand
new empty game object name it sound
let's reset transform make sure it's on
zero zero zero okay great now let's add
an audio Source component
and for the auto clip let's use the pan
sizzle let's make sure to not talk on
play on awake but we do want it to Loop
and let's also make it a 3D sound
okay so that's the basic setup Now to
control this let's make a script so
let's go into our scripts folder and
let's create a brand new c-sharp script
come with the stove counter sound
let's attach the script over here and
let's open it
so now here first let's grab the audio
Source component so we've got a private
audio source for the audio source and
just go on awake and audio Source
sequence get component of type audio
Source okay
then we're also going to need a
reference to the stove counter so let's
uh appear a centralized film private
of type stove counter for the stove
counter
then back in the editor let's drag that
reference all right
now on the stove counter over here we
already have the states and we have the
on-site change event again the same one
that we use to modify the visual so on
the sound lets you pretty much examine
the same thing
over here let's do a private void start
and on certain let's go into the stove
counter and listen to the on stay
changed event
and basically when this changes we want
to check if it's frying or fried if so
then we want to play the sound if no
then we don't want to play it so let's
define a ball call it play sound and
we're going to play if the state equals
we are frying or the state equals that
it is currently fried and about to burn
Okay then if we have a play sound
then let's go into the audio source and
comp play
and if not then let's go into audio
source and call pause
all right so that's it pretty simple
let's just make sure to save our prefab
go back outside and let's start on play
and okay four stars there's no sound
playing now if I pick up some meat and I
drop it on there
and if there go there's a sizzling sound
and continues going and now it is still
sizzling but if it burns it should stop
so if I go
and if there go the sizzling soundstomp
all right awesome so let's take this one
out let's actually trash it now let's
pick up another one let it cook
and once let's go pick it up and there
you go the sound of the Stomp all right
awesome
so we just have one more final sound
remaining that's the footsteps
by the way the warning sound is going to
be added during the Polish lecture
for the footsteps we want very much the
same thing that we did on the stove so
we're going to want a script to handle
that logic
but this time we don't need an audio
Source on the player we're going to use
the same play Method as the other ones
let's just make a script to run the
sounds so let's make a new c-sharp
script for the player sounds
let's go into the player game object and
attach the sound okay so here let's
first grab the player reference
so private player player and on private
way the way let's get the component of
type player and assign it to the player
okay
then for the footsteps basically we want
to play them every certain amount of
time so let's do appear a private Cloud
for the footstep timer another one for
the footstep tower Max and let's say you
want to play say 10 times per second
then we do a basic update and on update
footstep timer countdown by time.com
time and if the footstep timer is under
zero
then let's reset it so set it to the
maximum
and it's in here that we're going to
play the sound so now here we have two
options we can fire an event here and we
can listen to it on The Sound Manager so
exactly the same thing that we've been
doing previously or we can just trigger
the sound directly from here doing that
will mean that this class is tightly
coupled with The Sound Manager usually
we want to avoid tight couplings however
in this case the player sounds class
this one is really only meant to exist
alongside the sound manager so in this
case it's perfectly fine to totally
coupon them so let's play the sound
directly from here which means we need a
reference to The Sound Manager we can
make a serialized field or just make
this a Singleton so let's do that
so a public static type Sound Manager
name it instance where they probably get
any private set
then on private void awake
we just set the instance equals this
okay
so then over here we can just access it
so just go into the sound manager access
the instance and we call play sound
which we actually need to make public
however this function also takes a
reference to the audio clip array
so that means we need a reference to the
audio clips so again we have multiple
options we could add over here on the
player sounds at a serialized film for
the footstep sounds or we can just make
a specialized function over here on The
Sound Manager both options can work just
fine let's go with the second one just
to be different so just make here a
public void play
footstep sound
we're just going to receive a vector 3
for the position
and then we just call play sound let's
go into the audio clip refs ASL and
let's pick up the footsteps and play it
on this position
and let's also receive the volume
just appear a fault for the volume
okay so that's right now we just need to
call this function
it's over here on the player instead of
calling play sound let's go on the other
one play the footstep sound
then for the position that's the player
transformed that position and for the
volume I just exposed the volume just in
case you want to make the footsteps a
bit more sound or not
but for now let's begin with one F and
then see if that's waiting around as
usual instead of using magic numbers
let's define a fluid for the volume put
it at 1f and over here use the volume
okay great however you might be noticing
an obvious issue here right now this is
going to play non-stop obviously we
don't want to do that we only want to
play footstep sounds if the player is
actually moving so this pre-semble we
just need to ask the player if it is
moving
and we already did that so player is
walking so if the player is walking then
you play The Sounds if not we don't okay
that's it so let's test so here we are
and if I'm standing still there's no
footsteps okay that's great and as soon
as I move yep there you go we got some
nice WhatsApp sounds
all right great so with all that we
added all of our sounds
now here note how we mostly use this
method of going into the audio source
and using the play clip at Point
function this one is great because it is
so simple but it does have limitations
specifically with regards to all of the
options if we look on the audio Source
component here we have all these options
so you can use an output use an audio
mixer like we saw in the previous
lecture we can play around priority play
around the pitch make it 2D or 3D play
around over here with how the sound
falls off so tons and tons of options
that you can't really access if you use
that simple function so one approach if
you need these options you could make
each sound a prefab so make a prefab for
each different audio clip and then
instead of calling that function you
would simply instantiate that prefab to
spawn that audio so if you have lots of
options depending on how complex you
want your sound to be
but for a simple game and for simple
sounds this one line of code is super
simple
alright so here we have added sound
effects to our game that component with
the music that we had previously already
makes everything sound so much more
alive it's really starting to look like
a proper game
the one thing we still don't have is
some kind of game start and game and
scenario so let's have that in the next
lecture
hello and welcome I'm your code Maki in
this lecture let's add a simple and
beginning state to our game so right now
we can play the game of the mechanics
everything works perfectly and it's all
been implemented however in the
beginning of the game it just starts
right away as it loads there's no start
no countdown no time for the player to
get ready
someone sort that out with a simple
countdown let's begin by making a
general game manager script to handle
all of our general game States so let's
create a brand new c-sharp script
and now here you could use the name game
manager so you could use this name
however for some reason yantian likes uh
this custom icon when a script is named
exactly game manager personally I don't
like this I don't want it to be a
different icon I want this script to
look and behave just like any other one
of my scripts so personally I don't like
this but if it doesn't bother you then
go ahead use it doesn't really change
anything just a visual but in my case I
prefer to give it a different name so
sometimes I call it game Handler or
other times just something related to
this game like for example the kitchen
game manager and just like that it won't
have that custom icon just need to go
inside and rename this to Kitchen game
manager okay save the script and all
right now let's make a game object to
run it so a new game object with the
same name let's attach the kitchen game
manager and reset transform okay let's
go now here we're going to Define all of
the various game states that our game
can be in so for that let's define an
enum so a simple enum call it state
and for the various States let's say we
are first of all waiting to start then
we are on countdown to start then the
game is playing and then we have a game
over okay so these are our states let's
do a private void awake and on the
waiting list of the state so we need to
store a state for our state
and on a week we set the state equals
and let's begin on waiting to start by
the way the point with this waiting to
start say it will also be very important
in the next video covering multiplayer
basically we're going to wait until
everyone is connected before we start
the actual countdown but over here for
now we're just going to wait a little
bit on the waiting to start then we're
going to trigger the countdown and then
after some time trigger the game playing
state so pretty much all of these states
are going to be time based so let's make
a simple timer so a private float for
the waiting to start timer let's begin
on something like 1f so we just wait for
one second then let's make a private
void update and let's make a state
machine just like we've done previously
so do a switch on our state
in case we are on state DOT waiting to
start
if so then let's go into the waiting to
start timer count it down by time dot
Delta time
then if the waiting to start timer if it
is under zero if so then let's move into
the state equal state DOT let's go into
the countdown to start okay so that's it
and the other states are going to be
pretty much exactly the same so let's
just copy this so we have the winning
start and the countdown to start then we
have the game playing and finally we
have the game over and that one doesn't
have anything so just like this like I
said we could reuse the same timer but
let's write our code nice and proper so
let's make different timers for each so
let's make three timers so we're going
to have the countdown to start timer
so countdown
for this one let's see Fallen two three
so we're going to wait three seconds
before we start and then the game
playing timer
and for this one let's put it something
short just for testing so let's put it
just test and then down here let's just
use them so on the countdown let's count
down this timer on the game playing
count down this timer when the countdown
ends we go into game playing and when
the game playing ends we go into game
over alright so that's our super basic
state machine just a bunch of timers
super simple
let's do a quick look just to see so
over here just say debug.log and let's
just print out the current state
okay so just like this let's test and
yep right away we are waiting to start
after one second going to countdown then
after three seconds go into game playing
and now if we wait for 10 seconds
after 10 seconds we should be able to
see just a little bit and yep there you
go we've got our game over okay great
all the logic is working although we
actually didn't change anything
technically the game right now is on a
game over but everything still works the
same experience only so I can still play
I can still do everything
so let's sort them when we are in any
state other than the game playing State
we don't want the player to be able to
interact with anything we want to leave
it movement because that's usually nice
and fun but we don't want it to be able
to interact pickup objects or do
anything so let's do that basically over
here on the game manager let's just
expose the function so public pool let's
call this is game playing
then over here pretty simple just return
if the state equals state DOT gameplay
that's it
so now we can go into the player script
so over here on the player script let's
go down into the interaction function so
over here we've got the interact
alternate and the interact and on both
of these basically let's just ask if the
game is in the game playing state if so
we want to interact but if not then we
don't want to do anything so to access
the game manager we could add a pure
serialized field or as usual let's just
make a nice Singleton so pure public
static of type kitchen game manager the
instance make a public get and a private
set
then down here on awake let's set the
instance equals this okay so now over
here on the player let's just go into
the kitchen game manager access the
instance and test is game playing
and we're going to do an if if the game
is not playing so if we are not playing
we want to stop this so let's just
return so if the game is not playing the
code is going to stop executing here and
same thing on the interaction so just
like that we won't be able to interact
with anything once we are not in the
game playing State okay so here we are
waiting to start nope I cannot pick up
anything count down to start nope I
can't and as soon as we go into game
playing yep now I can't interact so I
can cut a bunch of things
and as soon as it goes into game
overstate
there you go currently in game over
state so now if I try and interact nope
can't do it okay awesome everything
works perfectly
so in terms of logic this is really it
there's nothing else we need to do
but of course right now the player would
have no clue as to why sometimes they
can grab and sometimes they can't so
let's add a proper visual
first let's add a visual to the starting
countdown
so let's do that as a canvas element so
let's go inside our canvas create an
empty game object name this the game
start countdown UI let's press F to
focus on the object press 2 to turn this
into 2D okay so let's see and over here
we really just need a text object so
let's leave this one anchored on the
center let's put the width and height
both on zero we don't need that and then
let's go inside create a new text object
call this the countdown text and then
inside let's just put a number so just a
three
let's put the width and height both on
zero then down here let's put it in bond
on a really big font size so let's say
something like 250 okay really nice big
number then let's also put it centered
and down the middle okay that's right
we've got our nice big countdown number
also by the way when using text mesh Pro
we can easily add a whole bunch of
effects if we'll look down here we have
the default text mesh Pro material and
over here we can add an outline another
line and so on so that's really great
however there's one very very crucial
thing when you want to add some effects
always remember that the effects are
being applied to the material meaning
any text objects that are sharing this
material all of them won't modify so for
the most part usually you don't want to
modify the default material if you do
then everything using this default
material will change like for example I
want to add a nice thick outline to this
one but over here I've got some regular
text that is also using the default
material so if I now add an upline and I
increase the thickness and if there you
go those also got an upline as well as
this and if I wanted download make it
quite a lot bigger there you go all of
them modify because all of them are
sharing the same material so usually you
don't want to modify the default
material if you want to add some kind of
special effects always make sure to
create a brand new material beforehand
so over here let's remove the outline
put it back on the dilation and let's go
up here to create the brand new material
first we need to find our phones over
here on the font asset we can just click
on it and we can see it over here
highlighted on the project window so
it's inside the text mesh profiler the
resources phones and so on so here is
the default font and inside this one is
the font that we're using now in this
font there's a nice little error icon
and inside we can see the default
material so let's duplicate this
material although it's important make
sure you duplicate the material and not
the font so with this material selected
I'm going to press Ctrl D and there you
go it duplicates the material and over
here let's give it some name so let's
say this is material that I want to use
for the start countdown
so there you go just like this also one
very very important thing the name of
the material needs to include the font
name otherwise it won't show up for
example if I get rid of this the only
version Sans SDF if I name the material
just like this and now I'll look over
here on the countdown text look on text
mesh Pro here is the drop down menu for
selecting material and over here note
how that one does not show up so it is
extremely important in order for it to
show up in here it needs to have the
same starting name so over here if I
rename this material put Liberation
sends SDF and then the name and now back
in here now look and yep now I do see my
material okay so that's great and over
here we can add what kind of effects we
want and it will only affect this one
and not any others okay so for this one
let's add a nice outline and let's make
some nice thick numbers so over here on
donation let's handle it by quite a
little bit
then for the outline color let's put it
maybe on a blue something a bit like
this okay let's push it back just a
little bit okay I think that looks
pretty good now if you want you could
add even more effect to this I made
another video covering how to use custom
Textures in your font doing that you can
just import the font directly into
Photoshop and edit it with all kinds of
effects for example in that method is
example what I used in my game hypernite
make the head counter look really nice I
also have a tutorial specifically on
that so if you want even more custom
text definitely go ahead and watch those
videos but anyways here we have our
countdown text looking pretty nice now
the number itself will be written
through code so let's do that let's go
into our scripts into our UI folder
create a brand new c-sharp script for
the game start countdown UI okay and
let's select the parent object and
attach the script now here first thing
we need is a reference to that text
object so let's add a serialized film
private and again remember what I
mentioned a couple of night years ago
with regards to the types so we want
xmesh Pro U GUI we want this one so it's
going to be our countdown text and now
for updating this text basically we just
need to know the game state so we need
to know when the countdown should show
up and as usual let's use some nice
events so over here on the kitchen game
manager let's fire an event whenever the
state changes
so a public event event handler
let's call it on stay changed
okay just like this no need for the
arguments so let's go down here whenever
the state changes and let's just invoke
this event so invoke this eventar is
that empty
so we change in there change in there
and change down there okay that's it so
now over here on the game start
countdown let's see we've probably start
and on start let's go into the kitchen
game manager access the instance listen
to the on say changed event as usual
write some nice clean codes so let's
rename this the kitchen game manager
so when they say changes we basically
want to show this if we are on the
countdown to start so let's go here to
the kitchen game manager and let's make
another function so public boom is
countdown to start active
and we just return if the state
equals the state DOT countdown to start
okay so that's a nice simple function
and on the UI script if the kitchen game
manager
if this one dot is countdown to start
active
if so then let's show if not then let's
hide so else
let's do a hide
so let's make these functions so proud
void show
and a private void hide and on this
let's just do the usual thing so game
objects and active into true or over
here set it into false and on start
right after we subscribe to the event
let's also hide it by default okay so
that's the basic logic for showing or
hiding it and now for the timer text
technically over here once inside the
countdown to start we could fire an
event on every single update that would
work but it would have some unnecessary
overhead
so instead another option is just make a
function to expose it so let's go here
make a public returning float get the
countdown to start timer
and we just return the countdown to
start timer very simple so then over
here on the UI script we can just make a
regular proud void update and on update
go into the countdown text in order to
set the text
and let's go into the kitchen game
manager and let's get the countdown to
start timer and just do A2 string okay
so that's it super simple so on update
we're going to constantly update the
timer so let's see if this works
back here in the editor let's just make
sure to drag the countdown text
reference and let's hit on play and okay
waiting to start and after a bit yep
there you go there's the number it's
currently on countdown and now the game
is playing so the show and high did work
on the number seem quite a bit odd
that's because over here on the settings
we have wrapping enamel so now I just
quickly disable this and let's test
again
sir we are waiting to start and there
you go there's our countdown three two
one zero and there you go gameplay
okay so it did work now of course as it
comes to the visuals it depends on what
you want
for example if you want to limit the
decimals you can use over here the two
string this one can include all kinds of
string formats for example for
displaying just two decimal places you
can add the string format F2
let's see what this looks like waiting
for the countdown and there you go now
it does Show with two decimals okay so
this is one approach alternatively
another format you can use is
number sign Point number number and
let's see this one
and yep there you go now it looks like
this
so as you can see there's lots of things
you can play around with when it comes
to the two string formats but in our
case I don't really want any decimals I
really just want to see whole numbers so
for that let's just seal out this number
so in mathf.cl
let's see on this one out and then just
do a two string okay let's see
so wait a bit and we got three two and
one and there you go the game is winning
alright awesome so here we have our
waiting to start and the countdown to
start all of that logic is working
perfectly now the next thing we need is
to handle the game end so let's do that
in the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to handle
the game over State now for the game
over State this is obviously a game
design question for example you can make
it so that each recipe had a timer
attached to it and the player had to
create that recipe within time limit
then if they failed enough recipes you
could trigger some kind of game over or
for something more simple let's just do
exactly what we did for the game start
let's just do a basic countdown timer
after the game is over let's pop up a
game over window and show how many
recipes the players delivered so let's
do that let's go into our canvas and
inside make an empty game object call it
the game over UI then over here let's
stretch it to occupy the entire parent
like this now inside let's begin by
making a UI image this is going to be
the background let's put it in black
with just a little bit of transparency
and let's also stretches to occupy the
entire thing
so just like this then let's make some
text so let's make a new UI text click
the game over text
and let's say just game over
let's set the width and height both at
zero then down here disable wrapping put
it centered let's put it pretty big so
maybe 135 put it a little bit higher
then for some more text let's duplicate
this let's call this the enlay bone
recipes delivered text and over here we
just say recipes
delivered
let's put this one a bit lower and quite
a bit smaller
say on 50 okay and also on this one
let's put it in bold then change the
color a little bit okay next let's make
yet another text this one is going to be
for the final number so let's call this
recipes don't deliver text
and this one is just going to have
whatever number of recipes we've
delivered and let's put it over here and
quite a bit bigger okay so this is the
game over window that we want also a
quick note like I mentioned previously
the Sorting order over here on the UI is
based on the ordering the hierarchy so
for the game over we want this one to
show up on top of everything else so
make sure the game over it is the last
one over here on the UI make sure it is
the bottom most child on the canvas okay
now let's make a game object to run this
so let's create a brand new script game
over UI let's go into the object wait
for the compilation and let's drag the
script okay now here the only reference
that we need is just for the text so
let's just make a serialized film of
type text mesh Pro ugly for the recipes
delivered text here in the editor let's
just drag the reference okay now let's
make some show and height functions and
also show it just on the game over so
really we're going to do the exact same
thing that we did over here on the game
start countdown so let's actually copy
exactly this let's go into game over UI
pass the exact same thing Okay so we've
got the show and hide functions we test
and then over here on the state change
instead of showing this one on the
countdown we want to show it on the game
over
so let's go over here and just make
another function so public goal is game
over and we just return if the state
equals the state that game over okay
that's a function
so over here if we are is State game
over
if so then we show if not we hide okay
the last thing we need is just for the
text so this is going to be the recipes
only vertex so we're going to set this
to something
which really means that we just need to
keep track of all of the recipes that
have been delivered so until here onto
the delivery manager script and let's
just keep track so just a simple end so
a private end for the successful recipes
amount
and then whenever we have a recipe
success so let's go here into our
delivery recipe function whenever we
have a success let's just increase this
by one okay so that's it now we just
need a function to expose this so we
probably can't for the get the
successful recipes amount and just
return the successful recipes amount
okay so finally back here on the game
over UI let's just print it so go into
the delivery manager xsc static instance
and get the successful recipes amount
and of course we need the string so to
string except for this one this is never
going to change after the game is
already over so let's not do this on
update that would be quite wasteful so
let's just do it up here so as soon as
we have the game over we show we print
the recipes and that's it okay so let's
test so here we are waiting for the
timer and let's wait and just wait five
seconds for it to finish and we should
see a zero so let's just make sure that
works so after a little bit of time yep
there you go we've got recipes all over
zero okay
now back here again let's try and
deliver some recipes now so let's try
and make a cheeseburger try it only for
that
cut this one pick up this one
pick it up put it in there
and okay quickly all right good and
there you go we've got a one all right
Awesome everything worked perfectly
let's just add one more final element
right now we cannot see what is the time
left in the game so let's add a nice
lock element
so over here on the canvas let's make
another empty game object
let's name this the game playing clock
UI
and let's also put it behind the game
over UI so let's put it above on the
hierarchy so that it shows up behind in
order to be able to see what we're doing
let's also just hide the game over UI
but only here on scene view so let's
click on the I icon okay so here we have
our window let's just anchor it on the
upper right corner so let's put it
somewhere in there then inside let's
create a new UI image come with the
background for the Sprite
let's go with these circles right so
let's click on the eye icon to show all
the default Sprites and let's use the
one included with the circle
so you have this one let's also add a
nice little outline so let's put it on 2
2 with phone Alpha and let's also add a
nice shadow just nice visual so on five
minus five like that and for the color
let's also put it some kind of dark gray
okay so this is our background now let's
duplicate this so Ctrl d
and let's rename this one the timer
image and for this one let's give it a
different color so maybe something like
a blue so something like this okay and
now over here on the image type instead
of simple let's go with filmed let's
choose Radeon 360. okay great and now
over here we can play around the film
Mount and this will be our timer then
you can set it up however you want for
me I'm going to choose to start from the
top so as it starts the time we're going
to countdown Until the End okay so
that's great now let's make the script
to run this so let's create the brand
new c-sharp script same thing the game
playing clock UI and over here let's
just attach a script so now all we need
is reference to our image
so let's make a serialized field
private image let's make sure to use
this one the image inside Unity
engine.ui this is going to be our timer
image okay like this back here in the
editor let's drag the reference all
right now that we have this we need to
ask the game manager to get the timer
normalized so let's go over here onto
the kitchen game manager and let's make
a function to return just that so a
public float let's call it get plane
timer normalized or game point timer
actually just to match the state
so get this one and up here we have the
playing timer we just need to define a
maximum in order to be able to calculate
the normalized value so let's duplicate
this call it the game timer Max and set
this one to 10 and this one leave it
like this
and down here when we change the timer
when we go into game pointing let's set
this one equals this.mex that way we
only Define the timer just up here okay
so with that now down here we can do the
compilation so we can return the game
playing timer divided by the game
playing timer Max
except just like this going to be
inverted because for the game playing
timer we're counting down instead of
counting up so all we need to do is our
simple just reverses so just one minus
just like this okay great so we have
this function and then over here on the
clock just go private void update and on
update let's go into the kitchen game
manager the instance let's get that and
we're going to use that on the timer
image.fillment okay that's it super
simple let's see okay here we are on the
waiting to start all right waiting and
as soon as we start if there you go
there's the timer going and we can see
it constantly increasing
so it's at the halfway point
and just a little bit more
and there you go yep we've got the time
over and we have our game over
all right awesome so over here we
implemented a really nice game over
Saint we have a playing timer with an
icui element and when it ends we get a
game over window showing you a bunch of
stats now with this working the next
task is to have some kind of main menu
so we can play again after the game is
done so let's do that in the next
lecture
hello and welcome I'm your code monkey
in this lecture we're going to make a
super simple main menu and downloading
system okay so every game needs a main
menu so let's build one let's begin by
making the scene so let's go into our
scenes and create a brand new scene call
this the main menu scene
and okay here's our default scene now
over here for the most part you really
just want some basic buttons so nothing
too special so let's create a brand new
UI canvas and let's set up as usual so
screen space overlay yep then let's go
with scale with screen size 1920 by 1080
and let's match with the height okay so
there's our canvas now inside let's make
an empty game object name this the main
menu UI let's stretch it to occupy the
entire thing so zero zero on everything
okay
now inside let's create a brand new UI
button let's name this the play button
then inside for the text let's say play
Let's size the button to be quite a bit
bigger so let's say 450 by 150 and on
the text itself let's put it in bold
only font size quite a bit bigger let's
say 70 then let's also change the color
let's put the text in White and the play
button over here the normal color for
the image let's put it on a dark gray
then also over here on the button
background let's add a nice outline
let's put it on foam black say something
like three three then let's make a
Shadow and for this one five minus five
okay so that's our basic button let's
just anchor the button so choose the
play button let's anchor it on the lower
left corner and let's push it just a bit
like this okay pre-symbal now let's
duplicate this one push it a bit lower
let's also make it just a tiny bit
smaller so just 120 this is going to be
our quit button so let's rename this to
the quit button and inside for the text
just say quit and put a bit more on the
font size okay like this okay so we have
the two basic buttons that we need now
let's make this crypto random so let's
make script with the same name so main
menu UI so let's go into our script UI
folder create new script for the main
menu UI let's attach the script and open
okay so now here let's begin by making
serialized films for our buttons so it's
always film private of type button
inside Unity engine.ei this is the play
button and then we have another one for
the quit button okay back in the editor
let's drag the references so that's the
only button and the quit button okay now
here in the code let's add some
listeners to these buttons and let's do
a private way to wake and on the way
let's go into the play button and going
to the on click event so the event when
the player clicks on the button and
let's add in listener and now we pass in
The Listener now for here to do this we
can add a function so we can make a
private void Play Click we can define a
function kind of like this and over here
add it as The Listener so that's one
approach or another alternative that
personally I like to use is to use what
is called a Lambda expression so instead
of defining an external function down
here we just go up here and directly
with the finding Lambda so we open
parameters to display the parameters for
the function which in this case we have
none so just open and close then we do a
nice little arrow and then we have
whatever we want to be our clear code so
both the code that I have here and one
that I have here both of these are
exactly the same thing this one is
called the unlimited expression which is
also a type of delegate definitely go
ahead and watch my video on C sharp
delicates in detail it's yet another
extremely powerful c-sharp feature I
find them especially useful especially
over here to setting the click listeners
there's no need to make another function
just use a Lambda expression that's it
so over here I'm going to use that
instead of an external function Okay so
we've got the play and then let's also
listen to the equip so on the quit
button the exact same thing okay now
first on the equip button it's actually
very simple we just go into application
and we call the quit function this will
quit the game that's it very similar
although one note if we actually test it
like this so here is the game playing
and if I click on quit and nope nothing
happens now the logic is actually
working we can see visually that the
button is changing state so we are
indeed capturing clicks however when the
game is running inside the editor
calling that function the
application.quit doesn't do anything but
if this were a phone bill then clicking
on that would indeed close their game
okay so now for the play button for this
one it's also very simple we just need
to go inside the scene manager which is
inside the unity engine.scene management
we just need to go inside of this one
and we call load scene
this function will load with a certain
scene and for loading we can either use
the scene film index or we can use the
scene name like I've mentioned several
times string names are horrible although
in this case the alternative using an
INT is also not very good just a number
is very hard to read the code and being
able to know what scene this is loading
so there's one better approach that I
prefer to use but first over here let's
just use the index just for testing so
we're going to load the scene on index
one so just like this and then here in
the editor and let's go into file and
build settings
and over here we see the scenes in our
build right now we just have the game
scene so let's just add our scene so
let's drag the main medicine and drag it
on there and also let's make sure it's
on the top of the list basically the
first scene is the one that won't be
unloaded as soon as the game starts so
let's try it right up top just like that
then over here on the right we see the
index so by loading the scene on the
next one we're going to be unloading the
game scene okay so with the slits test
so here we are and if I click on playing
and if there you go it doesn't load the
main scene okay great everything is
working so this is the seamless way to
do scene loading however this method
does have one issue it's not super
noticeable when a game of this scale
because it loads pretty quickly
but like this note how when we click on
play there you go everything freezes for
a little bit while the game is loading
like I mentioned in this case the freeze
is so small so not necessarily an issue
but if the game was much more complex
then the player would be staring at a
frozen main menu for perhaps 30 seconds
that would not be good one way to avoid
that is actually very simple basically
it's what I already covered in detail in
the scene loading video that video was
made quite a while ago but it's still
very much up to date here we're going to
do pretty much the same thing so we
first create the scene just empty just
saying loading and then from that scene
we load the final scene that way the
game stays Frozen on a scene that says
loading which is much more clear to the
player so let's do that first let's make
our scene so inside our scenes folder
let's create a brand new scene call this
the unloading scene okay let's go inside
and on this one we want this one to be
fully black so let's go into the main
camera and scroll down over here under
environment and instead of rendering the
Skybox for the background let's go with
a solid color and let's go with phone
black okay there's our black main camera
now let's make a canvas so a new UI
canvas let's set up as usual so scale
with screen size 1920 by 1080 and match
with the height okay then inside let's
just make a simple text object so just
say text then over here on let's say
just loading
let's put the text width and height on
zero put it on Bold let's make sure to
disable wrapping
and push it over there on the side and
maybe increase the font size down a
little bit okay there you go we have our
very basic loading screen now we're
going to unload this scene and then once
on this scene we're going to load the
final scene although also one very
important thing related to loading
scenes is you need to remember the
lifetime of the objects regular game
objects only for example the ones that
we see here in the hierarchy these get
destroyed when you do a scene change
so for the goal that we're trying to
achieve we need to unload this loading
scene but then also somehow transfer
data so that the loading scene here
knows which one is the final scene now
you might think that over here on the
main menu we could create a game object
attach a script that would hone the
reference to the final scene but like I
said game objects get destroyed as soon
as we unload the unloading scene so for
transferring data between scenes we
can't really use a regular script on a
regular game object now one approach is
to use the don't destroy on loan this is
a Unity function that helps you stop a
particular script or a game object from
being destroyed that way the object
won't process through scene changes so
that's one option but another option
that I prefer is very simple let's just
make it another class so let's create a
new c-sharp script call this loader and
over here let's go ahead and make this
class a static class and we are not
going to extend Model Behavior so just
like this
basically by making it static it means
that this one is not attached to any
specific instance of an object this
class cannot be attached to any object
and cannot have any instances
constructed then inside we can add
static functions in fields like for
example a static and for the Target
scene index
so now this field we could set this
field from over here on the main menu UI
and when we would load we would not be
resetting this field also here I should
point out one quick thing you can make
field static without making the entire
class itself static making the class
static is just a good approach if the
entire thing if everything in this class
is also meant to be static if you don't
make it static then you can have regular
films here
you can have both static and non-sanic
whereas if you make this static
then you're going to have an error
because you cannot have non-static
feelings so this is another clean code
thing if it's only meant to contain
static logic then make the class itself
static okay so we have a static field
for our Target scene but as usual we
don't want this to be a public field we
don't want the main menu to directly
write to this field so let's make this
class the only one responsible for
anything related with scene loading
since then let's make a function so a
public static void call it load
and for a printer let's receive a string
for the Target scene name then over here
we will load the actual scene so let's
go into the scene manager and load the
scene
analyst best in the Target scene name
okay that's it
and then over here on the main menu UI
instead of directly unloading a scene
let's go into the loader and con load
and pass in the scene name so that's the
game scene
okay so this is what we're going to do
that's good except it's obviously not
good over here we're using string names
that's horrible we should never use this
so let's avoid using strings as much as
possible in one simple way is to just
Define an enum for all of our scenes so
let's go here on the other and let's
define that so a public enum let's call
it scene
and for all of our scenes so we have the
main menu scene then we have the game
scene and the unloading scene
okay so then down here on this function
inside receiving a string we just
receive a scene for the Target scene and
we use the target scene although of
course the NT API does not support
unloading our custom enum it has to be
an index or string so the simple
approach is just to convert this one
into a string that's it so the only
thing you need to make sure is that the
enum values over here match the actual
name on the actual scenes perfectly so
don't make any mistakes keep it case
sensitive so don't do this make sure
everything matches perfectly okay so
just like this everything should already
be working the same as previously so the
main menu calls that let's actually just
use that so let's use scene Dot Game
scene
so on the main menu we do this and
unloader we load the scene okay let's
test here is the main menu and if we
click and wait a bit and after you go it
didn't load the game scene okay great so
everything still works the same as
presently except now all of the
unloading logic is inside of this class
and over here let's open a loading scene
in the middle basically when we have
this function to load a final scene
let's first off set this field so this
one instead of being type in let's make
it a type scene and this is going to be
the target scene and let's make it
private okay
so when we have this function let's set
that field although here remember how
this is a static class so in order to
access this field we need to exit
through the class name because over here
we also have a local variable with the
exact same name so what sex is the
unloader.target scene and set it to the
Target scene
so again don't be confused here you can
even use visual studio and put the
cursor on top to see what object
represents what so you can see the
unloader.target scene is referencing
this field whereas this one over here is
referencing the local field so we want
to assign the member field to the one
that we received as a parameter okay so
we store that and then let's immediately
unload the unloading scene so scene
manager let's load the scene and we're
going to load
the scene dot loading scene dot to
string okay so we're going to download
that and now here comes the tricky part
if we do this so if we load the
unloading scene and then immediately
unload the target scene if we didn't
like this it won't actually show the
loading scene
we're calling these functions one right
after the other so to unload the one and
immediately the other basically we need
to wait at least one frame to render so
that the unloading scene is visible and
then we can alert the final scene so
let's make a script to do a very simple
jump let's create a brand new c-sharp
script for the unloader comeback and now
let's go inside the unloading scene so
this is important let's make this on the
loading scene not the main menu or the
game scene so over here let's create an
empty game object for the unloader
comeback let's reset transform just keep
things nice and clean and let's attach a
script so the only other comeback okay
and on this script we want to basically
just wait for the very first update
so let's see private ball is first
update and we started off as true
actually
so is the first update is true then we
do a product void update so if it is the
first update if so then let's set is
first update to false
we have the first update although
technology I should point out that we
don't really need this we're going to
load right away so either way it will
only run One update but still I like to
add this just to make the logic
perfectly clear basically if it is the
first update then let's call a function
on the unloader so on the loader over
here let's make a function public static
void call it below their comeback
okay we have this function it's over
here on the other convex let's just go
into the unloader and call the unloader
convex function all right so basically
now here we have this function that is
going to be triggered on the first
update so we know for certain the
unloading scene has been rendered so
it's over here that we want to load the
actual final scene okay that's it here
we have a super simple loading system
just make perfectly sure that the
unloader come back with the script this
one only exists on the loading scene it
should not be on any of the other ones
so let's test and for that let's go
inside the main menu scene okay and now
let's hit on play okay so here we are on
main menu now if I click on play and
actually here's the thing that I forgot
so make sure you don't forget this we
need to add the unloading scene to the
builds in order to be able to load
so let's go up here into the build
settings let's go into the project drag
the unloading scene like that okay so
now let's test so here we are on the
main menu let's hit on play and there's
the loading scene after a bit yep here
we have our game scene all right awesome
so with that everything is working
perfectly all of the logic is working
great now the wrong words great let's
just make a nice proper visual for our
main menu so for that let's go inside
the game scene and over here let's copy
a few things so let's pick up the four
object and let's also pick up the global
volume with the post pressing so let's
copy both of these let's go into the
main menu scene and over here on let's
paste both objects okay now let's also
drag some player visuals so let's put
this in 3D go back down into the floor
and let's pick up some visuals so let's
go inside our assets on the prefabs
visuals let's find over here the player
visual again make sure you drag the
visual only we don't want any logic
components and by the way this is yet
another great benefit of separating the
logic from the visuals right now it's
super simple for us to play some players
here because we have just the visuals
commonly separated from the logic okay
so on the visual let's just make it look
at the camera let's position a bunch
more players so let's duplicate this
and put one to the side we're going to
move the camera in a bit but now let's
just place them and included assets
there are a bunch of materials so over
here we see the employer body then we've
got a blue a green and a red like I said
this first course is on making this game
in single player but the goal is to then
make a second course after this one on
converting this game into multiplier so
that's why I included multiple colors so
let's just drag these let's go into this
player Visual and on this one make it
blue so on the head and on the body then
on this one on the side here let's make
this one green so green there and green
on the head and for the one behind let's
make this one the red one so put it in
red and in red Okay so we've got our
nice four players now let's also add a
camera so we're going to have the camera
kind of like this kind of from below and
looking upwards I think that looks
pretty good for that let's use cine
machines and let's go into game object
go into cinemachine and let's create a
brand new version on camera okay unlike
this let's just push it up a little bit
okay so this is our nice composition
now on the virtual camera let's just go
ahead and add some noise so let's add
basic multi-channel purlin so let's do
it just like we did when we first had
the thin machine so let's use the
handheld normal mild and now let's just
play around these films which by the way
you can do that while the game is
playing so let's hit on play and over
here you can play around down the fields
although actually defaults already look
pretty good but let's put the frequency
maybe a little bit less and the
amplitude maybe a little bit bigger so
just some nice little Sway and by the
way if you make any changes to the send
machine virtual camera and now you stop
playing it will actually lose those
changes but over here on the virtual
camera there's this nice toggle save
during play so if you tick this and now
you exit play mode and there you go
those changes were saved okay great now
let's just make sure to untick this so
we don't accidentally modify okay so
here we have the basic Vision that we
want finally there's also a game logo in
the included assets
so let's just go into our canvas into
our main menu let's create a brand new
UI image let's assign the logo Sprite
then let's just position it on that
corner so let's move it all the way up
there we can anchor it to the top left
corner and let's make it a bit bigger
and by the way I want something like
this if you play around this it might
get a bit scratched so if so over here
on the options on the image you can
download this one to preserve the aspect
ratio so that way even if you stretch it
won't actually be stretch it will always
be perfect okay just like this okay so
here we have our basic main menu it's a
basic setup but it looks pretty good and
with that we have built a nice main menu
alongside with the unloading system so I
can click on play it goes into the
loading scene and then into the game
scene so that's great
the next thing that we need is some kind
of pause button so let's do that in the
next lecture
hello and welcome I'm your code monkey
in this lecture we're going to add a
pause button with a pulse window that
also has the ability to quit back to the
main menu and in doing so we're also
going to solve some sneaky issues with
loading okay so here in the main menu we
can click the play button in order to
unload the game and yep everything works
now I'm in the game but now let's say I
want to pause the game for a bit or quit
back to the main menu right now there's
no way so let's do that let's go here
onto the game scene and first let's send
on the pause and for that we're actually
going to need some input so let's first
go inside our player input actions let's
open this and then over here let's make
a brand new action let's name it the
pause
for the action type let's go with button
okay and for the bindings over here
let's go with escape and actually if we
use the same method that we've been
using if we listen and press on Escape
nope doesn't work because Escape just
cancels it so instead we need to use a
search bar here Search for escape
keyboard just like this okay great now
again as always let's make sure to save
the asset and wait for the compilation
to happen there it is so now here on the
game input list let's listen to it and
fire the event as usual so go into the
player input actions the player action
map let's go into the pause action and
listen to the performed event
and when this happens let's fire off an
event so a public event event handler
let's go on pause action
and then down here we're simply going to
invoke this event
okay just like this now from listening
to it here's the question where does
that make more sense should we do it
over here on the player script or
perhaps over here on the kitchen game
manager I think over here on the game
manager makes more sense since a pause
is more related to the game itself
rather than a specific action by the
player so let's add it over here let's
first of all listen to the event so
let's see what private void start and on
start let's listen to it so let's go
into the game input and we didn't
actually make it a Singleton yet so
let's do that over here let's make a
public static game input
for the instance with a public yet and a
private set
then down here on the Wake let's set
instance equals this okay there's our
Singleton so now back in the kitchen
game manager what's going to be instance
and listen to the on pause action event
and again let's rename this to give it a
proper name
so the C game input on pause action okay
so here we have it when we have this
let's call some kind of pause game
function so let's define this let's go
to the end of the file here and over
here let's make that function
so a private void pause game and over
here we're going to pause the game now
for pausing doing this is actually
surprisingly easy
basically all of our logic is using time
dot on time for example over here on the
player script we have our movement speed
yep then we get the inputs and over here
on the handle movement function yep for
the movement distance we have move speed
multiplied by time.10 is done or another
use case over here on the stove counter
we've got a frying timer and how we
count it down again is the same thing
time dot double time well it turns out
that behind the scenes time to time the
time actually already has a multiplier
when you access this it is after that
multiplier calculation so over here on
the pause game function we can just go
into time and we can modify the time
scale this one is the multiplier so if
we just put this at 0f then that's it
this is going to pause all of the other
Delta times so let's test so here we are
pay attention to that in the countdown
timer and I press on escape and there
you go everything pauses the countdown
timer pauses over here the script pauses
and I can no longer move nothing works
everything is perfectly paused alright
Awesome everything works except one
problem obviously right now we cannot
unpause if I press Escape it's not in
pausing so let's do that over here on
the kitchen game manager let's add a
simple bone so a private bone let's come
with is game paused and let's see found
it to phones okay so is game paused and
then down here on the pause game
function let's simply flip this one so
we set this one equals not this one so
that is going to flip that Boolean and
then we check if the game is paused if
so set it to zero f and if not then
we're going to set the time.time scale
back into one F okay so now this should
pause and unpause so essentially rename
this function since this is no longer
just going to pause let's rename this to
toggle and pause game this is going to
pause and unpause
okay so let's test
okay so here we are everything is
running now I pause and there you go
everything freeze I cannot move the
arrow will stop the countdown to stop
when I press again and there you go nice
and redeemed all right great so all of
the logic is working perfectly the only
thing we need is we don't just see
visual and as usual let's separate the
logic from the visuals so let's go
inside the canvas let's go into the
scene View and inside the canvas let's
create an empty game object call it the
game pause UI then let's stretch to
occupy the entire screen so zero on
everything okay great now inside let's
first of all add a background so a new
image name this the background let's
once again stretch to occupy everything
and on the color let's put it in black
with just a little bit of alpha okay
just like that then let's add some text
so let's create a brand new UI text
let's name it pause text
and in here let's just say paused let's
just make it big so the width and height
both on zero let's disable wrapping Put
It Center down the middle and let's
increase the font size by quite a bit
and put it in bold and let's also change
the color maybe a nice yellow something
like this okay that looks pretty good
let's just lift it up by a little bit
now let's make a script to show this so
on the UI folder let's create a brand
new c-sharp script call this the game
pause UI let's attach it then open now
here let's do the usual thing so let's
make two show and hide functions so
private void show and then a private
void hide
so on the show game object set active
into true and on the hides set it into
false
okay that's it pretty simple now we need
to know when to show our hide these
functions so we're here on the kitchen
game manager let's make two events to do
that so let's go up here make a public
event event handler
and let's name this on game pause
another one for on game unpaused okay we
have both events then down here on the
toggle pause game if we have this one
time scale 0 that means we have pause so
let's invoke the on game pause this
eventar is not empty okay and on this
one let's trigger the other one so on
game unpause
okay we've got the two basic events now
back here on the game pause UI let's
listen to it and as usual let's do it on
start so private start let's go into the
kitchen game manager access the static
instance and let's listen to the on game
pause
and I'm going to listen to the other one
so the instance on game unpaused so
listen to both of them and as usual
let's write the clean codes and let's
rename this so kitchen game manager and
on this one the same thing
so also the kitchen game manager
okay we have both and when the game is
unpaused then we want to hide the pause
window and when the game is paused then
we want to show the pause window and
finally of course we want to hide it by
defaults over here on sart after we add
listeners let's just hide it okay so
that's it that should work so let's test
so here we are everything is running now
press the pause and there you go got a
nice pause window press again and there
you go everything resumes okay great so
the last thing that we want is just a
button over here to go back to the main
menu and let's also add a button to
resume without having to press the
hotkey so over here let's create a new
UI let's make it a button this is going
to be the main menu button now let's
make it quite a bit bigger okay width
and height of 30 and 80. let's put this
one quite a bit down there and inside
for the text this one is the main menu
let's put the color in White and the
background for the button let's put this
one in a dark gray and let's also just
for fun add a nice upline and let's also
add a shadow
for the outline let's put it on for
Alpha and let's put it on about 3 3 and
for the effect on the shadow 5 minus
five okay so that's a nice outline and
nice shadow
and then for the text itself let's put
it in bold and raise it by just a little
bit okay just like that looks pretty
good so this is the main menu button and
then let's also make so duplicate this
let's make this one rename it this is
the resume button
and inside on the text let's say resume
okay we have our two basic buttons so
let's handle them in the script so over
here let's add as usual a serialized
field private of type button so that's
inside Unity engine.ui so it's for the
resume button and then we're going to
have the main menu button
okay let's save the script and back in
the editor let's drag those references
so that's the main menu button and the
resume button okay so now for these
let's add the click action so let's do a
private awake and on the way go into the
resume button the on click and let's add
a listener so this is going to be our
listener
and same thing for a main menu button so
main menu now for the main menu this one
is super simple let's just go into the
loader and call the unload function and
we're going to download the main menu
scene
okay that's the main menu very simple
and for the resume this one is only
going to be clickable when the game is
paused so we can just trigger the same
function on the kitchen game manager to
toggle the pause so kitchen can manager
the instance and toggle the pause game
this one is actually private so let's go
to it and let's make this public so we
can count from there okay that's it
super simple Let's test okay so here we
are and let's pause the game and now if
I click on resume if there go it does
work everything resumes and now pause
again and now let's go back to the main
menu loading any up there you go back in
the main menu alright awesome so
everything works perfectly
however there's one sneaky issue here
you can already see the issue by seeing
that all of these animations are still
but let's click on play and notebook
that issue everything is still frozen I
cannot move the character and over there
the Shader that one is completely Frozen
so the times can only still set to zero
basically we need to manually reset it
and the simplest way to do this is
really just in the main menu
so we can go here on the main menu UI
and we can just use this as our reset
function so let's just go into time.time
scale and let's set this one back into
one F that's it that's the only change
Let's test so here we are let's pause
let's go back into the main menu
and we can see the animations are indeed
playing and if we go back into play and
if there you go everything works
perfectly we can pause and yep here we
do see one of the other two sneaky
issues left basically it has to do with
scene loading and cleanup so the first
one is on input
over here on the game input class we are
constructing our player input actions
and we are listening to these events and
technically this object the one where
the game input is attached this object
is going to be destroyed when the scene
changes
however this object that we're creating
this instance of player input actions
this one does not get destroyed
automatically so that is why when I went
into the pause menu again for the second
time over here we've got a missing
reference exception basically the player
input actions of the previous game is
trying to show the pause window also of
the previous game which has since been
destroyed so obviously we have a missing
reference exception because that object
no longer exists so in this case we have
two options to solve this one option is
we can just unsubscribe to these events
Unity mono behaviors have a really nice
combat called on destroying so over here
private void on Destroy so this is the
default one this one is called when the
mono behavior is destroyed
so we can go into this one and we can
manually unsubscribe and the way that
you unsubscribe is you just do minus
equals
so this would solve that problem because
when this object is destroyed it's going
to unsubscribe from those events so the
next time it will no longer trigger so
that would fix it however on the game
input class we are still creating a new
object of this type I'm not 100 sure how
the input system works in the background
so perhaps this object might say in
memory which is not good so another
approach we can do or perhaps in
combination with this is we can
unsubscribe and then we can properly
dispose of this object how we do that is
very simple let's just go into the
player input actions and we just call
the dispose function that's it
this should clean up that object and
free up any memory so let's test so here
in the game view let's pause let's go
back into the main menu now let's go
back into the main game and now if I hit
pause and if there you go we no longer
have any errors okay so that's good
however now we still have one more
potential issue and this one has to do
with Statics like I mentioned before
Statics belong to the class and not any
instance of that class so that means
that static films will not be destroyed
or reset when the scene changes in the
case of our unloader here where we have
a private static field this one the fact
that this one doesn't reset
automatically that was a good thing
that's what allowed this to make the
unloading system but in the case of
maybe static events that might not be as
good it might mean that we might be
keeping some state from the previous
game which might cause everything to
break so basically we have a similar
problem to what we had in the input
where some logic from the previous game
might be affecting the next game in all
the code that we wrote the main place
where we use Statics were in The
Singletons and these are going to be
cleared automatically when the
underlying instance object when that one
is destroying so these do not cause any
problems however for example over here
on the cutting counter we've got a
static event when the scene changes this
will not be cleared so this will still
have the same number of listeners we can
actually see how many listeners there
are by printing it so let's go down here
before we're invoking the event let's do
a debug download let's go inside the on
any cut event and over here we can get
the invocation list this one is a list
of all of the functions that are
listening to this event
and we can just print out the link to
see how many listeners are listening to
this event so let's see what this
returns okay so over here let's pick up
some cheese and slice it and if I'm
working the log yep there you go one
there's only one listener okay that's
correct
however now if I go back into the main
menu and now I go back and I play again
okay so let's play let's just wait for
the countdown and once the countdown
ends pick up some cheese go there slice
it and there you go there's the problem
now we have two listeners in this case
doesn't really cause an error because
the tune listeners they're just over
here on The Sound Manager so we are
subscribing to this event and we're
doing the cut and playing the cut object
however if here we do something with
this transform like for example let's
just do a debug download on this
transform that position if we do this
here let's go ahead on the first one
let's slice and okay that works let's go
back into the main menu now play again
now wait for the timer
pick up some cheese go there slice any
of that I go there we have our air that
is because we are now accessing The
Sound Manager transform and that one has
since been destroyed so if you do use
static events like this one here if you
do that always remember you need to
manually reset that state it won't
happen automatically on the scene load
and one way that I normally do it is
just make a class responsible for doing
that so let's go ahead and let's create
a brand new c-sharp class let's call
this the reset static data manager and
for this one we want this one to run
only on the main menu That's only where
we're going to reset things so let's go
inside the main menu scene let's go
there let's create a brand new empty
game object for the reset static data
manager let's reset transform just keep
things clean and let's attach that
script again it's very important that
this object only exists on the main menu
then over here we're basically just
going to go into any script and reset
any data so for that on all those
scripts let's make a function
so over here on the cutting counter
let's make a public static function
let's call this reset static data in
order to reset any listeners let's just
go into the on any cut and set it to
null that will clear all the listeners
so we just do this and then on this
script Let's see we practically awake
and on awake let's go into the cutting
counter under the class so not any
instance so we're going to access the
static and we're going to reset the
static data that will clear all the
listeners on The Cutting counter all we
need to do is make sure to do this on
every single static event that we have
so on The Sound Manager and by the way
here we can get rid of the testing code
here we can see all the static events
that we're using so we've got the
cutting counter then we've got the base
counter and trash counter so let's go
here on the base counter and paste the
exact same thing and reset this event
okay and now let's go into the trash
counter
so here on trash counter same thing
reset this event set them all into null
and by the way here we have a warning
that's because trash counter extends
base counter so basically this is
telling us that we are hiding another
function with the exact same name in
this case we do want to hide it so
what's actually make this new to make
sure that this one is a different one
just to avoid that warning and same
thing over here on the cutting counter
we also need to make a new okay so
that's it and now we just need to go
over here onto the reset static data
manager let's go into the base counter
and reset the static data go into the
trash counter and reset the static data
okay that should do it let's see so here
we are in the game let's pick it up and
slice it and yep we've got just one
listener that's good let's go back
outside back into the main menu let's
play once more and over here let's pick
it up again go there drop it and there
you go still just one listener because
we are now correctly eliminating all of
the previous listeners
so this is the one sneaky issue that you
must be careful with when it comes to
object Lifetime and Statics for static
Fields you need to remember that they
don't manually get cleaned up that's up
to you so that's something you have to
keep in mind but you can also see how
easy it is to solve now that this is
solved let's just go into the cutting
counter and just get rid of our testing
log alright so with all of that all of
our scenes are working so we can start
from here from the main menu and go
straight into the game then here we are
in the game playing normally we can
pause the game at any point from the
pause screen we cannot resume or we can
go back into the main menu and from back
into the main menu we can once again
play the game from scratch and if there
you go everything works alright awesome
now the next thing that every game
requires is some options so let's do
that in the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to create a
simple options menu where we can modify
the audio levels okay so here let's make
the options menu so on our game scene
let's go into the canvas and create a
new empty game object let's make this
the options UI let's stretch out this
one to occupy the entire screen
then inside let's make a UI image once
again let's stretch out everything
let's put this one in black in just
almost full Alpha okay now let's make
some texts so let's create a brand new
UI text call it the options text
then for text let's say just options
let's put the width and height at zero
let's disable wrapping Put It Center
down the middle and put it quite a lot
bigger
okay that's the options now just move it
slightly upwards all right now let's
make some simple buttons to handle our
audio controls we're going to make it
super simple literally just a button we
can click so inside the options UI let's
create a brand new button
call this the sound effects button then
let's make the button a bit bigger
something like this okay
and inside for the text let's say sound
effects and then we're going to have a
number for the sound effects let's just
quickly change the color so put the text
in White and the button over here the
button image let's put it in a dark ring
okay let's also make it just a tiny bit
thinner it's just like that okay so this
is the sound effects button now let's
duplicate this one this one is going to
be the music button so let's name this
the music button
then inside for the text music and then
a number
and that's pretty much it so by clicking
on either of these buttons we're going
to increase and then Loop the volume so
let's make a simple script to handle our
options window so in our scripts inside
the UI let's create a brand new c-sharp
script for the options UI let's go ahead
and attach a script and open
so here as usual let's get some films
for our buttons so a serialized film
private of type button for the sound
effects button and then there's another
one for the music button
okay both buttons now let's add the
click event so on private awake let's go
into the sound effects button and on the
on click let's add a listener
and we're going to do the same thing on
the music button
okay so now when we click we want to
change the volume so let's go here onto
The Sound Manager and make a function to
modify the volume
let's make a private void change volume
and here we're going to increase the
volume by 0.1 percent so constantly
increase in 10 increments so that means
we need to keep track of the volume so
up here in order to find a SIM phone
private float for the volume
well it's default it to one F okay so
now down here we take the volume and we
increase it by 0.1 F and now let's Loop
it back to zero
now for looping usually you do it using
the modular operator so here you could
do volume equals volume module of 1.1 f
that way when it gets to 1.1 f it would
reset back to zero but here since we're
working with floats which can have a bit
of odd Precision with this let's just do
a simple lift to make sure that always
works
so if the volume is above one f
if so then let's just reset it to zero
okay
so here we modified volume and let's
just make sure to use it over here when
we actually call the audio
source.playclip Point here we've got a
volume but this is the one that we
received as a parameter so let's
actually receive this one rename this to
volume multiplier
and we're going to basically multiply
the one that we receive in the parameter
by the one that we actually store
so this way on these functions when we
play a certain sound we can still give
an optional volume if we want to make it
louder or quieter then the regular sound
effects okay so we have our change
volume function now we just need to call
this from the options UI so that means
this one actually needs to be public
okay so now here on the options UI we go
into the sound manager access the
instance and call change volume okay so
that is going to change the volume then
we just need to update the values on the
options UI so let's make a proud void
update visual
and this one we need to update the text
so up here on let's add once again some
more serialized Fields so text mesh Pro
ugly one for the sound effects text and
another one for the music text
okay we have both these then here the
sound effects text not text
equals and we go into The Sound Manager
the instance
and then we need to get the volume
so over here on the sound management
let's make a function together so a
public float return get volume and we
just return the volume okay so then here
let's get volume except volume is going
to be a normalized value so rather than
showing 0.1.2.3 on the UI let's just
multiply the volume by 10f that way we
show between 1 and 10 okay then let's
just round out this number
and then add the text
so here's sound effects and then we have
the bone okay so that's pretty much it
and up here when we change the volume
let's just update the visual
and let's also make a private void start
and on start let's also update the video
okay that's it pretty simple now let's
do the exact same thing on the music
except on the Music Manager we named it
music manager but over here we just have
an audio Source there's no actual
manager so let's actually make one let's
create new c-sharp script for the Music
Manager let's go into the Music Manager
object let's attach a script and let's
open so here we really just need pretty
much exactly the same thing that we had
so let's just go here into The Sound
Manager and just copy these
so on the Music Manager let's paste them
we need a volume so a private mode for
the volume just like this okay so that
changes the volume except again the
Music Manager this one the music is
constantly going to be unlooping so
after we modify the volume we need to
update the actual audio source so let's
begin by grabbing the audio source audio
source and we just do a pro void awake
and on a week let's grab the audio
source
get the component of time Body Source
okay so we have this and when we change
the volume let's go here and update this
phone okay that's it and let's also
default it to some like 0.3f okay good
then in order to be able to call this
from the option Cy we just need to make
it a single turn so as usual public
static Music Manager for the instance
and we have a public get and a private
set
and then an awake just set instance
equals this okay
so then here on the options UI we can go
into the Music Manager the instance and
change the volume and afterwards let's
update the visual and down here on the
update visual lets you pretty much the
same thing so on the music text modify
the text to say music then we go into
the music manager and get the volume all
right that's it all this should be
working let's just drag our references
so back in the afternoon let's drag
firstly button so the sound effects
button that's this one then the music
button that's this one then we have the
music text that's this one and the sound
effects that's like that okay let's test
okay so here we are the music is playing
and as I click the music is currently
getting louder and louder
and their game I'm using is at max
volume and if I click again no the music
is completely muted alright awesome any
sound effects also work so like this
they should be less leather than usual
okay great so everything works perfectly
except obviously we have one big issue
the options window is on top of
everything
the goal is for the options window to be
kind of a sub menu of the pause window
we want to have an options button on the
pause window that won't bring up the
options window so let's do that let's
first hide the options window let's go
into the game pause UI and over here we
have these buttons let's just make one
more let's put it down the middle this
is going to be the options button
and inside let's modify the text to
options okay
now let's edit this script so we're
going to have another button so this is
the options button and down here we're
going to have another click so the
options button okay
and when this happens we want to just
show the options window so in order to
access it let's make this a Singleton so
public static for the options UI
a static instance
with a getting a private set
and on weak as usual instance equals
this
so over here on the game POS UI we go
into the options UI access the instance
and then call a show function so we need
to make this
so here on the options UI let's make
those so a public void show
and this one as usual just game objects
that active into true
and then we have a private hide
and this set active in two phones
okay we have both these on the other
side we show it and over here on start
let's also hide it okay
then let's also hide it manually so
let's add a button to close the options
UI so over here let's show the options
UI and let's make another button let's
put it on the bottom this one is the
close button
and over here let's just say close
so then here on the options UI just make
another button the close button and down
here for the click event
we go into the close button and we just
call height
okay so that won't hide the window
however remember that the pause window
can also be closed by just pressing
escape if we resume with the hotkey it
won't hide the pause window so let's
also make sure this one hides on the
same thing so we can do pretty much
going to the kitchen game manager the
instance and let's listen when the game
is unpaused so when that happens let's
hide this window
so once again let's do things nice and
clean let's rename this so the kitchen
game manager
and when this happens let's just hide
okay this should work let's just drag on
the references so first here on the
options UI let's drag the close button
and then on the game pause UI let's drag
the options button okay so let's test
and if right away the options window is
not showing the trade and if I press in
this game there you go there's the pause
window and if I can click on options if
there's the options window now if I can
go and close back here back into resume
okay works now if I pause options and
now press on the Escape key and you
better go closes everything all right
great so everything is working fine
however we have one slight issue
the option does work so I can modify
this to change the sound effects and
Music volume so for example let's mute
the music and put the sound effects on
five so I put it like this but now if I
stop playing and I hit play again
and working the options and oh there's
the issue basically that is back to the
default obviously that is resetting
since we didn't actually save anything
so let's save it now in unity the
easiest way to save some data is using
player prefs so let's go over here on
The Sound Manager and when we modify the
volume over here when we do that let's
access the Unity Player prefs and over
here we've got a bunch of set functions
so we can save a float an INT or a
string this one as you can see it takes
a string and a value so this is pretty
much essentially just a dictionary now
for the key as you can see it's a type
string but again we should not be using
strings directly
so let's go up here in order to make a
proper constant so a private con string
let's go with Pro layer
prefs sound effects volume
and let's go sound effects volume
okay we have our nice Center in content
and down here when we set the float
let's use this string and say the volume
okay so that is going to set the float
and now technically Unity is going to
automatically save the player perhaps
basically there are only problems if
Unity somehow crashes in between when
you can't set float and when it actually
saves but if you want to prevent that
from happening you can just go and tell
it to save manually just like that that
won't definitely save it and now we just
need to handle loading so here on awake
when we have this let's go into the play
prefs and let's use get float let's pass
in the same key so this one takes the
key and default value so let's default
it to one F basically the default value
is used if there's no save data on
display prefs on this key so the first
time we run it's actually going to use
this default and this one's going to
return these saved value so let's just
set it on the volume
okay so that's it that's only takes to
save some basic data now let's do the
exact same thing on music so over here
on the Music Manager let's first Define
our private con string for the player
pref's music volume
and this is going to be the music volume
okay we have our string and then down
here when you change the volume layer
press
and let's set the float on this key and
let's pass in the Music Volume okay and
then what's going to player prefs and
actually save it and now appear on the
wake
let's grab the volume
and it's going to be going to the player
prefs in order to get the float on this
key
and default value is 0.3f however over
here on the music again we are not
spawning the sound afterwards the sound
starts playing right away
so let's make sure to set the audio
Source volume to the one we grab from
there okay that's it so like this it
should be working so let's test so here
we are and the music is playing let's
pause go into the options let's bring
the music completely down so let's mute
the music okay the music is gone and
sound effects let's put a note 5. now
let's stop playing and now play again
and going to the menu options and if
there you go the data was indeed saved
and the music is indeed muted alright
awesome so here we have some basic data
being saved and also just quick note
related to saving for this simple game
decisions are pretty quick so I didn't
include any kind of save system for the
actual game data but if you want to know
how to do that I also have video
covering that topic okay so with that we
have our options window working the
volume sliders work perfectly the next
thing we need to add to our options is
some key rebinding so let's do that in
the next lecture
hello and welcome I'm your code monkey
in this lecture we're going to add key
rebinding to our options menu so here we
already have this nice options menu we
can modify the volume of the sound
effects or the music next let's handle
key rebinding okay so first let's build
the elements over here on the UI so
let's create a bunch more buttons but
before that let's actually make some
text on the side and buttons in the
middle so let's create a brand new UI
text
call this move of text
let's put it on the same size as the
other one so these got a font of 24 so
let's put it same thing font of 24 width
and height let's put both of these on
zero and down here anchor it to the left
okay down the middle and with no
wrapping okay so then over here this is
going to be the move up action
so we have move up then we have the move
down move left move right then we have
the interact the interact alternate and
finally the pause so these are all of
our actions so let's just make all of
these
so rename this so this one is the move
down
then this one over here is the move left
this one is the move right this one is
the interact text then the interact
alternate text and finally the pause
text now let's just modify the text on
these so that's the pause
that one is the indirect Alt
then this one is the interact then we've
got the move right
then over here the move left and finally
we have the move down
okay so those are our labels for our
controls now let's just make buttons
over here on the right side so let's
duplicate one of these buttons let's put
it over here and put it on something
like 50 by 50. so this is going to be
the move up button and inside on the
text this is going to be pretty much
just a w okay so we have the move up
then we're going to have the move down
move left move right the interact the
interact alternate and the pause
so we just need a bit more space so
let's move all of these up by quite a
bit let's also move the music and the
sound effects so move all of these like
that okay let's just name all these
buttons so this one
is the second one so this may move down
then over here the move left
then the move right then the interact
button the interact alternate button
and finally the pause button okay those
are on the buttons let's just position
all of the labels exactly where they
should be
okay so here we have all of the options
all of our bindings now in code let's
grab references to all the buttons and
all the text inside the buttons so here
inside the options URL let's add all of
those so first of all for the attacks
we're going to have the move of text
then the down left right and so on so
let you see all of these so down
then over here the left then the right
then the interact text the interact
alternate text and finally we have the
pause text
and for the buttons let's go up here
make all the buttons so they move up
button then they move down button
then we have the move left button then
the move right button then we have the
interact button the interact alternate
button
and finally the pause button
okay so we have all of these references
over here in the editor let's just drag
them so let's make sure we drag them on
correctly so let's do it one by one so
the move up this is the text and
actually it's not that one so that's
already a mistake right there we want
the text from inside buttons
so let's pick up all of these text
objects so let's go into the options so
text inside the move up let's grab that
one then inside the move down let's grab
that one and then left and so on so
definitely make sure you grab the right
ones okay that's on text now for the
button so let's move up button then you
move down
then they move left
the move right the interact interact
alternate and finally the pause button
okay great and just to verify that
everything is working let's give proper
names to these objects
so the move up button text
okay so I've renamed all the buttons so
now over here it's much easier to verify
that we have the correct references so
the sound sound music music and so on so
definitely make sure all of these are
correct otherwise you might go crazy
when things start to go a bit weird so
make sure these are all correct all
right now let's begin by updating the
text inside over here so let's go into
our update visual so we go into this set
the text and now we need to get the
binding text for this binding so for
that let's make that function on the
game input over here let's just comment
this out
then over here on the game input script
let's make a function to get the
bindings certainly we could make
something just to grab this player input
actions but again we don't want the
options UI to know what input system
we're using it should work regardless of
what input system
so we don't want the game input to
return anything of this type instead we
want to make a nice layer of abstraction
so for that let's make an enum to Define
all of our bindings so let's make a
public since we're going to access it
enum call it binding
and over here let's add all the bindings
so we've got the move up then we have
the move down the move left the move
right then we have the interact the
interact alternate
and finally the pause so these are all
of the bindings now let's make a
function to return the binding text
so over here let's make a public we're
going to return a string
let's just name it get binding text and
as a parameter let's receive a binding
okay so now here let's just do a switch
switch on this binding and basically
just match up the enum to whatever
action we have
so for example let's begin with the
interact since these are the simplest
ones
so for this one to get the bindings we
first go inside the player input actions
then let's go inside the player action
map then for the action so in this case
the interact and anything inside we've
got the bindings this is an array of all
of the bindings in our input map we
defined all of the keyboard bindings on
index 0. later on we're going to add
Gamepad bindings but for now we're going
to have the keyboard always on index 0.
so over here going to bindings axis on
zero and let's just do a two string
okay so let's just return this and let's
do a default to return always this one
just like this okay so let's do a quick
unlock to see what this returns so let's
do it over here on the game input just a
debug.log go into there get the binding
tags for the interact
okay so let's test and right away yep we
do see it working so the interact and
The Binding is on keyboard slash e but
we don't want all of this text we really
just want to see the E thankfully the
input system has a really great function
for just that so instead of calling the
general to string let's call to display
string let's see any of this one does
return just easy okay great so this is
the one that we want let's do the same
thing for all of the other simple
actions
so we've got the interact then we have
the interact alternate and we have the
pause so these are all the super simple
ones so just going to interact alternate
grab the binding on zero and for the
pause binding on zero okay so these are
all super simple now the more complex
one is the move it's more complex
because you can see all the others just
have one binding except for the move
over here we have a composite binding so
that's basically a binding which inside
has four separate bindings basically the
way that this works is that when you use
a composed binding all of these are
added to the array so this to the vector
is going to be on binding 0 then the up
is going to be on binding one two three
four and so on then the arrow keys this
one is going to be on five then we have
six seven eight nine and ten let's do a
log just to verify
so here if we do one for the move up
action for this one let's go into the
move and let's print out just the
binding zero let's do a regular two
string let's see what this returns so up
here let's just modify our log to say
the move up okay so let's see any up
index 0 does have the move to the vector
and now if we print the one on binding
of one yep now this one does have the
move on the w
so like I said we can see that all of
these Composites these are technically
inside that one but in terms of that
array it's just a flat array so this one
index 0 1 2 3 and 4. so that makes it
super simple to add over here so they
move up down left right
and let's just do all these
so we have all the bindings and over
here just one two three and four
and set a two string let's call the
display string okay so the binding text
this is all set up so let's go up here
and get rid of our testing code we can
now call this from the options UI so
over here let's do exam with that so
when we update the visual
let's go into the game and put let's
access the static instance let's get the
binding text and this one is going to do
the move up
so that's it this one is going to return
a string
let's write all of them
okay here are all of them so let's see
and if there they are all perfect don't
we SCD EF Escape okay great so the
visual is working now let's end on the
rebinding so let's add a click event
let's go into the move up button
let's go into the on click let's add in
listener and for the enlistener over
here let's make a function on the game
input to rebind this binding
so over here on the game input let's see
public void rebind binding and we
receive a binding
now for rebinding I cover this in detail
in the dedicated input system video
first basically we need to disable the
action map so let's go into the player
input actions let's access the player
and disable it so we need to do this
first then we're going to need to find
the action so player input actions and
for now let's go into the player and
let's just modify the move up action so
we're going to call the function perform
Interactive rebinding
this one as you can see takes a binding
index and if you remember up here we saw
that in order to modify the move up it's
on bindings index one so let's modify
the one on index one
okay so this is the function this
returns an object of this type a
rebinding operation this is a pretty
complex object where you can modify all
kinds of things add a bunch of
limitations and so on like for example
make a key not be able to be bound to
the mouse or something so there's tons
and tons of options you can play with
over here for the simple thing let's
just add an on complete listener so this
one takes in a convex and this will be
called whenever the interactive
rebinding completes
so over here on let's define and Lambda
so we come back and inside we have this
by the way over here this is the same
line of the expression that we saw
previously so exactly the same thing as
this except when we have just one
parenthesis we don't need to add them
okay so like this so then on this convex
we can see all kinds of things like for
example we can see the action that we
just rebound this is going to contain
all the data on the rebind operation so
for example let's print out the path so
let's go into the action
let's go into the bindings
on index 1 and let's print out the path
similar to a debug.log
and there's actually another one so
let's log the path and also the override
path these are two different things
let's see why in a bit we do this and
after we log we also need to rename on
the player action map so let's go into
the player input actions deep layer and
back enable this okay so we're only
going to need these settings on the
rewind action then we can just call
start in order to start the rebinding
process okay so this should work let's
just call this from the options UI so
over here we have the click let's go
into game input instance and let's
rebind The Binding and for this one is
the move up
okay with this let's test okay so here
if I click on the button and I click on
the T key and if there go it did work so
you can see that it print out the
regular path that is w and the override
path which is C so now if I exit out of
the options go back into the game if I
press W nope it does not move but if I
press T yep it does move upwards okay
great so we have successfully rebound
this one key now here just one thing in
previous versions of the input system
when doing a rebind operation you need
to manually dispose of this comeback
otherwise it would throw a memory error
in the recent version that I'm using
here there's no error so it seems
perhaps it's no longer needed to dispose
of the compact manually but still
there's no harm doing it just in case
over here combat dot dispose
okay so with that the key rebinding is
working except we have two issues the
first one is that it's not very clear
that it's listening for an input and the
second one is that the text options also
does not update so it's on both those
first let's add a visual when waiting
for a key press so inside the game
options UI let's create an empty game
object call this the press to rebind
team
let's stretch it out so put it on zero
on everything okay then inside let's add
a UI image
let's put it in black and once again
let's stretch it out
okay now let's also add a simple text
and for text let's say press a key
to rebind as usual let's put the width
and height on zero put it in bold Center
down the middle with no wrapping and
increase the size by quite a bit okay so
that's our super basic window now in the
code we just want to show and hide this
so let's do that and let's actually
begin with this hidden by default so
let's disable this object so here on the
options UI let's add another serialized
film it's going to be a transform for
the press to rebind key transform
so you have this let's make two show and
hide functions
so we show press to rebind key
we just go into that one game objects
and active this one into true
and another one where we set it to
phones so just
hide and set it to false okay pretty
simple let's make sure to hide this over
here on our start okay just like that
and for showing let's show it when we
actually rebind an action so right in
here but since we're going to have tons
of listeners to these events let's
actually make a nice separate function
to handle all of the rebinding logic so
down here let's make a function rebind
binding
we receive a game input.binding
then first we show the press rewind key
and then let's go into game input access
the instance and time to rebind binding
and pass in the same binding
okay so we have this and now up here on
the button event let's just call in this
function okay very simple so this will
work for actually showing the window but
now we need to know when to hide it and
for that let's use something that we've
used a few times in this course but
never directly let's use a c-sharp
donate as usual I have a dedicated video
on them this is basically how you can
define a field or a parameter of a type
which can hold a function it's another
Super useful CCR feature definitely
watch that video to learn all about it
let's go here on the game input and down
here when we have our rewind binding
over here let's receive a second
parameter this one is going to be of
type action this is one of the built-in
dongates it takes no parameters and
returns void so this one is perfect for
a simple comeback just like this one
let's go with on action rebound and
we're going to trigger this right here
after we achieve the convex so we get
the comeback let's trigger this just
like that and let's also get rid of
these testing logs we no longer need
them so just like this
now back here on the options UI so we've
got that and for the second parameter
let's just pass in the function to hide
that window so hi the press the rewind
key that's it again remember we're
passing in the function itself we're not
calling it so there's no parentheses
we're just passing in the function
itself okay so with this let's test so
here on the options let's rebind the
move W and there you go it does show up
to window and now if I press the key you
better go down hides okay great so this
is working but over here the text is
still not updating so over here on the
second comeback instead of just calling
this function we need to call this and
then also call the update visual
function so as usual let's use a simple
Lambda expression to do exactly both
so let's open and close the parentheses
and we do exactly this
so we hide the price of rebind and then
we update the visual okay that's it
let's test so here we are let's rewind
the move down we press on the T key and
there you go we did rebind and it did
update all right great now let's just
apply this to all of the other bindings
so first up here on the buttons let's
set listeners to all the buttons so
let's see move left
actually be moved down
then the move left move right the
interact button
the interact alternate button and
finally the pause button and for the
bindings this one is the fast binding
the interact alternate then the interact
then the move this one is the right
again make sure you don't make mistakes
here you call them the exact same one so
they move down okay so all of it is
correct here
and over here on the player input let's
do a switch on our binding
so Keys move up we do something and now
we could write this code directly up
here and then make a move down and write
a bunch more code that would work but
that would be way too worthy so let's
write our code in a nice clean way
basically the only thing we need down
here is we need to know the actual
action we're going to rebind and we need
to know the action index so let's just
find up here exactly that so an input
action for the input action
and then an end for the binding index
okay and then over here when we have the
switch for all of our bindings we just
set those so the input action in this
case it's going to be the player input
actions player and it's the move action
and for The Binding index
this one is on index one
then we're going to have the other moves
so they move down is going to be on
index 2.
then left and right
these are on index 3 and 4. okay so we
have all these and now for the other
ones
so for the interact this is the interact
action on binding zero then we've got
the interact alternate and the pause
so interact alternate and the pause
and this one is the pause action and the
interact alternate action and all of
them are on finding index of zero okay
so that's good so over here we are
assigning the input action and defining
index and also one thing we need to make
sure to always assign these values
so let's make sure to add a default here
just make sure it always works okay
great so now down here instead of always
accessing the move let's access whatever
is stored in the input action
and for The Binding whatever it is on
The Binding index okay so now this will
work with all of our bindings so here we
are and let's try rebinding all of them
so let's put them over here on the side
so before it move up let's put on T down
on G A on F then D on H for the interact
on y interact jumped on J and for the
Escape let's put it on E okay so all
these Keys have been rebound let's just
make sure they work so here I am moving
with these keys and yep it does work go
up here to interact and do the alt
interact and now the pause and if there
you go everything works perfectly
alright awesome so everything worked
perfectly although again we have the
same issue as previously so all the keys
have been rebound so it's not correct
right however now if I stop playing and
now if I play again
and nope there's the issue the rebinding
was lost so just like with the sound we
also need to save the new state now
thankfully the new input system has a
function that makes that super easy
let's go down to where we are rebinding
things and when we finish rebinding
let's just go into the player input
actions and let's call this function the
save bindings overrides as Json
this one is going to return a Json
string now if you don't know what is
Json go watch my quick video on it
basically it's a super easy to
understand and widely used file format
it's very easy to read and modify it's a
format where it's stored as just text so
let's look at what this says once we
debug down log over here after rebinding
something let's see so here if I rebind
one of these and if there you go there
we have our Json so the override
Bindings that overload the move on this
ID on this new path so basically we just
need to sort this string somewhere and
just like we did with the sound let's
just store it in the player prefs so
first let's define our constant so
private constring for the player prefs
bindings
and let's call this the input bindings
okay just like this
so then down here after we rebind the
king
let's go into player prefs and let's set
a string on the player prefs
bindings
and we're going to save the overrides as
Json
and after we do let's just make sure the
player perhaps is correctly saved okay
so that saves it then let's go on a way
to unload it so over here on awake let's
load that
let's first do a quick test to see if
there's a save so if the player prefs if
it has a king and if it has this key
if so then let's get it so the player
prefs let's get the string on this key
that returns this ring and we're going
to use the string let's just go into the
player input actions
and let's call the function load binding
overrides from Json just like this and
also let's make sure we do this right
after we construct the object and before
we enable the action map okay so that's
really it let's test so here we are
let's rebind the move up to T okay hit
rebound now stop playing now playing
again and you appeared is still rebound
to T alright awesome okay so here we
created a really nice options menu where
we can modify the volume and rebind keys
the only issue that we still have is
that we can only navigate the menus with
the mouse so let's add support for many
navigation with a controller in the next
lecture
hello and welcome I'm your code monkey
in this lecture we're going to set up
phone controller support for our game
including regular actions and menu
navigation okay so first let's just set
up the controller input I have an Xbox
impact controller connected so let's
open up our player input actions and
over here we have all of our actions and
we already made the move one a long time
ago so let's just add the bindings for
the other ones for example over here on
the interact let's add a brand new
binding let's go into the path and
listen and for interact I'm going to
press the A Button and again here you
can specify just the a button on Xbox
controller or you can use the generic
South button which will mean a on an
Xbox or cross on a PlayStation or B on a
switch or anything else so let's go with
the generic one for the internal
alternate let's add a binding and for
this one I'm going to put it on the X on
the Xbox so the button West
and for the pause let's add let's listen
and I'm going to press the menu which is
the start button okay so these are the
basic inputs let's make sure they work
and thanks to this new input system we
really don't need to modify any code
let's just save this asset
let's wait for the compilation and then
we can do a test so here we are and yep
I'm using my control to move now let's
just wait for the countdown
and go up there and pick up a cheese put
it and slice some cheese yep I can do
that pick up a plate and so on all right
so everything works let's also pause and
yep that also works okay great so
everything works except there are two
issues with the GamePad especially one
with the movement that I only noticed
just now the first issue that we have is
the dead zone right now we don't have
one so if I just lightly touch my
Gamepad joystick there you go it starts
moving automatically in Gamepad games
you should always have some kind of dead
zone to prevent any kind of joy-con
drift thankfully that is super easy to
Zone let's just go into the player input
action so let's go into the move find
the left stick binding
and over here for the processors let's
add one and let's add a stick dead zone
so that's it pretty simple this
basically considers that inputs under
this minimum to be zero and above this
maximum to be one so if you have
joystick drift where when the joystick
is Idle it's always moving by say 0.1
and direction this helps solve that
problem except in our case for a game
we're only using normalized inputs so
actually for our use case let's increase
the minimum by quite a bit I did some
testing in 0.5 Works quite great and the
max that default that is just fine okay
so that's it one problem solved let's
just go ahead save this Ascent now the
other bigger issue that we have is if I
approach a counter and I try and look at
it it's really difficult it tries moving
left and right instead of actually
facing the counter that's because the
logic that we added in a long time ago
that logic to help the character
controller feel better when moving on
diagonals against the counter
that works great for keyboard because
it's digital so it's either moving phone
and left probably right or on the
diagonals
but it messes up the control which is
analog on the player movement if we are
not moving perfectly up or perfectly
down then it's considered a diagonal and
on a Gamepad it's really difficult to
get a perfect just up or just down input
we're always going to have a tiny bit of
either left or right so that's the issue
that we have here and thankfully the
solution is actually pretty simple let's
go over here on to our player script and
let's scroll down into the handle
movement function okay
so we're doing a can move using the
regular move Direction and if it doesn't
work then it's over here that we are
attempting only the X movement or only
the Z movement and for doing that we
made it so we can move if there is
nothing only on the X and if we have any
movement at all on the X so if it is
different from zero basically the issue
here is if the move dear.x is let's say
0.001 that is still different from zero
so it is still going to trigger this
logic so basically let's just widen this
Gap instead of testing literally just
different from zero let's test if they
moved here.x if it is under say minus
0.5 F or if moved here dot X if it is
bigger than plus 0.5 f
so instead of being exactly just on zero
we're only going to consider diagonals
if we are at least moving 0.5 either
left or right so we just did this and
same thing over here except we just test
for this n so we moved here.z and they
move the other dot set okay so like this
it should feel much better on the
GamePad and still work exactly the same
on the keyboard so let's test
so here I am moving around and yep now
it is much easier to just stay around
and look straight at the counter okay so
that's great so I can pick up and this
is all much much easier and the
character is no longer just sliding left
and right Non-Stop okay that's great so
now that this is working let's set
support for rebinding our controller
bindings so over here on the game input
let's do it just like we did for the
keyboard so let's add a bunch more
bindings over here on the enum let's add
the GamePad interact then the GamePad
interact alternate and then the GamePad
pause
okay so we have our bindings then let's
go down and add them to both our
functions so of course the text and then
the bindings so we're here on the text
let's copy pretty much this we're going
to have the GamePad interact then we're
going to have the other two so the
GamePad tracked alternate and the
GamePad pause okay
now for these bindings we're going to
use the same actions so this one is the
interact alternate and over here we have
the interact and over here on the input
actions we saw that we added for all of
them on index 0 we have the keyboard and
on the next one we have all the gamepads
so over here that's literally don't
change for the GamePad let's go into
bindings and access the array on index
one
okay and then over here on the rebind
binding it's going to be pretty much the
exact same thing so let's copy all these
change this to the GamePad interact then
the GamePad interact alternate and then
the GamePad pause some of these all we
need to change is just by an index put
them all on one okay so with that all of
the code over here on the game input is
working perfectly now let's go over here
into our options UI so we've got all of
our buttons so let's duplicate our
buttons let's just go into the
interactive pause and so on let's
duplicate push them to the right side
okay
and just change the name so let's get
into all of them so this one's the game
pad interact button then the game pad
interact alternate and finally the
GamePad Parts okay
also inside let's also rename these
buttons just to make sure the text works
great
and let's also make sure that these show
up behind the press the rebound key so
let's drag them put them above okay so
that's our setup over here on the
options UI now let's go over here on the
options UI script and let's add
references to our buttons and to our
text objects
so let's copy all these the GamePad and
add all these this is the pause the
interact and the interact confident and
then down here the exact same thing
let's add all of these
okay like this now over here let's drag
all of our references so on the options
UI let's make sure to always write the
correct things so the GamePad interact
text the interact alternate text and the
pause button text and then the buttons
themselves so the pause button interact
alt and the interact button again make
sure you always drag the correct
references so check and double check
make sure everything is correct okay
then over here for our code let's first
handle the text over here
so the text for all these
so the GamePad interact text then the
GamePad interact alternate text and
finally the GamePad pause text and we
just go the game file pause the GamePad
interact alternate and the GamePad
interact finally over here on the
buttons let's do the exact same thing
so Gamepad interact interact alternate
and the pause
okay so we added everything let's do a
test and see if everything is working so
over here let's pause the game go into
the options and for the interact let's
modify this one instead of a and let's
put it on B and yeah there you go it did
go so let's close let's resume and now
let's see so if I approach and I press a
nothing happens Press B and there you go
it does interact okay awesome so the
rebinding is all working perfectly
except we have another obvious issue
I can pause with the GamePad however now
with this pause I cannot click on any of
those buttons and if I go back to the
main menu
over here I also cannot do anything with
a controller so at some of that the
first step is on the event system object
look at how it shows us this warning
basically if we're using the new input
system we should be using a different
input Handler here thankfully this is
super easy we just need to click on this
button and yep that's it it
automatically sets it up now the way
that this works is by pre-selecting
buttons in order to better see which
button is selected we should probably
add a more visible color let's go into
our pause window so for now let's hide
over here the options UI show the pause
window and we have these three buttons
let's select all of them
and over here on the right side on the
button we can see one option for the
selected color
so instead of being white which is going
to be really difficult to see let's put
something really visible so let's say
like a bright green okay like this
let's do the same thing for all of the
buttons on the options UI so let's show
this one and find all the buttons so
we've got all of these ones down here
and these three ones up here and let's
do the same thing so on the selected
let's put it all on my screen okay so
all the buttons have a nice selected
color and just like this if we test and
if I pause the game
and right now nothing is selected so
right now I cannot do anything with the
controller however if I press over here
with the mouse on this button and then
let go once outside the button yep look
at that now that button is selected so
now as long as that one is selected now
if I move with the mouse pad yep now I
can navigate through this menu and if I
press on a yep I can essentially click
that button so that's great basically
all we need is to make sure that we
select the button as soon as the pause
menu shows up so let's go over here on
the game pause UI script and then over
here let's go into the show function so
when we show this window when we do
let's go into the resume button and just
call the select function this will make
it selected so that's it and with this
if we test and now here with the game
playing if I pause whilst pressing the
button on the GamePad and if they go
down and selected and now I can select
any option okay that's great so now it
works fully with just the GamePad except
now if I go into options yep now you can
see that the button that is selected is
on the options one over there on the
background so let's also make sure to
select a button on the options as soon
as the options window shows up so over
here on the options UI let's go into our
show function
and let's just select the sound effects
button and just console it okay let's
test so here let's pause go into options
select any of the Lego that did work
okay great except we have another issue
as I move up or down over here on these
buttons you have a look at that some of
them are a bit strange like for example
over here on a I'm moving up and look at
that it actually selected the resume
button behind it so as we are moving up
or down we are actually selecting
buttons on both menus that's very
strange basically what is going on is
that since both windows are visible the
game is trying to guess which button we
want to select basically what is
happening is Unity is trying to use
automatic navigation if we select the
button so let's go for example let's
hide the options and show just the game
pause okay let's select one of these
buttons and over there on the button
component we can see navigation is set
to automatic and we have a button to
visualize and if we click on that yep
over here we can see all kinds of arrows
for example we we can see one over here
on the options that seems to be going to
some button in there that is going to be
the button that is showing over there so
if we move down from the options we're
going to end up over here on the
interact alt button now usually the
automatic navigation actually works very
well the only reason why we're having
problems is because we have both windows
active at once one solution to this is
to make the navigation explicit so let's
hide the options here and over here on
the resume on the navigation instead of
automatic let's put none and then let's
select explicit and if now we have our
own four Fields so we can decide which
object gets selected when we are here
and we move up down left or right so for
example here we would drag for the up
going up we could go into the main menu
so we will drag that button and going
down we could drag the options button so
that's one solution just add the
explicit navigation to every single
button or another simpler solution is
let's leave this one on automatic and it
said we're just going to hide the pause
window once we are in the options window
so over here on the game pause UI let's
see over here we are showing the options
you Ai and when we do let's just call
hide on this so we are going to hide
this window when we show the options and
then on the options we want to know when
the options closes so that we can show
this one again so over here on the show
function let's receive an action this is
what we're going to do when we close the
options let's call it on close button
action
and let's store it up here so let's
store
a simple and private action for this
okay so we have this and then down here
when we have our show function when we
have let's set this equals this we store
this and then we're just going to run
this action whenever we click on the
close button so let's go over here the
close button we've got that one let's
hide the options window and Trigger this
action so now we need is over here on
the game plus UI let's pass in and
basically when we close the options UI
we want to show the POS UI okay so let's
test so here we are let's pause the game
okay let's go into options and open it
and if there go it only shows the
options and over here moving up or down
works perfectly and moving left and
right also works perfectly
and now if I want to go back let's go
into close press it and there you go
back into the pause menu
all right awesome so everything is
working perfectly now the last thing we
need is over here on the main menu so
let's do the same thing first let's open
up the main menu scene
let's save the changes okay and over
here let's begin by doing the same thing
on the event system so let's replace it
okay great
then let's go inside our canvas inside
main menu y let's select our buttons and
once again let's modify the select color
put it on my screen all right and since
over here we only have one menu we could
set a test selected over here on the
main menu UI script
that's one option or we can just go into
the event system and over here on the
event system there's a film for the
first selected so you can just drag the
play button and that will automatically
make it the selected one so it says and
yep the play button starts off as
selected and I can move up or down
and if I press a button yep there you go
here I am playing the game I can pause I
can resume go back to the main menu and
so on all right awesome so here we have
the final thing we needed to make our
game fully playable with the GamePad
thanks to how the input system works and
the menu automatic navigation this was a
pretty simple task for this our game is
pretty much completely done however the
next lecture is also one of the most
important lectures it's all about
publish so let's do that in the next
lecture
hello and welcome I'm your code monkey
in this lecture we're going to add all
kinds of small things to polish our
power game if you are regular on this
channel then you've certainly heard me
say that polish is what separates good
games from great games so as you build
your own games make sure you don't
neglect polish here let's add a bunch of
small tiny things that will make a big
difference in the final game let's begin
with a very simple very visual one let's
just add some ones to our map and first
let's just hide our canvas so that it's
not blocking our view so again over here
we can use the buttons on the hierarchy
to hide it okay great
so let's add some walls and for that
let's create a brand new 3D cube let's
name this a wall let's put it quite a
bit thin so over here on the scale for
the X so let's put it 0.25 then on the
one let's put three so something like
this then we modified Z so let's put it
over here on the side right next to the
counters okay so that's the wall let's
just stretch it out One Direction and
the other one okay so that's our basic
one
now when you included project files
there's a nice one material so let's go
over here into assets under materials
and you appeared as you want material so
let's just drag it and use this one and
if there you go it's just a nice simple
gradient this is also an example of how
you can take something simple and make
it a bit more interesting if you look at
this material the base texture is really
just this it is literally just a simple
vertical gradient texture and then with
the color point to it and looks pretty
good okay so this dual let's put the
wall on on three sides so let's
supplicate this so just select and press
Ctrl D 2.8 let's put one on the other
side so right there right next to the
counters okay and finally the one there
so Ctrl D to duplicate it let's push it
over there on the side and rotate it 90
degrees
and let's put it just like that let's
just scale it to get to that end and to
get to that end okay so we have our nice
walls but over here if we're playing the
game we can still see the floor on the
outside that looks a bit ugly so let's
fix that
let's create another object and let's
create a 3D object another Cube and for
this Cube let's put it over here on the
side and this one let's use the black
material so again in the included assets
there's this nice black material there
you go it's completely black nothing to
it
so let's just use this as kind of a
Hider so let's just scale it quite a bit
and lift it up
okay so there it is a black material
right next to the wall and let's put
another one over here on the left side
and just like that
you can also put another one on the back
there even though I don't think the
camera can see that part but still let's
put it so just put it like that and
stretch it out okay that's good by the
way over here on the outside it doesn't
have to be perfect doesn't have to
perfectly match the camera is never
going to see that position so it doesn't
matter it only matters what the camera
can see and if we pull it like this and
if they're yellow now that looks quite
nice if we want over there we can get it
together just a little bit and we can
also move the camera forward a tiny bit
so over here on this one let's push it
just a little bit to the left okay and
now in the virtual camera
let's play the game
and now here if we want we can push it
up a little bit something like this so
let's put it on this set so let's copy
it stop playing the game and let's paste
it just like that
okay so here's our game and as you can
see with just this one tiny chain just
adding some walls and a nice black
outside just with that it already looks
so much better than having some counters
in wide open space now for another
simple one let's add some nice particles
while the player is moving
so in the included assets if we go
inside the prefab visuals over here is a
nice one for player moving particles
this one as you can see is a particle
system so let's drag it over here into
the world see what it looks like and as
you can see by default it's actually not
spawning anything so I can make sure
that this one is running and nope
nothing is spawning so this is actually
set up in a really interesting way is
that instead of spawning particles all
the time it only emits while moving so
if I click to move this object there you
go the particles start emitting and if I
stop they stop so this one is definitely
perfect for a player particle system the
way this setup is over here on the
emission on rate over time it is set to
zero so it doesn't spawn anything
automatically and it only has over here
the rate over distance so as it moves
it's going to spawn that number of
particles then the other settings
they're all pretty basic so there's some
gravity so they fall down just like the
stove counter particles simulation is
over here on space so that as I move the
particle stay behind this is important
if I were to put that in local and I
move it around look at that this is not
what we want we want the particles to
essentially stay behind instead of
following this transform so that is why
this change is super important if that
one is set to whirl and as I move yep
the particles stay behind okay great and
the other property is around pretty
basic for the shape it's a cone pointing
upwards then for the size of our
lifetime again just a basic curve
constantly becoming smaller and smaller
and down here on the renderer instead of
rendering your quads actually rendering
a mesh and it's rendering a sphere mesh
so that's just so that it looks a little
bit better I think than just having a
Sprite particle okay so that's it so in
order to make this work really all we
need is just attach it to the player
so let's find the player make this
object a child of the player game object
and again let's also make sure to set
all of this to zero so the position on
zero zero and zero
and there you go just with this that's
all we need if we test here we are
stopping there are no particles and as I
start moving if there you go some nice
particles around the player okay great
next let's add a pretty obvious one some
kind of mini tutorial we want a window
to show the controls and the goal of the
game and wait for the player input
before we start the countdown
so for that let's go into our canvas so
let's show our canvas and inside let's
create an empty game object called the
tutorial UI
let's drag this one above the game pause
window so that it shows up behind it
let's double click to center it and
let's press on the 2D button to go into
2D mode okay let's also hide those two
windows so you can actually see what
we're doing so outside all of these okay
great
now this one first of all let's stretch
it to occupy everything so put zero on
everything okay then inside let's make a
UI image for our background once again
let's stretch it put it like this
and for this one instead of black like
we've used for all of our Windows let's
actually leave it on white put it on an
alpha something like half so something
like this just to be a bit different
then on top of this let's make another
image so let's make another UI image and
for this one instead of stretching let's
give it a size so let's put it on 1280
by 800 and for the image I created a
nice image for the tutorial if we go
inside the assets and then inside
textures yup here is a really nice
tutorial image
so let's just go ahead and use it so on
the image let's drag it all right
there's our nice internal image so this
has a pre-based tutorial so the recipe
is coming from the customers then the
player has to prepare the correct
recipes and deliver them on a plate on
the delivery counter so just a very base
tutorial and also over here it's very
important for the player to know how to
actually play the game so there are some
labels for the controls and now we're
going to dynamically add some keys on
top so let's do that let's create an
empty game object call this the king
let's put it on a size of 40 by 40 okay
now let's go inside and inside let's
make an image let's name this the
background
and for the Sprite let's go with the
included Circle so default Circle
and for the size let's stretch it occupy
everything put it on zero zero zero okay
there's our nice key
so we have the background and for the
background let's actually make it just a
little bit darker
and let's also add just a nice shadow so
maybe three minus three and let's also
make a nice upline
let's put it on two by two
full Alpha so something like this just
to be a nice one maybe one by one okay
so that's just the visual and then on
top of it let's add a text
and this one's essentially going to be
the king so let's put a key for the
width and height let's stretch it to
match the parent size okay then for the
phone here let's go with maybe just say
20 let's put it Center down the middle
and also let's put it on bond okay so
that's our nice key indicator
so this is our key and we're going to
have the movement so the movement on the
keyboard is going to have four keys so
let's just implicate so one two three
and four Keys okay then on the GamePad
that one is actually not rebindable so
let's put this one as static
so let's just go inside inside the text
and just say left stick and let's lower
the font size so that it fits in there
okay great
then for some more keys
we're going to have the interact action
then the interact alternate
and finally the pause action
then let's just duplicate these to be on
the other side
okay so these are all of our keys now
instead of having key one two three this
is very difficult to understand so let's
give it some proper names so this is the
key move up then we have the key move
down
then the key moves left then the key
move right
then this one is going to be the key
Gamepad move
then we have the key interact
the key interact alternates
the key pause
this one is the key Gamepad interact
alternate
this one is the key Gamepad interact and
finally the key Gamepad pause
okay all of these and since we're going
to drag references to the text objects
let's also give those a name
so just copy drop it with text
just like this
okay so those are all the names so
everything is nice and organized okay
great now let's make the script to run
this so our tutorial UI let's go down
into our UI scripts create the brand new
c-sharp script for the tutorial UI and
let's attach the script okay
so first let's drag references to all of
our keys we only need the text so let's
do a serialize field of type text mesh
Pro U going again never make the mistake
always use the ugly one if we're working
the UI so the key move of text
so let's add all of these
okay these are all the references then
over here let's drag on and make sure to
drag the correct ones
okay let's double check to make sure all
the references are correct okay they
don't seem correct all right great and
then over here only to pretty much
exactly the same thing that we did over
here on the options so we need exactly
this so let's copy this and over here
and let's do just that
let's see a private void update visual
and on this one let's do pretty much
this so the key move up text
I know this one you get binding text to
move up yep let's just do all the others
okay so those are all the bindings
that's great now let's go over here on a
proud void start and on start let's
update our visual all right and also
let's make sure this updates just in
case the player rebinds something from
the pause menu once the tutorial is
still visible
so we just need to know when that
happens so let's go over here onto the
game input and make a nice event so
public event even Handler let's call it
on binding rebind
okay we have this event and down here
when we have our rebind binding function
we do this we rebind and over here let's
invoke this event
okay just like this
so then on TTR only y let's go into the
game input the instance on binding
rebind let's listen to this event and as
always let's rename this so let's put a
game input okay when this happens let's
simply update the visual
okay that's it pretty simple so let's
test and see if the inputs are correct
and if there it is we do see it correct
so we've got ones we've got e to
interact F and over there we've got the
GamePad okay great so all the buttons
are correct all that's left is the show
and hide so over here let's make the
usual two functions so product void show
and a proud boy in Hind and for these
game objects set active and this one is
going to be into false and this one's
going to be true okay
so for show up here on start let's
actually show it by default even though
it's actually already going to be shown
but still okay then for the hind this
one we want to hide when we press the
interaction
however when that happens we don't want
just this window to hide we want the
kitchen game manager to change the state
so we're here on the kitchen game
manager we currently have the waiting to
start and that one actually has a timer
so we count down the timer and then we
start whereas right now we want it to be
based on player input so let's modify
this to not be based on timer so let's
just get rid of this timer
and now let's see all these errors so
I'm waiting to start we are not going to
count down any timers instead let's
listen to the game input so game input
let's listen to the on interact action
event and rename this to the game input
okay so when we have this event when the
player presses the interact action let's
check if the state if this one is on
waiting to start
if so then let's modify the state so
let's go into State and we're going to
go into the countdown to start and let's
trigger the on state changed event
okay so that's it so we're only going to
change it on the player input and
nothing over here on the updates then
for hiding the tutorial over here one
approach would be to listen to the
interact action and hide it but I think
it makes more sense for this to only
listen to the kitchen game manager state
that way if we wanted we could also
modify how this one changes the waiting
to start
so let's listen to distinct over here on
tutorial we want let's go into the
kitchen game manager the incense and
let's listen when the state changes
so here we are going to check if the
kitchen game manager instance if it is
on the countdown to start active so if
the countdown is active then we're going
to hide this
okay so that should do it now let's just
do one more small thing the delivery
manager is currently spanning a recipe
whilst we're still reading the tutorial
that's not quite right
so let's go over here on the delivery
manager and right now this one starts
off at 0f and starts counting it down
right away
instead of only doing it like this let's
just make sure that we only spawn a
recipe if the game is playing so that's
super simple over here kitchen game
manager instance is game playing if so
then we are going to spawn a recipe and
let's do the same thing on the points
counter so let's go in the plates
counter
so here we are on the plates counter so
we count on time responsive lights but
let's also make sure we only spawn
plates if the game swing
okay so with all of this let's test and
right away here we are we can see our
nice tutorial teaching the player how to
play okay great here we've got the
controls everything and we're currently
waiting for an interaction we can see
over there plates are not being spawned
and recipes are also not being spawned
but as soon as I press the E key
and if there go the countdown starts
playing and we've got everything else
any up there you go the game starts and
after a while yep we've got plates and
we've got recipes alright awesome so
next let's publish the countdown visual
right now it's pretty basic it's just a
static number so let's add a nice
animation to it let's go inside the
canvas let's find the countdown UI so
the game start countdown okay
so here it is we just have some basic
text now let's go into the main game
object and let's add an animator
component
then let's create a brand new animated
controller so let's create a new down
here an animated controller for the
countdown UI over there let's assign
this controller okay now let's open up
the animation window so window animation
open up the animation window okay let's
create an animation clip and over here
on let's name this the countdown UI
number pop-up okay that's great now for
making the animation we want to
basically make it shake and also make it
fade away so one very useful component
is the canvas group so over here once on
the parent let's attach a canvas group
component this one is a really useful
component in this case the main benefit
is it let's just easily animate the
alpha so let's go ahead and turn on
recording let's go into the frame just
before one second so let's go into 60
frames because we are on 60 frames per
second over here let's record the normal
keyframe so let's modify the scale on
the tiny bit just to record it and let's
reset it back to one okay just to record
the keyframe then for rotation let's
rotate on Z then put it on zero again
just record the keyframe okay great so
now we can go back into the first frame
and over here let's first make it
smaller so for the size let's put it on
0.6 then let's rotate it to the left so
let's put 17 over here on the set
rotation okay like that now let's move
up by just three frames so on frame
three over here let's make it quite a
lot bigger so let's put it on 1.3 and
let's rotate it to the opposite position
so -17 okay that's great that's a nice
start now let's put it on frame 10 and
over here let's set the rotation to zero
and for the scale put it on 1.1 okay so
now finally over here on frame 50 let's
set the alpha onto one and then on one
second let's put the alpha zero okay so
let's preview and if they go a nice
simple animation okay so that was great
now we just need to play this when the
countdown happens so let's stop
recording let's go inside the animator
controller so here it is we've got our
number pop-up and we basically just want
to play this animation whenever we want
so let's put it and make a transition
from the any state onto the number
pop-up on this transition let's make
sure we have no exit time and for the
settings over here for the duration
let's put it on zero so that it's
instant okay great now obviously we need
a condition so on the parameters let's
create a brand new trigger call this the
number pop-up let's select that one and
Trigger it on this trigger okay great so
now for handling this logic here we have
the usual question
so do we put this visual Logic on the
same UI script or do we separate the
animations from the UI for me I find
that UI is usually part of the visual so
sometimes I like to mix the two and
sometimes I keep them separate it really
depends on a case-by-case basis this
visual is so simple and so connected to
the actual UI Logics over here let's put
them together so let's open up the game
start countdown script and over here
let's first grab the animator so private
animator for the animator and on private
void awake let's just get the animator
and just get the component of type
animator okay so we have the animator
now we basically just need to keep track
down here where we're modifying the text
we're doing this on every update but now
we need to know when this number changes
so let's basically just keep track of
the current number and the previous
number so first of all over here an end
for the countdown number
and we're going to get this so this is
our countdown number and over here we
set it to string
okay and we just need to use a different
function so instead of Cl lets you cl2n
just to convert the output into an
integer okay great
so we have the countdown number now we
just need to know if this one is
different from the previous one so let's
go up here let's define a private tint
for the previous countdown number
then when we go down here we've got the
current countdown number okay then just
check if it's different
if it is different from the current
countdown number if so then let's update
it so the previous one becomes this one
and now let's fire off the animation so
let's go into the animator and set the
trigger and again we don't want these
strings so let's go up to the top of the
file make a private cons string let's
call this the number pop-up
and number pop-up
okay so we have this end down here we
just set this trigger okay so that's it
pretty simple and just for fun let's
also add a nice sound effect so let's go
over here onto The Sound Manager and
let's make a function to play sound so
just like we did over here for the play
footstep sound let's make another one
for this one let's go and play countdown
sound and for this one let's not receive
a volume or position and we just play
let's say just the warning sound so just
down on Vector 3.0 and with the current
volume
okay so we have this function and then
down here just going to sound manager
instance and play the countdown sound
again we could refactor this code to
separate the Yuan logic from the
animation from the sound that is one
approach and sectionally one thing that
we're going to do in the next polish
stage but this one is also a possible
thing since the UI is only so directly
connected to visuals okay so with this
let's test so here in the options let's
just make sure that we have our sound
effects so let's make sure they are
playing okay great now let's go ahead
and play and there you go we have our
nice countdown number and there you go
it looks great so it looks great and
sounds great alright awesome as you can
see just by adding a simple animation
and some simple sounds that already
looks so much better now the next thing
we want to publish is on the stove so
let's go into our stove back into our
counters back into 3D and zoom in over
here okay let's also make sure that we
hide the canvas just so we can play
around this all right great so there's
our stove and for this we want to add
basically a warning icon on any nice
sound when the meat is about to burn so
let's go inside the stove counter prefab
okay so now inside of this we already
have a nice generic progress bar UI and
like I mentioned if you want to get some
more custom Behavior you can combine a
generic bar like this one with some
specific components so that's exactly
what we're going to do right now so over
here let's create a brand new canvas as
usual let's make it a world space canvas
for position let's put all of this on
zero
let's just lift it up by a bit so set it
on a y of three okay great then let's
add our super useful look at camera
component and make it camera phone okay
now inside let's go ahead create a new
image let's put it on a size of 0.5 by
0.5 okay just a nice square and for the
Sprite there's a nice warning image in
the asset so it's this one here we have
the warning okay great basically we want
to show this when the meter is about to
burn so let's make a screen to run this
and on the canvas let's give it a proper
name so let's call this the stove burn
warning UI
okay so let's make this crypto render so
when you c-sharp script with the exact
same name and over here let's attach a
script okay great so now the first thing
that we need is obviously a reference to
the stove so let's make a serialized
film private for the stove counter for
the stove counter
okay here in the editor let's drag the
reference of the sub counter okay great
so now we basically just need to know
when the food is about to burn and for
that we can actually listen to the on
progress event so let's do a private
void start and on start let's go into
the stove counter and let's listen into
the on progress change event okay so we
have this one
and recently we're going to want to show
this element so let's find a bone show
we're going to want to show this when
the progress normalized is above a
certain amount so let's define a float
for the burn show progress amount and
let's say 1.5
so on this one we show it except
obviously we don't want it to be shown
when the food is just cooking we only
want it to show when it's about to burn
so that means we also need to check the
state on the stove counter so let's make
a function to check if we are in the
state that we want so we're here on the
stove counter let's go down to the
bottom
and let's make a public bowl is fried
and over here we just return if the
state equals state DOT frame
okay that's great so now here we're
going to show if the progress is above
0.5 and the stove counter is on the
Fright state
all right so that's the logic that we
want then we just want to show our
height so let's make the original
functions private show and a private
void hide
and just do game objects and active into
either true or false
and over here if show then let's call
the show function and if not let's call
the Hide function and of course on start
let's start off as hidden okay that's it
let's test just over here in the editor
make sure the reference is right and
let's save the prefab go outside and hit
on point and yep right away there's no
element okay great now I place it and it
won't cooking there's no element and now
once it's on the halfway point for
burning and if there you go we've got a
nice warning okay awesome so now that
this is working let's just add a nice
animation so once again let's go inside
the stove counter and on the burn
warning UI let's add an animator
controller
then let's actually create the animated
controller so let's create a brand new
animated controller
for the stove burn warning UI
then let's assign it okay and over here
on the animation window let's create an
animation
let's put it on the same folder and call
it
for this one let's say flash we're going
to make it Flash and then again for
making it flash let's use the same
component that we used a while ago so
let's add a canvas group so here it is
now we can play around the alpha so
super useful although I should say that
at this point since we just have a
single image we could just record a
change over here on the alpha for the
image itself however one place where
this component is super useful is if you
have multiple images so if over here I
duplicate this one and I put it off to
the side if I change the alpha on one of
them then obviously it only affects that
one but if I go over here and I modify
the canvas group that changes the amp
for both of them so if you have a group
of images then using the canvas group
makes it super simple so anyway so here
we have just our image let's go ahead
and record and let's say we start off on
Alpha zero then after 10 frames going to
Alpha One and after 20 frames back into
an alpha of zero okay so that's it a
super simple very basic animation we
don't even need analogic since we just
want this animation to play Non-Stop so
that's great that should be working now
let's add some sound so for that we
could make another script but already on
the stove counter we already have a nice
sound component so let's open up this
grip the stove counter sound so this is
basically where we're playing or
stopping the sizzling sound so over here
we can just add the warning sound we're
going to play the sound just like we
have over here for the burning UI so
let's actually copy these same
components and over here let's face it
so for this one instead of show let's
give it a proper name so play warning
sound except it's not on say change so
let's actually listen to the other one
so still counter on progress change
let's listen down and it's on that one
that we use this
Okay so we've got that one and then for
playing the warning sound we're going to
want to basically play it every certain
amount of time
so let's make over here a private void
update and an update let's just Define a
private float for the warning sound
timer
and so down here we just count down as
usual time dot Delta time
and if this one is under zero
if so then let's reset it so Define a
certain maximum
let's say 10 times or maybe just five
times per second that should be good so
we have this but obviously we only want
this to run if we should be playing the
warning sound so let's actually save
this one up here so probably won't for
these play the warning sound and then we
set it on this one
and down here let's just go and we're
only going to run this if play the
warning sound then we're going to run
our timer logic all right and then over
here all we need is to play that warning
sound
so let's actually go into The Sound
Manager and just like we added the
countdown sound let's add another one so
let's say the play warning sound and for
this one let's receive a vector 3 for
the position and we're going to play the
warning sound on this position so now
over here on the stove counter let's go
into The Sound Manager the instance and
let's play the warning sound and pass in
the stove dot transform that position
okay that should do it so we now should
have a nice warning sound and over here
we should have a nice animation on the
burn warning UI so let's see both those
okay so let's pick up some meat and drop
it and right now it's cooking okay great
and once it gets a halfway point
if there go now we have a nice warning
sound all right awesome let's just add
one more tiny thing let's make the bar
itself also flash red when we're about
to burn so once again let's go inside
the stove counter and on the progress
bar UI let's add a nice animator and
let's go ahead and make one so let's
create a new animated controller for the
stove burn flashing bar
let's go ahead and assign it so it's the
one on the progress bar let's add the
stove burn flashing bar then on this one
let's create new animation let's go
inside the assets animations let's make
one and just call it idle for this one
we're going to want the exact same color
as the normal color so let's go into the
bar and set the color just save a
keyframe over there okay so that's what
we want now let's make another animation
so let's stop recording and let's
actually duplicate this one so duplicate
it and for this one name it flash now of
course we need to add it to the animated
controller so let's go over here and
drag it on top okay now for the
animation let's select the Flash and for
this one let's go ahead click on record
let's start off on this one and after a
few frames so let's say maybe after 10
frames let's Flash in red and after 20
frames let's copy paste the same frame
okay so that's our nice flashing bar now
let's just set it up so let's go into
the animator and over here we're going
to have a transition from that
deformation form flashback now all we
need of course is an animator to control
this so let's make a new animator
parameter let's make it a Boolean and
call it is flashing and again make sure
to be careful with cane sensitive
okay so from idle into flash let's go
ahead remove the exit time for the
duration make it instant so zero and for
the conditions when that one is true
okay great and for going back once again
same thing so instant and let's make the
condition when it's false okay that's it
super simple now let's make a script to
run this so let's go ahead create a
brainy sharp script for the stove burn
flashing bar UI let's go ahead and add
it to the bar so that's the flashing bar
UI okay over here let's do pretty much
the same thing that we did on the other
one
so let's go over here onto the stove
burn warning UI I might actually copy
exactly this so let's go on this one and
paste this one then back here in the
editor let's drag the reference to the
self counter and over here the logic is
going to be very very similar so the
only difference is we have an animator
so the animator and we're going to grab
it on private wide awake and later get
component of type animator
so we have the animator then let's
define the parameter so private con
string
for the is flashing
and let's set it is flashing okay we
have our parameter and now down here
instead of showing and hiding we'll just
go into the animator in order to set a
ball
and the bone will be the is flashing and
let's set it based on show so either we
show or hide and we actually don't need
these functions and by default of course
let's leave it on false okay so that's
it super simple Let's test just make
sure to save the prefab and hit on play
okay let's go ahead and cook so let's
pick it up and drop it alright so it's
cooking let's wait for it to be burning
and as soon as it gets there yeah there
you go we've got a nice warning a nice
flashing bar and a nice sound effect so
all three warnings making ourselves much
more polished alright awesome now just
for balancing let's play around the
timers so let's go into our script ball
objects on the frying rest BSO let's
make this one take five seconds
then on the burning recipe for this one
let's make it take six
and finally let's also add another stove
so let's take our self counter duplicate
the prefab let's put it over here so
rotate it to the side and let's get rid
of this one and put this one right in
there so on 7.5 0 and minus 1. all right
so we now have two stoves I can put one
cooking put another one and I can start
cutting down some cheese start cutting
and before they start to burn what's
actually here there you go that one is
about to burn so let's pick it up
quickly and that one is actually gonna
burn but I got it okay great all right
awesome everything's working great now
for one more polish element let's make a
nice visual when we deliver either a
correct or incorrect recipe I think it
wouldn't look good as a warm canvas on
top of the delivery counter so let's do
that let's over here find the delivery
counter let's go inside the prefab and
now in here let's create a new UI canvas
let's name this the delivery result UI
and as usual let's make this a worm
space canvas so put it on worst face
and for the position let's actually lift
it up and then we're going to make it
look at the camera but just like this it
might actually go inside the wall so
let's put it over here to the side a
little bit so let's put it on this
position so on the X of minus 1.6 on a y
of three and on a z of 1.2 okay that's
the position so right there that is
going to be unlocking at the camera now
inside let's create a new UI image it's
going to be our background and for the
size the width and height let's put it
on 2.2 by 0.9
okay that's our background for the
Hunger let's tinted in a nice green so
let's put it something like this
then let's also add a nice outline let's
put it on full Alpha and for the size
let's put it on 0.1.1 then let's also
add a nice shadow component for this one
leave it on half Alpha and let's put it
on 0.2 and minus 0.2
okay so that's a nice visual now on top
of it let's create a new UI text let's
call it the message text and for the
message we're going to say something
like delivery and then underneath
success let's put it on a width and
height of zero let's put it on a super
tiny font so let's say just 0.25 let's
put it in bold and put it down Center
and get rid of wrapping okay that's it
let's just push it a little bit on the
left side so on minus 0.32 on the X okay
and now next to it let's make another UI
image for this one call it the icon
image let's put it with a size of 0.5 by
0.5 and put it over to the right side so
on an X of 0.7 okay and now for these
Sprites including the assets are too
nice sprites so there's a nice cross for
when we get it wrong and there's a nice
tick okay so that's the setup that we
want now on the delivery result UI let's
go ahead add our own look at the camera
component and for this one let's go
different so instead of the camera four
let's go ahead with the unlock at
inverting so there it is this is our
setup now let's make the script run this
so let's go ahead create the new UI new
c-sharp script for the delivery result
UI let's attach the script and open okay
so now here on let's make serialized
films for our elements so a serialized
film
first of all for the background image
and this is actually going to be a Type
image image inside in the engine.ui okay
our background image then we're going to
have another one for the icon image and
we're going to have another one this one
is a text mesh Pro e GUI for the message
text
okay let's save okay so let's drag the
references to the background the message
text and the icon image okay great and
over here let's listen when a delivery
is delivered so let's make a private
start let's go into the delivery manager
the instance and we have all of our next
events so we've got a success and a
field so let's listen into both them
so both the success and on the recipe
failed let's listen to all these and as
always let's write good point code and
rename this so the delivery manager on
recipe success and for this one is the
on recipe failed
okay we have both of our events
so over here it's actually going to be
very simple we just want to play around
the text the icon and the background
color so for example when we fail let's
go
and we want to set the background image
to about a red so for defining the
column let's actually go here and Define
a color for the success color and we're
going to have another one for the failed
color
and then for the Sprites let's also have
that so Sprite for the success Sprite
and another one for the failed Sprite
okay those are on the elements so we're
here in the editor let's just set them
so for the success column let's actually
use the exact same color by the way
here's a quick tip if you go up to film
for example like this one on the color
you can right click and copy and then go
into delivery results and over here
right click and paste there go the
perfect color then for the final color
let's go with the red maybe a bit darker
and also importantly make sure you set
the alpha to phone okay so we have a red
nice and like that okay then the success
Sprite this one is going to be the tech
and for the fail this is going to be the
cross okay those are all of our elements
so over here when we fail let's go into
the background image and set the color
and let's put the fan color then for the
icon image let's set the Sprite to the
Fey on Sprite
and for the message text let's set this
one for delivery and then failed
by the way this backward slash n this
means a new line so we're going to let
you set the text on this one so it
essentially means that it won't write
delivery then new line and then failed
underneath just make sure you're using
the Packer slash and not the forward
slash so use the backwards one there you
go there's a new line okay so that's the
on recipe film and now on the recipe
success let's use the success color the
success Sprite and over here the
delivery success okay so that's great
that should be working now just one more
visual thing let's add a nice animation
so just like we did previously let's go
over here over here and let's add an
animator component
let's create an animation for this one
for delivery result UI so let's go up
here create a brand new animated
controller for this and let's go ahead
and assign it so delivery result UI all
right now let's make an animation so
this delivery result UI let's call it
just pop-up and for this one let's do
just like we did for numbers so let's
scale and rotate it however if we rotate
that's actually not going to work that
is because we have the unlocked camera
and this one is already going to be
setting the rotation so we would end up
with this script finding the animator
for the rotation so that would mess
things up however one nice and simple
solution to this
basically we just put this inside
another game object so let's create a
new game object and let's put it inside
what's an empty game object for the
delivery result rewind then look at the
camera
so we have this one now the reason why I
created it inside is that so over here
we can set everything to zero and now
with that one on zero we can go ahead
and drag this outside of this object and
there you go that one keeps the exact
same settings and on this one we can add
the unlocked camera component and set it
up just like we had so then we'll look
at inverting and on this one we're going
to make a channel live down and there
you go now everything is on zero exactly
as it should be and on this one we can
get rid of the unlocked camera and now
we can indeed play around the rotation
so for the animation let's just go ahead
and set it so for this one let's go up
to one second
and let's record a keyframe on a scale
of one and on a rotation of zero then
let's go back into the beginning and for
this one let's scale it backwards so
maybe something like this maybe a 15
let's put it quite a bit smaller then
let's go up by three frames let's put
that one on -15 so rotation on the other
side and put it quite a bit bigger and
then on frame 10 put it on say 1.1
with a rotation of zero just like that
so there you go there's a nice pop-up
and for the alpha let's also go over
here into the 50 and let's just add the
canvas group let's set this one over
here is on one and then we scroll it
down to zero okay so that's our nice
animation let's stop recording let's
open up the animated controller and over
here let's make our nice animations
transition so transition from any state
into that one let's make it based on a
trigger let's call it just pop-up
and for this one this says no exit time
duration of zero and let's go when the
condition when we have this trigger okay
so that's it although one thing by
default this animation is going to Loop
so let's just go ahead we can select the
animation and over here let's just
untick Loop time so that way the
animation will not Loop okay so that's
great now let's go into the script and
over here let's get our animator so
private animator animator
let's get the animator just get
component of type animator
and let's define over here the private
constring for the pop-up
so we have this and then when we have
either fail or success let's just go
into the animator
and let's set the trigger for our pop-up
both up here and over here now we just
have obviously one issue which is that
it starts off as visible we don't want
that so over here we can just do game
objects set active into false in order
to hide it and when we get either of
these let's set it both to true
then afterwards the animation won't make
it invisible so it will still be active
but it won't be invisible so that's fine
so just with this everything should be
working as we want so let's test let's
just make sure to save it and go back
okay so here we are let's try delivering
an incorrect plate and there you go
Gotta delivery film okay great now let's
try delivering a correct one so someone
wants a cheeseburger so let's cook it
slice some cheese let's get some bread
so bread cheese and pick up the burger
and deliver and there you go a nice
delivery success all right awesome
okay so with these handphone changes you
can already see how we made quite a big
difference in our game we didn't do
anything to change any core mechanics we
just made what was already there pop out
we added a nice visual boundary to make
the map look nice we added some nice
particles when the character is moving
then we added a nice tutorial and
controls right as the game starts we
also added a bunch of effects on the
stove so it flashes has a warning and
some sound and lastly we also added a
nice pop-up when delivery is delivered
whether correctly or incorrectly
now of course we can always keep
publishing the game until Infinity
there's always more small things you can
add to punish the game just a little bit
more but at this point I'm very happy
with what the game looks like so after
all this work let's go into the next
lecture where we're going to play our
game from start to finish and see what
we've done
hello and welcome I'm your kudmaki in
this lecture we're going to look at all
the work that we've done and have some
fun playing the final game okay so here
we are in our nice starting main menu
it's simple but it works I actually
thinking looks pretty good so we have
our main menu working and we also have
the unloading system that we made so as
soon as I click on Play There You Go
loads in loading scene and here we are
on the game scene so we start off with
our really nice tutorial window and down
here we have the controls of course some
of these are dynamics so depending on if
the player rebinds or something this one
is going to update so we can look at
this window for as long as we want the
game is paused in the background so it's
on a paused game state
then whenever ready we can interact
so again that's the game input class
listening to the input and again all of
the code in here is really nice and
clean so when we press enter key the
tutorial isn't directly listening to
that but rather the general kitchen game
manager that main State machine is the
one listening to the input and this one
is listening to that state
so our logic is very well organized all
of the elements only listen to the
things that make sense to them so
anyways here we have tutorial let's
interact and there you go we've got our
nice game start countdown some really
nice animation really nice sound and yep
here we are then we've got our clock
showing the game time and on the left
side we can see our recipes once again
all of the elements they're all Dynamic
they're all spawn randomly and the icons
for all of the recipes they're also all
Dynamic so over here we have the
character control that we built we have
the collisions that we implemented and
of course we have the raycast testing
for interaction so we can identify all
the objects in front
let's begin delivering some recipes so
for example we need to cook some meat so
let's go ahead put it on the stove so
here is the really nice tape machine
that we built so we've got all the
various States we've got the visual
completely separated from the logic so
everything is really nice and of course
here we have the nice burning elements
that we added in the Polish lecture so
that one is burned so let's go ahead and
use the trash bin to get rid of that
so let's go ahead cook another one and
let's make a cheeseburger so let's put
some cheese let's listen to the aunt
interaction key and we can slice the
cheese we can pick up the meat pick up
the cheese then also pick up some bread
and deliver the recipe and there you go
our nice polish visual all right awesome
so here you can already see everything
that we've built the character the
physics the logic the input all of the
UI elements all of the worm UI elements
of the various counters and how they are
on prefab variants of the plates the
separation between the visuals and logic
separation between the sounds and logic
of the Polish elements that we made over
there the nice shadow graph that we made
then of course some of the basic things
that a lot of tutorials won't teach you
like for example how to make a pause
menu how to make the options
how to modify the Sound and Music Volume
how to rebind the Keys and so on
so with all that here throughout this
course we'll learn how to make a really
nice game with lots of interesting
interactions which you can now apply to
any kind of game any kind of genre you
want so like I mentioned in the very
beginning
you can take pretty much what we've made
here which is really just a character
controller and a bunch of interesting
interactions you can take everything
that you've learned here and make
something on a Sci-Fi space like for
example make something like Among Us you
can make something like FTL or perhaps
make some kind of survival crafting game
some of the interactions you would have
like resource nodes in the world then
you can interact together those
resources so with that you could build
something like rust or Minecraft or
Don't Starve so hopefully in this course
you'll learn a ton that you can now
apply to your own custom original
projects and if you've made it this far
then congratulations let's go into the
next lecture where I'll give you my
closing thoughts
hello and welcome I'm your code monkey
and congratulations you have completed
this course awesome seriously congrats
looking at the stats on my courses very
few people stick with it until the very
end so if you're hearing this then
that's excellent you're on the top 10
percent it means you are serious about
learning game development and I
generally hope this course has helped
you on your own Game Dev Journey
throughout this course you'll learn
about the basics of unity and c-sharp
you'll learn how to make a character
controller how to do a physics raycast
and use that for both Collision
detection and identifying objects to
interact with you'll learn about c-sharp
interface and events two extremely
useful c-sharp features you'll learn
about script mode objects how to use the
new input system should graph and tons
tons more and the most important thing
of all you'll learn how to build a
relatively complex game while writing
good clean code I really hope that's the
main takeaway you'll learn from this
course learning how to write better high
quality code learning how to refactor
how to keep the visuals and logic
separate keep the UI the couple from
logic learning all those things has now
made you a 10 times better developer
than when you started
so I really hope you enjoyed learning
all that let me know in the comments
what was the most important thing you'll
learn throughout this course I really
hope this was very fun and very
educational if you enjoyed my teaching
style check out my other courses I
really think the turn-based strategy
course would be excellent for you right
now it Dives even deeper into some
Advanced topics and since you've watched
this entire course all the way you now
have all the knowledge needed to follow
that course it will help you really
simply the final knowledge you gained
especially everything related to writing
good high quality clean code and since
you use Unity check out my ultimate DND
overview course it covers lots of tools
and features of the engine so you can
really use all the tones at your
disposal to make any game you can think
of alternatively if you like visual
scripting I have course on that or learn
how to make a really nice Builder
Defender game and definitely make sure
that you wishlist my upcoming steam game
total one Liberation I won't be posting
devlogs and in those you will see how
the code that I use in my own steam game
is on the same level of quality as what
you learned in this course okay so
that's it for me this course was a ton
of work so I generally hope it helped
you a ton on your gamedev journey thank
you so much for watching and I'll see
you next time
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.