- In this video, you'll
learn how to create
simple pathfinding using
Unity's NavMesh features.
At the end we'll have a
working pathfinding system
where the player can click
anywhere on the level
and the character will then
find the shortest path there.
To do that, we'll be
baking a navigation mesh
using the NavMesh surface component,
which allows us to define
walkable surfaces for our agent.
We'll then write a script
to control a NavMesh
agent along the surface.
Also, this video is sponsored by Unity.
All right, let's get started.
So as you can see, I've set
up this simple example scene.
In here we have a player,
that's the green cylinder here,
as well as a tiny level.
The level consists of a ground
cube and on top of that,
some walls and that's pretty much it.
Now the improved high
level NavMesh components
are available now.
As you can see, I've included
them in my project here,
you can use the link in the description
to get both the NavMesh components,
as well as this example scene.
All right, so the first thing
that we want to do is, bake a NavMesh.
This means that we will
define what surfaces
are walkable for our agent.
To do that, let's go to the hierarchy.
Lets right click, go create empty,
let's reset the transform on this,
and let's rename it to NavMesh.
Lets then drag it to the
top so we can easily see it.
So this game object is
going to be responsible
for baking our NavMesh.
To make it do this, lets
say hit, "Add component."
And we'll add in the
NavMesh surface component.
Here we have a few different settings,
but if we just go ahead and hit bake,
we can see that right away
Unity creates a NavMesh for us.
All the blue tinted
areas represent surfaces
that our agent can walk on,
and so we can see that he
cleverly avoids all the walls.
We can also see that the agent,
can currently walk on
top of some of the walls
and that the NavMesh currently treats
our player himself as an obstacle.
To avoid this, we edit the include layers.
Here we can select what layers
we want to include when
baking our NavMesh.
In our case, we don't want
to include our player,
so we can go select our player,
go to the top right where it says layer
and add a new layer and
we'll create a player layer.
We'll then select our player
and make sure to assign
this new layer to him.
Then when we go back to our NavMesh,
we can simply disable this layer.
When we then hit bake,
we can see right away,
our NavMesh simply ignores our player.
So now we can easily control what parts
of our environment we want
to take into consideration
when baking a NavMesh.
We can also choose whether
we want to bake on NavMesh
from the Renderer meshes,
meaning the actual look of our level
or using physics colliders.
Now I don't currently have
any colliders in my scene.
So if I go ahead and hit bake,
we can see that nothing really appears.
However, if I go in here and
add a collider to the ground,
I'm going to add a box collider
and then go back to the
NavMesh and hit bake,
we can see that this now shows up.
But we can simply use the
Renderer meshes and rebake that.
Finally we have a setting at the top here
called the agent type.
And right above this, we have a drawing
with some different values.
If we go under the agent type,
we can open up the agent settings.
This is part of the navigation window,
you can always bring this up
by going window, navigation.
Now here we can choose some
properties for our agent.
And these properties will
affect how the NavMesh is built.
Right now it's just
using some default values
for a regular humanoid character.
But if we go ahead and hit the plus sign,
we can create another one.
This one is going to be an Ogre,
we can increase the radius,
because he's probably
going to be fairly big,
we'll set that to one.
I could also imagine
him being pretty tall,
so we'll set the height to three,
then we're going to
adjust the step height,
which is probably going to
depend on the length of his legs,
I like to imagine that
he has pretty short ones.
And finally, we can adjust the max slope,
which is how well he can
climb angled surfaces.
Let's say that he's fairly lazy,
so he'll only do about 30 degrees.
Now if we were to go back to the inspector
and change the agent type
to Ogre and hit bake,
we can see that our Ogre will have
a much harder time
getting around our maze.
In fact, there are plenty of places
that he won't be able to get through.
I'm just going to change this
back to humanoid and rebake.
Now we don't want our
walls to be walkable.
So to change this, we can
go and select our walls
and here we'll add another component
called the NavMesh modifier.
The NavMesh modifier, allows
us to change NavMesh settings
for a given object.
We could for example,
ignore it from build,
which means that if we rebake our NavMesh,
it's just going to
completely ignore our walls.
We could achieve the same effect
by simply assigning our walls to a layer.
However, we do want our walls to be used,
we just don't want them to be walkable.
So we'll deselect ignore from build
and instead use override area.
This allows us to change the
area type for this object.
If we select this, you
can see that we have
three default area types;
walkable, not walkable and jump.
As you probably guessed,
if we select not walkable
and we generate.
Voila!
Our player can now only
walk on the ground.
Finally, we can choose what
agents this is going to affect.
By default, this is set to
all, but we can be specific.
This allows us to create areas of the map,
that are different for each agent.
Say if you're creating an RTS game
and you don't want your regular
units to pass through fire,
but you want your fire elementals
to freely walk past it.
So affected agents can
actually be really useful.
Now that we've set up our NavMesh,
we're ready to start
moving around the player.
To do this, we're going to
add a component to a player
called the NavMesh Agent.
A NavMesh Agent is a character
that can navigate around the mesh.
Here we have a bunch
of different settings.
We'll look into these in a second.
But first, we want to
create a simple script
that will control our player.
So we'll hit add component
and we'll create a script
called player controller.
Lets say create and add,
let's double click it
to open it up in Visual studio.
Now before we start scripting,
let's have a look at how to go about this.
So controlling a NavMesh Agent in Unity,
it's actually really easy.
Most of the time, we use a simple function
called SetDestination.
This allows us to input
some kind of position
and our agent will then automatically
find the shortest path there.
In our case, we have a level
and on top of that
level, we have a player.
We also have a camera
that looks at our level.
And we want to be able to
click on some part of the level
and then have our player
automatically move to that location.
To do that, we'll look for
some kind of mouse input.
And when the player presses the mouse,
will send out a ray,
to the point where the player pressed,
will then look for where this ray hit
and will get the position of that point.
And then by using set
destination on the agent,
will have him automatically
calculate a path
and move to that location.
So to do this in code,
we first want to remove
our start function.
And inside the update method,
we want to check if the player presses
the left mouse button.
To do this, we'll write if,
we'll go into the input class,
and we'll use a function
called GetMouseButtonDown.
Here we can specify what mouse
button we want to check for.
We want to check for left mouse,
which has the index of zero.
We then close off our IF statement
and in here we can specify
what we want to happen
when we press our left mouse button.
In our case, we want to
use the current position
of our mouse on the
screen, to send out a ray.
We can get the position of our mouse
by going Input.mousePosition.
And this is our current mouse position
in screen coordinates,
but we need a function
that can convert this to
a position on the screen,
into a ray that we can shoot out.
Luckily, our camera has a
function that does exactly this.
So we need to go to the top here
and create a reference to our camera,
we'll create a public Camera,
let's just call it cam.
Then at the bottom here, we can use cam.
and then we want to
access the function called
ScreenPointToRay.
And this is going to take
in our mouse position,
and it's going to convert it
to a ray that we shoot out,
in the direction that we click.
We then want to store this
ray in a another variable.
So we'll create a variable of type Ray.
Let's also call it ray and set it equal to
whatever we get from this function.
And before we actually shoot out this ray,
we want to have a variable
that we can use to store
information about what it hits.
To do that, we create a RaycastHit,
and let's just call it hit.
So now we're ready to shoot out the ray.
To do this we write Physics.Raycast,
we'll feed in the ray
that we want to shoot.
And remember, we want
to take the information
about what we hit and where we hit it
and store it inside of our hit variable.
So we'll write out and then hit.
This is going to shoot out our ray,
but we don't actually
want to move our agent
unless our ray hits something.
If we just click somewhere
where there isn't an object,
then we don't want our
agent to do anything.
This is in fact really easy to do,
because Physics.Raycast will be true,
if we hit something
and false if we didn't.
So we can actually turn
this into an IF statement.
At the beginning here we'll write, if,
and we'll make sure to close
off the parentheses as well.
And then we can open and
close our IF statement.
So what we're doing here is
basically checking to see
if we click our left mouse button.
If we do, we take our
current mouse position
and create a ray in that direction,
we then shooting out this ray
and we are gathering information about
what we hit in the hit variable.
And in the event that our
ray actually hits something,
we're going to continue
into this IF statement.
And so this is where we want
to go ahead and move our agent.
And whenever we're working
with the NavMesh system
through script, we need
to make sure to include,
so at the top here, we'll
write using UnityEngine.AI,
we can also go and remove our
two namespaces at the top,
because we won't be using those.
And now to move our agent,
we of course need a reference to it.
So at the top here, we'll
write public NavMeshAgent,
and we'll just call it agent.
Then down here where we
want to move our agent,
we'll write agent, and
then we'll use the function
that we saw before, called SetDestination.
And the destination that we want to set,
is the point that we hit.
So, hit.point and that
should be all of the code
that we need to do.
So if we now go into Unity,
we now have two empty fields
under the player controller.
Here we'll drag in our main camera,
as well as our NavMesh Agent component.
And if we now hit play,
we can see that we can
click anywhere on our level,
and our agent will try and
find the shortest path there.
In fact, we can even click
again to change direction
while the player is moving.
Pretty awesome.
We can also configure steering settings
under our NavMesh Agent.
Here, we can change the speed,
let's set that to eight,
the angular speed, which
means how quickly it rotates,
lets set that to 180.
The acceleration, which means
how quickly it starts moving
or changes direction, we're
going to set that to 15.
And finally, the stopping distance,
is how close we need to
get to the end of our path
before the agent stops moving.
I'm going to set that to 0.1.
If we play now, we
should see that the agent
moves around a lot quicker and
we now have a working demo.
Yay!
That's pretty much it for this video.
In the next one we'll dive
further into the NavMesh system.
So make sure subscribe to
get notified once it's out.
On that, thanks for watching
and I will see you in the next video.
Thanks to the awesome Patreon supporters
who donated in February.
And a special thanks to
InCodeWeTrust, Patrick McGinley,
Diego Gayk, Frank, Tristin
Daum, Duy Nguyen, Beffio,
InfinityPBR, Yorai Omer,
Hans Hoftun, Cyborgmummy,
Derrick Heemskerk, Faisal
Marafie, Beard or Die,
DoubleTap45, James P,
JDelaay025, SupermanTheGr8,
John Beauregard, Dennis Sullivan,
Jason Lotito, Alex
Rakitsky, Bjørn Furuknap,
Svetlin Svilenov, Jin, Sascha Hopstein,
Sune T Jacobsen, Gregory
Pierce, James Rogers,
Robert Bund, Youdaman,
Rob Fearn and Erasmus.
(sighs)
You guys rock.
