UDN
Search public documentation:

DevelopmentKitGemsCreatingADynamicNavMeshObstacleJP
English Translation
中国翻译
한국어

Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

UE3 ホーム > Unreal Development Kit Gems > 動的ナビゲーションメッシュ障害物の作成
UE3 ホーム > AI とナビゲーション > 動的ナビゲーションメッシュ障害物の作成

動的ナビゲーションメッシュ障害物の作成


2011年7月に UDK に即して最終テスト実施済み
PC および iOS 対応

概要


ナビゲーションメッシュには多くの便利な機能があります。以前のパスノードシステムと比較して、はるかに優秀です。非常に便利な機能の 1 つとして、リアルタイムに障害物を実に簡単に定義できるということがあります。

以前のパスノードシステムでは、これを実行するためにはパスノードをオフにして、パス設定によって使用されないようにする必要がありました。これによって、パスノードの数が非常に多くなり、レベルデザイナーがこのことを考慮しなければなりませんでした。また、かなり不便でエラーも起きやすいものでした。

ナビゲーションメッシュを使用すると、実に簡単に、2D 図形を障害物として定義、登録するだけで済みます。

関連テーマ

動的ナビゲーションメッシュ障害物


次のスクリプトは、既存の NavMeshObstacle クラスを継承したヘルパークラスです。これによって、簡単に使用できるインターフェース (SetAsSquare、SetAsRectangle、SetAsCircle) がプログラマーに提供されるため、図形をたやすく作成することができるようになります。

DynamicNavMeshObstacle.uc
class DynamicNavMeshObstacle extends NavMeshObstacle;

// List of possible shapes
enum EShape
{
  EShape_None,
  EShape_Square,
  EShape_Rectangle,
  EShape_Circle
};

// Shape of the nav mesh obstacle
var PrivateWrite EShape ShapeType;
// Used in EShape_Square
var PrivateWrite float Width;
// Used in EShape_Square and EShape_Rectangle
var PrivateWrite float Height;
// Used in EShape_Circle
var PrivateWrite float Radius;
// Used in EShape_Circle
var PrivateWrite int Sides;
// Align the obstacle to the rotation of the actor?
var bool AlignToRotation;

simulated function PostBeginPlay()
{
  // Skip default post begin play function
  Super(Actor).PostBeginPlay();
}

function SetAsSquare(float NewWidth)
{
  if (NewWidth > 0.f)
  {
    ShapeType = EShape_Square;
    Width = NewWidth;
  }
}

function SetAsRectangle(float NewWidth, float NewHeight)
{
  if (NewWidth > 0.f && NewHeight > 0.f)
  {
    ShapeType = EShape_Rectangle;
    Width = NewWidth;
    Height = NewHeight;
  }
}

function SetAsCircle(float NewRadius, float NewSides)
{
  if (NewRadius > 0.f && NewSides > 0)
  {
    ShapeType = EShape_Circle;
    Radius = NewRadius;
    Sides = NewSides;
  }
}

event bool GetObstacleBoudingShape(out array<vector> Shape)
{
  local Vector Offset;
  local int i, Angle;
  local Rotator R;

  if (ShapeType == EShape_Square)
  {
    if (AlignToRotation)
    {
      // Top right corner
      Offset.X = Width;
      Offset.Y = Width;
      Shape.AddItem(Location + (Offset >> Rotation));
      // Bottom right corner
      Offset.X = -Width;
      Offset.Y = Width;
      Shape.AddItem(Location + (Offset >> Rotation));
      // Bottom left corner
      Offset.X = -Width;
      Offset.Y = -Width;
      Shape.AddItem(Location + (Offset >> Rotation));
      // Top left corner
      Offset.X = Width;
      Offset.Y = -Width;
      Shape.AddItem(Location + (Offset >> Rotation));
    }
    else
    {
      // Top right corner
      Offset.X = Width;
      Offset.Y = Width;
      Shape.AddItem(Location + Offset);
      // Bottom right corner
      Offset.X = -Width;
      Offset.Y = Width;
      Shape.AddItem(Location + Offset);
      // Bottom left corner
      Offset.X = -Width;
      Offset.Y = -Width;
      Shape.AddItem(Location + Offset);
      // Top left corner
      Offset.X = Width;
      Offset.Y = -Width;
      Shape.AddItem(Location + Offset);
    }

    return true;
  }
  else if (ShapeType == EShape_Rectangle)
  {
    if (AlignToRotation)
    {
      // Top right corner
      Offset.X = Width;
      Offset.Y = Height;
      Shape.AddItem(Location + (Offset >> Rotation));
      // Bottom right corner
      Offset.X = -Width;
      Offset.Y = Height;
      Shape.AddItem(Location + (Offset >> Rotation));
      // Bottom left corner
      Offset.X = -Width;
      Offset.Y = -Height;
      Shape.AddItem(Location + (Offset >> Rotation));
      // Top left corner
      Offset.X = Width;
      Offset.Y = -Height;
      Shape.AddItem(Location + (Offset >> Rotation));
    }
    else
    {
      // Top right corner
      Offset.X = Width;
      Offset.Y = Height;
      Shape.AddItem(Location + Offset);
      // Bottom right corner
      Offset.X = -Width;
      Offset.Y = Height;
      Shape.AddItem(Location + Offset);
      // Bottom left corner
      Offset.X = -Width;
      Offset.Y = -Height;
      Shape.AddItem(Location + Offset);
      // Top left corner
      Offset.X = Width;
      Offset.Y = -Height;
      Shape.AddItem(Location + Offset);
    }

    return true;
  }
  else if (ShapeType == EShape_Circle && Sides > 0)
  {
    // Get the angle of each 'slice' defined by the number of sides
    Angle = 65536 / Sides;
    // If we are aligned to rotation, use the rotation as the starting point
    R = (AlignToRotation) ? Rotation : Rot(0, 0, 0);
    // Set the radius
    Offset.X = Radius;
    Offset.Y = 0.f;
    // For each side...
    for (i = 0; i < Sides; ++i)
    {
      // Add the the left side point
      Shape.AddItem(Location + (Offset >> R));
      // Increment to the next side
      R.Yaw += Angle;
    }

    return true;
  }

  return false;
}

defaultproperties
{
}

DynamicNavMeshObstacle (動的ナビゲーションメッシュ障害物) の使用


動的ナビゲーションメッシュ障害物を使用するのはとても簡単です。スポーンさせ、必要とする障害物の形状を設定し、登録します。

YourClass.uc
var DynamicNavMeshObstacle PlacementObstacle;

function PostBeginPlay()
{
  Super.PostBeginPlay();
  PlacementObstacle = Spawn(class'DynamicNavMeshObstacle');
  PlacementObstacle.SetAsCircle(96, 8);
}

また、DynamicNavMeshObstacle を動かすことによって、移動可能なナビゲーションメッシュ障害物を作成することができます。

function Tick(float DeltaTime)
{
  Super.Tick(DeltaTime);

  ForEach TraceActors(class'Actor', HitActor, HitLocation, HitNormal, CachedMouseWorldOrigin + CachedMouseWorldDirection * 65536.f, CachedMouseWorldOrigin,,, class'Actor'.const.TRACEFLAG_Bullet)
  {
    if (HitActor.bWorldGeometry)
    {
      PlacementObstacle.UnRegisterObstacle();
      PlacementObstacle.SetLocation(HitLocation);
      PlacementObstacle.RegisterObstacle();
      break;
    }
  }
}

DynamicNavMeshObstacleScreenShot.jpg