Arrival in Hell Dev Blog #1 – Navigation

Hello and welcome to the first instalment of the Arrival in Hell dev blog. Even though we’ve been working on Arrival in Hell in our spare time for over a year now, I wanted to kick off the dev blog from the beginning so you get a much fuller picture of how the game works.

In case you don’t know already, I’ll quickly summarize what we’re making. It’s a remake of a 2006 Flash game originally created by my friends Eduardo Mojica and Richard Rout. It is a horror point-and-click adventure game and we’ll be building it in Unity. I’ve been programming and making games for about 10 years now, but this is my first project in Unity.

The first thing I wanted to nail down early, before anything else, was the player movement. Since the game is now true 3D, the player needs to path find in 3D space. Luckily Unity already has awesome pathfinding functionality built in. To use it you simply open Window > Navigation, select objects you want to be included in the path finding and check them as ‘Navigation static’. This tells Unity that these objects are static (not moving) and should be taken into account when pathfinding.

NavigationStatic

Setting objects to ‘Navigation Static’

I’d like to take a moment to express just how awesome this is. In the past I, like most game developers, have had to build my own path finding system. I’ve done A* tile and node based pathfinding systems before, and in both cases, particularly node based, setting up the ‘walls’ has been a real pain. With a node based system you have to manually place points used by the AI to navigate between. Not only does Unity come with navigation out of the box, it also uses navigation meshes, which are far more efficient and smooth than manually placed nodes. To top it all off, you can re-bake (recalculate) the entire nav mesh by clicking one button. Gone are the days of manually fiddling with navigation nodes!

One of my less successful attempts at node based pathfinding

One of my less successful attempts at node based pathfinding

Once you’ve marked static objects to be included in the nav mesh, you choose a few settings (such as how steep a slope can be and how high a step can be before it’s considered a wall) and hit the bake button. This will generate your nav mesh which you can preview in the scene view. One thing worth noting is that just because an object exists in the scene, doesn’t mean it has to be part of the nav mesh. For example in the game I don’t care if the player walks over rubble, so I have not marked any rubble objects as navigation static; this speeds up the nav mesh generation.

These are the actual values used in Arrival in Hell

These are the actual values used in Arrival in Hell

Baked NavMesh. Unity does an excellent job of automatically generating this

Baked nav mesh. Unity does an excellent job of automatically generating this

Once the nav mesh was generated I simply added a NavMeshAgent component to the player model. The game is now set up for navigation. The only thing left is adding mouse input to control the destination of the NavMeshAgent.

NavMesh Agent settings

NavMeshAgent settings

To tell the nav mesh agent where to navigate to I:

  1. Listen for mouse input
  2. Get the mouse position in screen space
  3. Convert the screen space coordinate to a ray from the camera
  4. Cast the ray out until it hits the floor
  5. Set the NavMeshAgent’s destination to that position on the floor

The C# code looks a little like this:

void Update () {
    if (Input.GetMouseButton(0))
    {
        Vector3 screenPoint;

        screenPoint = Input.mousePosition;

        Ray ray = Camera.main.ScreenPointToRay(screenPoint);

        RaycastHit hitInfo;

        if (floor.GetComponent().Raycast(ray, out hitInfo, 10000.0f))
        {
            Vector3 targetPoint = ray.GetPoint(hitInfo.distance);
            agent.SetDestination(targetPoint);
            agent.Resume();
        }
    }
}
Click to set NavMeshAgent’s destination

Click to set NavMeshAgent’s destination

VisualizePath

You can visualize the destination and path in the scene view

This handles pretty much all of the navigation needs of the game. The only exception is when the nav mesh changes due to some event in the game. For example the cell door is initially closed in the first room. Later when it’s opened, the nav mesh needs to update to reflect this change and to allow the player to walk through the now open door. Rather than re-baking the entire static nav mesh at runtime, I have made use of the ‘NavMeshObstacle’ component. This component allows you to include ‘dynamic’ objects in the path finding. If the object moves, Unity’s pathfinding algorithm updates accordingly on the fly.

Navigation paths are updated automatically with changes to NavMeshObtacle

Navigation paths are updated automatically with changes to NavMeshObtacle

VisualizePathObstacle

Visualisation of NavMeshObstacle changes in scene view

And there we have it; this is how the navigation works in Arrival in Hell. All of this is achieved using out of the box navigation functionality supplied with Unity. I’ve made the example shown above available here in case anyone wants it. Next week I’ll be detailing how room changes and camera angles work.

Share This:

7 thoughts on “Arrival in Hell Dev Blog #1 – Navigation

  1. Really helpful overview of how Unity’s built-in pathfinding stuff works. The project I’m currently on uses dynamic generated levels so we ended rolling our own. Dynamic obstacles / collision is a pain to do nicely!

    What do you think will be the mostly challenging thing to implement for your project?

    • Yeah for dynamic levels you can’t really use Unity’s built in navigation since you can’t re-bake at runtime. What method are you using for your custom system?

      It’s hard to put my finger on what the most challenging thing has been so far. There has been a few tricky and time consuming bits. Getting animation to work how we want it has been quite painful. That includes syncing up his walk animation with the path finding (which I’m doing a write up for after next week’s camera control write up) and getting him to pick up objects with good accuracy. Balancing looks and performance is a constant struggle too.

  2. We have a super small team and it’s not very technical. I didn’t think we’d be able to author the navmeshes (like in Maya) and have the code stitch them together easily. Instead it uses simple circles the designer can place, then they’re linked up where they overlap. On top of that the enemies use rays for dynamic obstacle avoidance and some light flocking type stuff to avoid each other. It could definitely be better but it’s good enough 😀

    Cool. Looking forward to reading the next article!

  3. Pingback: Arrival in Hell Dev Blog #3 – Animating movement | Epic Industries

  4. Pingback: Animating 3D character movement in Unity - GeekTechTalk

  5. Hey there! I’m creating a simple point & click scene and I’m learning from this post. Is very useful to me.

    I’ve a problem:
    I’ve created a new script called PointClick and in the Update, I’ve pasted your code just to see what happens. The problem is that the compiler fails with the variables “agent” and “floor”. Outside of the Update, I’ve defined a “NavMeshAgent agent” variable and the “Plane floor” variable. The agent variable is ok, but the Plane variable doesn’t recognize the GetComponent function. Do you know how to make it work?

    Thank you so much for your help and I hope you launch the game soon, I’m looking forward to play it ;D

Leave a Reply

Your email address will not be published. Required fields are marked *

*