Navigation Using NavMesh in Unity
In this tutorial we will learn about Navmesh in Unity, how to create it and use it on your game as part of navigation.
Navigation and Pathfinding in Unity
Have you ever wondered how the various NPCs (Non-Playable Characters) in a game move around the game world, avoiding objects and even sometimes avoiding you, only to pop out from behind you to give you a jump scare. How is this done so realistically? How do these so called bots decide which paths they should take and which to avoid?
In Unity, this miracle (not so much once you know how it works) is achieved using NavMeshes.
NavMeshes or Navigational Meshes are a part of the Navigation and path finding system of Unity. The navigation system allows you to create characters that can intelligently move around the game world, using navigation meshes that are created automatically from your Scene geometry. Dynamic obstacles allow you to alter the navigation of the characters at runtime, while off-mesh links let you build specific actions like opening doors or jumping down from a ledge.
Different Components of NavMesh
The Unity NavMesh system consists of the following pieces:
-
NavMesh (short for Navigation Mesh) is a data structure which describes the walkable surfaces of the game world and allows to find path from one walkable location to another in the game world. The data structure is built, or baked, automatically from your level geometry.
-
NavMesh Agent component help you to create characters which avoid each other while moving towards their goal. Agents reason about the game world using the NavMesh and they know how to avoid each other as well as moving obstacles.
-
Off-Mesh Link component allows you to incorporate navigation shortcuts which cannot be represented using a walkable surface. For example, jumping over a ditch or a fence, or opening a door before walking through it, can be all described as Off-mesh links.
-
NavMesh Obstacle component allows you to describe moving obstacles the agents should avoid while navigating the world. A barrel or a crate controlled by the physics system is a good example of an obstacle. While the obstacle is moving the agents do their best to avoid it, but once the obstacle becomes stationary it will carve a hole in the navmesh so that the agents can change their paths to steer around it, or if the stationary obstacle is blocking the path way, the agents can find a different route.
Courtesy: Untiy NavMesh Documentation
Well all this is fine but this is all just theory. This just tells us what all tools exist. To know how to use them, that is an entirely a different ballgame altogether. To learn the implementation of these tools what’s better than an example?
Time for an Example!
What we aim to do here, is that we wish to create a maze kind of scene, in which we will place our player. We will implement the NavMesh in such a way that on clicking a certain point in the maze, the player object will automatically start moving and reach the selected (clicked on) spot on the maze. Easy? Well, pretty much.
Setup and Downloads
The components that we will be using are not included in the standard installation.
Clone or download the repository from the download links below, on the Unity Technologies GitHub by clicking on the green Clone or download button. After that, open the NavMesh Components Project using Unity, or alternatively copy the contents of the
Assets/NavMeshComponents folder to an existing Project.(Check unity version before downloading)
Unity 5.6 NavMesh Download
Unity 2017 NavMesh Downloads
Unity 2018 NavMesh Download
The Scene
The scene that we will be using will look something like this. The green capsule is our player who we will try and move. The orange objects are the walls that we will avoid and the black object is the floor that we will walk upon. You can try to create this scene by yourself (do try). If not, click the link to download the scene.
Download Scene //Place the correct link.
Baking the NavMesh
Baking? Is the Nav Mesh some kind of cake? Well.... in a way, yes. See, Nav Meshes are calculated and generated by the Unity engine. This process of calculation and generation of the Nav Mesh is
referred to as Baking.
So what we need to do now is to bake our NavMesh.
-
To do this create an Empty Object in the Hierarchy Tab, name it “NavMesh”, and reset its transform (do it yourself).
-
Select this “NavMesh” object in the Hierarchy and click on Components > Navigation > NavMeshSurface.
-
Now just to see the beauty of NavMesh, hit Bake.
-
On hitting bake, we get the above image. The blue region shows the surface that is walkable. The current bake of the NavMesh is not what we want. What we want is that only the flat part of the floor is marked blue. To make this happen, we will change the properties of the agent to match our Player. So, select the Agent Type drop down and click on Open Agent Settings.
-
Now in the Navigation tab, click on the + icon to create a new Agent Type and input the parameters as shown in the image.
-
Now clicking on Bake will have the desired effect. This is the path that we will need.
-
Now you will notice that the path treats our Player as an obstacle and hence there is no path under the Player. To remedy this we need to put our Player into another Layer and unmark the layer from the include layer setting. To do this click on the Layer drop down and select the Add Layer... option.
-
Now in the Layer view, type in “Player Layer” in a free layer space and hit Enter.
-
After this, select the NavMesh object from the Hierarchy and in the inspector, click on the Include Layers drop down and uncheck the Player Layer.
Now select the Player object in the Hierarchy, select the Layers drop down and click on “Player Layer”. We have thus changed the layer in which the Player object exists.
-
Now click on bake again to get the NavMeshWalkable Surface.
-
Now even though it seems that the walls are off limits, we have not ensured it. To ensure this we have to specifically make the walls “Not Walkable”. To do this first select all the wall objects from Wall (0) to Wall (9) in the Hierarchy, then select the Add Components drop down. From this drop down select Navigation > NavMeshModifier. Now all the wall objects have this component.
-
With all the wall objects still selected, in the Inspector check the Override Area attribute on the Nav Mesh Modifier. Now select the Area Type drop down and select “Not Walkable”.
-
Now finally click Bake again and bask in the beauty of the NavMesh you created.
Setting Up the Player
Setting up the player is pretty easy. We just have to add the “NavMeshAgent” Component to the Player object.
To do this:
- Select the Player object in the Hierarchy.
- In the Inspector, click on the Add Components drop down.
-
From the drop down, select Navigation>NavMeshAgent.
We get this component attached to the player. Now our Player can access the NavMeshSurface. You can try and play around with the Steering and Obstacle Avoidance settings as they deal with the actual movement of our Player.
Making Our Player Move
To make our player move, we will attach a script to it, which will make the NavMesh move our player to the point on the floor that we click on.
To do this attach a new C# script, named “Controller”, to the Player object.
using UnityEngine;
using UnityEngine.AI;
public class Controller : MonoBehaviour
{
public NavMeshAgent playerAgent;
void Update ()
{
if (Input.GetMouseButtonDown (0))
{
Ray camRay = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast (camRay, out hit))
{
playerAgent.SetDestination (hit.point);
}
}
}
}
Let us now understand the logic behind the code. Here what we wish to do is that get the position where the left mouse button was clicked, and casting out a ray from the camera to that point. The camera has a function called ScreemPointToRay(position),which shoots out a ray from the camera to the point given as input. Using rays, we can figure out the properties, components, attributes, etc. Of the object at the end of the ray.
Once the ray hits the floor we will get a true value in the if statement and we will set the player into motion toward the destination point. This is done using the SetDestination (Vector3) function of the NavMeshAgent class. This function moves the agent to the point given as parameter.
Now after writing this code, in Unity, select the Player object from the Hierarchy, and in the Inspector, drag and drop the Player object into the playerAgent variable in the Controller script.
Now we are good to go! Go ahead press play! See the magic happen!
This is just a simple maze. You can play with this. Create your own levels, bake the NavMesh and watch our player navigate the maze. Lastly and most importantly, have fun while making your game!
Power of NavMeshes
What we saw was just the absolute basic of using NavMeshes. NavMeshes can also be used during runtime.
For example take a floor with moving walls. The NavMeshSurface for this environment changes constantly. Thus runtime computation of NavMeshes is done (though it is extremely costly on resources; avoid).
Also NavMeshes can be used for procedurally generated levels too. What we have to do is to just bake the NavMesh on Start. To do this we use the BuildNavMesh() function of the NavMeshSurface class.
Thus we now have a tool, which is as powerful as it is simple to use. But remember, baking is processor heavy process, so use it wisely.