Part VI. Unity Lab 6: Scene Navigation

In the last Unity Lab, you created a scene with a floor (a plane) and a player (a sphere nested under a cylinder), and you used a NavMesh, a NavMesh Agent, and raycasting to get your player to follow your mouse clicks around the scene.

Now we’ll pick up where the last Unity Lab left off. The goal of this lab is to get familiar with Unity’s pathfinding and navigation system, a sophisticated AI system that lets you create characters that can find their way around the words that you create. In this Lab, you’ll build a scene out of GameObjects and use navigation to move a character around it.

Along the way you’ll learn about useful tools: you’ll create a more complex scene and bake a NavMesh that lets an agent navigate it, you’ll create static and moving obstacles, and most importantly, you’ll get more practice writing C# code.

Let’s pick up where the last Unity Lab left off

In the last Unity Lab, you created a player out of a sphere head nested under a cylinder body. Then you added a NavMesh Agent component to move the player around the scene, using raycasting to find the point on the floor that the player clicked. In this next Unity Lab you’ll pick up where the last Lab left off. You’ll add GameObjects to the scene, including stairs and obstacles so you can see how Unity’s navigation AI handles them. Then you’ll add a moving obstacle to really put that NavMesh Agent through its paces.

So go ahead and open the Unity project that you saved at the end of the last Unity Lab. If you’ve been saving up the Unity Labs to do them back to back, then you’re probably ready to jump right in! But if not, take a few minutes and flip through the last Unity Lab again—and also look through the code that you wrote for it.

Images
Note

If you’re using our book because you’re preparing to be a professional developer, being able to go back and read the code in your old projects and is a really important skill – and not just for game development!

Add a platform to your scene

Note

Sometimes it’s easier to see what’s going on in your scene if you switch to an isometric view. You can always reset the layout if you lose track of the view.

Let’s do a little experimentation with Unity’s navigation system. To help us do that, we’ll add more GameObjects to build a platform with stairs, a ramp, and an obstacle. Here’s what it will look like:

Images

It’s a little easier to see what’s going on we switch to an isometric view, or a view that doesn’t show perspective. In a perspective view, objects further away look small, while close objects look large. In an isometric view, objects are always the same size no matter how far away they are from the camera.

Images

Add ten GameObjects to your scene. Create a new material called Platform in your Materials folder with albedo color CC472F, and add it to all of the GameObjects except for Obstacle, which uses a new material called 8 Ball with the 8 Ball Texture map from the first Unity lab. This table shows their names, types, and positions:

Images
Images

Use bake options to make the platform walkable

Use shift-click to select all of the new GameObjects that you added to the scene, then use control-click (or command-click on a Mac) to deselect Obstacle. Go to the Navigation window and click the Object button, then make them all walkable by checking Navigation Static and setting the Navigation Area to Walkable. Make the Obstacle GameObject not walkable by selecting it, clicking Navigation Static, and setting Navigation Area to Not Walkable.

Images

Now follow the same steps that you used before to bake the NavMesh: click the Bake button at the top of the Navigation window to switch to the Bake view, then click the Bake button at the bottom.

Images

It looks like it worked! The NavMesh now appears on top of the platform, and there’s space around the obstacle. Try running the game. Click on top of the platform and see what happens.

Hmm, hold on. Things aren’t working the way we expected them to. When you click on top of the platform, the player goes under it. And if you look closely at the NavMesh that’s displayed when you’re viewing the Navigation window, you’ll see that it also has space around the stairs and ramp, but doesn’t actually include either of them in the NavMesh. The player has no way to get to the point you clicked on, so the AI gets it as close as it can.

Images

Include the stairs and ramp in your NavMesh

An AI that couldn’t get your player up or down a ramp or stairs wouldn’t be very intelligent. Luckily, Unity’s pathfinding system can handle both of those cases. We just need to make a few small adjustments to the options when we bake the NavMesh. Let’s start with the stairs. Go back to the Bake window and notice that the default value of Step Height is 0.4. Take a careful look at the measurements for your steps—they’re all 0.5 units tall. So to tell the navigation system to include steps that are 0.5 units, change the Step Height to 0.5. You’ll see the picture of the step in the diagram increase, and the number above it change from the default 0.4 value to 0.5.

We still need to include the ramp in the NavMesh, too. When you created the GameObjects for the platform, you gave the ramp an X rotation of -46, which means that it’s a 46 degree incline. The Max Slope setting defaults to 45, which means it will only include ramps, hills, or other slopes that with at most a 45 degree incline, so change Max Slope to 46. Now bake the NavMesh again. Now it will include the ramp and stairs.

Images

Now the NavMesh includes the ramp. Start your game and test out your new NavMesh changes.

Note

Don’t forget – it’s not cheating to peek at the solution!

Note

It’s okay if your code looks a little different than ours as long as it works. There are a LOT of ways to solve any coding problem! Just make sure to take some time and understand how this code works.

Fix height problems in the NavMesh

Now that we’ve got control of the camera, we can get a good look at what’s going on under the platform—and something doesn’t look quite right. Start your game, then rotate the camera and zoom in so you can get a clear view of the obstacle sticking out under the platform. Click the floor on one side of the obstacle, then the other. It looks like the player is going right through the obstacle! And it goes right the through end of the ramp, too.

Images

But if you move the player back to the top of the platform, it avoids the obstacle just fine. What’s going on?

Look closely at the parts of the NavMesh above and below the obstacle. Notice any differences between them?

Images

Go back to the earlier part of this Lab to the part where you set up the NavMesh Agent component—specifically, the part where you set the Height to 3. Now we just need to do the same for the NavMesh. Go back to the Bake options in the Navigation window and set the Agent Height to 3, then bake your mesh again.

Images

This created a gap in the NavMesh under the obstacle and expanded the gap under the ramp. Now the Player doesn’t hit either the obstacle or the ramp when moving around under the platform.

Add a NavMesh obstacle

You added a static obstacle in the middle of your platform: you created a stretched out capsule and marked it nonwalkable, and when you baked your NavMesh it had a hole around the obstacle so the player has to walk around it. But what if you want an obstacle that moves? Try moving the obstacle—the NavMesh doesn’t change! It still has a hole where the obstacle was, not where it currently is. And if you bake it again, it just creates a hole around the obstacle’s new location. To add an obstacle that moves, add a NavMesh Obstacle component to a GameObject.

Let’s do that right now. Add a Cube to your scene with position (-5.75, 1, -1) and scale (2, 2, 0.25). Create a new material for it with a dark gray color (333333) and name your new GameObject Moving Obstacle. This will act as a kind of gate that at the bottom of the ramp that can move up out of the way of the player or down to block it.

Images
Note

This NavMesh Obstacle carves a moving hole in the NavMesh that prevents the Player going up the ramp. You’ll add a script that lets the user drag it up and down to block and unblock the ramp.

We just need one more thing. Click the Add Component button at the bottom of the Inspector window and choose Navigation >> Nav Mesh Obstacle to add a NavMesh Obstacle component to your obstacle GameObject.

Images

If you leave all of the options at their default settings, you get an obstacle that the NavMesh Agent can’t get through. Instead, the Agent hits it and stops. Check the Carve box—this causes the obstacle to create a moving hole in the NavMesh that follows the GameObject. Now your Moving Obstacle GameObject can block the player from navigating up and down the ramp. Since the NavMesh height is set to 3, if the obstacle is less than 3 units above the floor it will create a hole in the NavMesh underneath it. If it goes above that height, the hole disappears.

Note

The Unity Manual has thorough—and readable!—explanations for the various components. Click the “open reference” button (Images) at the top of the Nav Mesh Obstacle component in the Inspector to open up the manual page. Take a minute to read it—it does a great job of explaining the options.

Add a script to move the obstacle up and down

This script uses the OnMouseDrag method. It works just like the OnMouseDown method you used in the last Lab, except that it’s called when the GameObject is dragged.

Images
Note

The first if statement keeps the block from moving below the floor, and the second keeps it from moving too high. Can you figure out how they work?

Drag your script onto the Moving Obstacle GameObject and run the game—uh-oh, something’s wrong. You can click and drag the obstacle up and down, but it also moves the player. Fix this by adding a tag to the GameObject.

Images

Then modify your MoveToClick script to check for the tag:

Images

Run your game again. If you click on the obstacle you can drag it up and down, and it stops when it hits the floor or gets too high. Click anywhere else, and the player moves just like before. Now you can experiment with the NavMesh Obstacle options. (This is easier if you reduce the Speed in the Player’s NavMesh Agent.)

  • Start your game. Click on Moving Obstacle in the Hierarchy window and uncheck the Carve option. Move your player to the top of the ramp, then click at the bottom of the ramp—the player will bump into the obstacle and stop. Drag the obstacle up, and the player will continue moving.

  • Now check Carve and try the same thing. As you move the obstacle up and down, the player will recalculate its route, taking the long way around to avoid the obstacle if it’s down, and changing course in real time as you move the obstacle.

Get creative!

Can you find ways to improve your game and get practice writing code? Here are some ideas to help you get creative:

  • Build out the scene—add more ramps, stairs, platforms, and obstacles. Find creative ways to use materials. Search the web for new texture maps. Make it look interesting!

  • Make the NavMesh Agent move faster when the player holds down the shift key. Search for KeyCode in the Scripting Reference to find the left/right shift key codes.

  • You used OnMouseDown, Rotate, RotateAround, and Destroy in the last Lab. See if you can use them to create obstacles that rotate or disappear when you click them.

  • We don’t actually have a game just yet, just a player navigating around a scene. In the next Unity Lab we’ll pick up where this one leaves off, but you don’t have to wait. Can you find a way to turn your program into a timed obstacle course?

You already know enough about Unity to start building interesting games—and that’s a great way to get practice so you can keep getting better as developer.

Note

This is your chance to experiment. Using your creativity is a really effective way to quickly build up your coding skills.