Chapter 6 – Navigation Mesh implementation

February 23rd, 2010 Leave a comment Go to comments

 

Chapter 6 – Implementing navmeshes

In this new chapter, we will expand on the chapter 5 of the isometric tutorial which you can find here. In this tutorial we will go into the specific of using the navmesh capabilities of Epic’s UDK. We will add a new state to pathfind on the navmesh for the main pawn. In a subsequent chapter we will add a sample unit selection, it may not contain exactly what you are looking for, but should provide a simple way for you to understand pawn possession. At this point I expect that you do more than copy/paste and understand the code.

Edit for the fans : As it takes some time to build these tutorial, please take the time to support me with my banners, it will make more incentive for me to spew more in the near future :)

 

Modifying the IsometricPlayerController

We will need to add a few new variable to the player controller to make use of the navmesh. Since you can leave the code for using pathnode for navigation, I suggest you comment the new variable section so it is clearly used for

navmeshes. We will work with point destination on navmesh patches. This means that when you click on the terrain, we will set the destination as the NavigationDestination. This is because GetDestinationPosition is modified by the

navigation system. Because of that we will also need a global variable to track the next temporary destination (from nav mesh patch to nav mesh patch). The rest of the variable should be obvious once we hit the new navigation state code.

Put this code on top of your playercontroller code (do not worry copy/pasting will take all the code even if not visible) :

/** Temp Destination for navmesh destination */
var()   Vector  TempDest;
var bool        GotToDest;
var     Vector  NavigationDestination;
var Vector2D  DistanceCheck;
/*****************************************************************/
var Actor       Target;
var bool        CurrentTargetIsReachable;

Adding the NavMeshSeeking state

Now copy/paste this chunk of code into your player controller and we will comment it just after. I added code comment for code clarity, you can read it beforce the later comments.

/////////////// NAVMESH PATHFINDING ///////////////

//Overwrite AIController's ScriptedMove state to make use of the NavigationHandle instead of the old way
state NavMeshSeeking
{
	function bool FindNavMeshPath()
	{
		// Clear cache and constraints (ignore recycling for the moment)
		NavigationHandle.PathConstraintList = none;
		NavigationHandle.PathGoalList = none;

		// Create constraints
		class'NavMeshPath_Toward'.static.TowardPoint( NavigationHandle, NavigationDestination );
		class'NavMeshGoal_At'.static.AtLocation( NavigationHandle, NavigationDestination, 50, );

		// Find path
		return NavigationHandle.FindPath();
	}

	Begin:
		`log("BEGIN STATE SCRIPTEDMOVE");
		// while we have a valid pawn and move target, and
		// we haven't reached the target yet
		NavigationDestination = GetDestinationPosition();

		if( FindNavMeshPath() )
		{
			NavigationHandle.SetFinalDestination(NavigationDestination);
			`log("FindNavMeshPath returned TRUE");
			FlushPersistentDebugLines();
			NavigationHandle.DrawPathCache(,TRUE);

			//!Pawn.ReachedPoint here, i do not know how to handle second param, this makes the pawn
			//stop at the first navmesh patch
			`Log("GetDestinationPosition before navigation (destination)"@NavigationDestination);
			while( Pawn != None && !Pawn.ReachedPoint(NavigationDestination, None) )
			{
				if( NavigationHandle.PointReachable( NavigationDestination ) )
				{
					// then move directly to the actor
					MoveTo( NavigationDestination, None, , true );
					`Log("Point is reachable");
				}
				else
				{
					`Log("Point is not reachable");
					// move to the first node on the path
					if( NavigationHandle.GetNextMoveLocation( TempDest, Pawn.GetCollisionRadius()) )
					{
						`Log("Got next move location in TempDest " @ TempDest);
						// suggest move preparation will return TRUE when the edge's
					    // logic is getting the bot to the edge point
							// FALSE if we should run there ourselves
						if (!NavigationHandle.SuggestMovePreparation( TempDest,self))
						{
							`Log("SuggestMovePreparation in TempDest " @ TempDest);
							MoveTo( TempDest, None, , true );
						}
					}
				}
				DistanceCheck.X = NavigationDestination.X - Pawn.Location.X;
				DistanceCheck.Y = NavigationDestination.Y - Pawn.Location.Y;
				DistanceRemaining = Sqrt((DistanceCheck.X*DistanceCheck.X) + (DistanceCheck.Y*DistanceCheck.Y));
				`Log("distance from pawn"@Pawn.Location@" to location "@ NavigationDestination@" is "@DistanceRemaining );
				`Log("Is pawn valid ?" @Pawn);
				GotToDest = Pawn.ReachedPoint(NavigationDestination, None);
				`Log("Has pawn reached point ?"@GotToDest);

				if( DistanceRemaining < 15) break;
			}
		}
		else
		{
			//give up because the nav mesh failed to find a path
			`warn("FindNavMeshPath failed to find a path to"@ScriptedMoveTarget);
			ScriptedMoveTarget = None;
		}   

	`log("POPPING STATE!");
	Pawn.ZeroMovementVariables();
	// return to the previous state
	PopState();
}

The FindNavMeshPath function will initialize all the properties of the NavigationHandle variable that we inherit deeply from the base Controller class. The rest of the code is pretty self explenatory, in pseudo code it reads humanly as

follow : while the pawn variable is valid and we have not reached our destination, check if next point is reachable, if it is, simply move to it. If the point is not valid then proceed to search for another path from our location. Lastly

check distance to destination using only 2d coordinates, if we are within 15 units, we have reached destination.

Modifying the ExecutePathFindMove function to pathfind on the navmesh :

function ExecutePathFindMove()
{
ScriptedMoveTarget = FindPathTo(GetDestinationPosition());
`Log("Route length is"@RouteCache.Length);
if( RouteCache.Length > 0 )
{
`Log("Launching PathFind");
PushState('PathFind');
}
else
{
//Lets find path with navmesh
`Log("Launching PathFind with navmesh");
PushState('NavMeshSeeking');
}

}

 

Get chapter 6-7 source code and test map.

 

 

Chapter 7 creating the follower

 

 

 

Update me when site is updated
Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Slashdot
  • PDF
  • Twitter
  1. Matthew
    May 22nd, 2010 at 22:48 | #1

    C:\UDK\UDK-2010-04\Development\Src\MyIsometricGame\Classes\IsometricGamePlayerController.uc(6,0): error : Unrecognized type ‘NavigationDestination’

    Is what i get when i try to build. I can’t work out the problem though.

  2. June 24th, 2010 at 02:04 | #2

    whoa your post went mental with the html non breaking spaces!  !

  1. February 14th, 2010 at 22:13 | #1