среда, 18 ноября 2009 г.

NavMesh'им ботов

Что такое Navmesh

Navmesh это замена стандартному способу поиска путей по вейпойнтам.
Плюсы новой системы:
  • Более быстрый поиск пути.
  • Более точный поиск пути.
  • Более быстрые проверки по ObstacleMesh и WalkableMesh.
  • Простота создания NavMesh с точки зрения дизайнера уровней.
Итак начнем.

 

Что нужно, чтобы NavMesh заработал?

  1. Наличие NavMesh в уровне. (см. Туториал по NavMesh для дизайнеров by redbox )
  2. Реализация передвижения по NavMesh в коде.

 

Добавляем ботам возможность искать путь по NavMesh

Итак, добавляем две функции в контроллер ботов которые определены в базовом классе GameAIController.
event bool GeneratePathToActor( Actor Goal, optional float WithinDistance, optional bool bAllowPartialPath )
{
  // Clear cache and constraints (ignore recycling for the moment)
  NavigationHandle.PathConstraintList = none;
  NavigationHandle.PathGoalList = none;

  // Create constraints
  class'NavMeshPath_Toward'.static.TowardGoal( NavigationHandle, Goal );
  class'NavMeshGoal_At'.static.AtActor( NavigationHandle, Goal );

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

event bool GeneratePathToLocation( Vector Goal, optional float WithinDistance, optional bool bAllowPartialPath )
{
  // Clear cache and constraints (ignore recycling for the moment)
  NavigationHandle.PathConstraintList = none;
  NavigationHandle.PathGoalList = none;

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

  // Find path
  return NavigationHandle.FindPath();
}
Поиском пути по NavMesh управляет NavigationHandle который находится в контроллере. Для того чтобы NavigationHandle мог найти путь ему нужну указать как его искать. В данном случае мы используем два ограничителя (NavMeshPath_Toward, NavMeshGoal_At). Для правильной работы NavigationHandle обязательно должен иметь ограничители типов NavMeshPathGoalEvaluator и NavMeshPathConstraint. Вы можете написать новые классы ограничителей сами, чтобы получить нестандартный поиск пути.

 

Поехали

Путь мы нашли и теперь нам нужно сказать боту, что ему пора бы пойти... по этому пути. =)
Я покажу передвижение ботов по NavMesh на примере замены стандартного состояния AIController ScriptedMove на ScriptedMove с использованием NavMesh.
var() Vector TempDest;

...

state ScriptedMove
{
  Begin:
    // while we have a valid pawn and move target, and
    // we haven't reached the target yet

    while( Pawn != None && ScriptedMoveTarget != None && !Pawn.ReachedDestination(ScriptedMoveTarget) )
    {
      if( GeneratePathToActor(ScriptedMoveTarget) )
      {
        //NavigationHandle.DrawPathCache(,TRUE);

        // check to see if it is directly reachable
        if( NavigationHandle.ActorReachable( ScriptedMoveTarget ) )
        {
          // then move directly to the actor
          MoveToward( ScriptedMoveTarget, ScriptedFocus );
        }
        else
        {
          // move to the first node on the path
          if( NavigationHandle.GetNextMoveLocation( TempDest, Pawn.GetCollisionRadius()/**0.8f*/) )
          {
            //DrawDebugCoordinateSystem(TempDest, rot(0,0,0),25.f,TRUE);
            MoveTo( TempDest, ScriptedFocus );
          }
          else
          {
            //give up because the nav mesh did not have anything for you in the path
            `warn("NavigationHandle.GetNextMoveLocation failed to find a destination for to"@ScriptedMoveTarget);
            ScriptedMoveTarget = None;
            break;
          }
        }
      }
      else
      {
        //give up because the nav mesh failed to find a path
        `warn("FindNavMeshPath failed to find a path to"@ScriptedMoveTarget);
        ScriptedMoveTarget = None;
      } 
    }  

    // return to the previous state
    PopState();
}
Все. Изучайте и экспериментируйте.

Комментариев нет: