Chapter 6 – Navigation Mesh implementation
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
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.
whoa your post went mental with the html non breaking spaces! !