In this tutorial we will learn about Navmesh in Unity, how to create it and use it on your game as part of navigation.
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.
The Unity NavMesh system consists of the following pieces:
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?
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.
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)
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? 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.
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”.
Setting up the player is pretty easy. We just have to add the “NavMeshAgent” Component to the Player object.
To do this:
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.
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!
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.