スマート オブジェクトを作成する

「スマート オブジェクト」 は、キャラクタ (パス フォローイング システムがネイティブで管理しないものすべて) がパスに沿って移動する際に、キャラクタとの特殊な相互作用を管理するオブジェクトを表す総称です。スマート オブジェクトは、シナリオとゲームプレイのニーズ、アニメーション サブシステムと対話する方法などに応じて、さまざまな形態を取ることができます。たとえば、スマート オブジェクトは次のことができます。

Gameware Navigation の SDK は、スマート オブジェクトのデフォルトの実装を提供しません。その代わり、パス追従処理中、特定の時点におけるキャラクタの移動を部分的または完全に管理する、ユーザ独自のカスタム スマート オブジェクトを作成するために必要なすべてのツールがエクスポーズされています。

ユーザ独自のスマート オブジェクトを作成する場合、コード内で実行する必要のある具体的な手順は、どのようなエフェクトを作成するかによって大きく変わります。ただし、最も一般的な種類のスマート オブジェクトなら、このページで紹介した戦略のおそらくほぼすべてを使用すると思われます。

NavTag を設定する

各スマート オブジェクトがコントロールする地形のエリアにタグを付ける場合は、通常は NavTag を使用します。これは必ず必要というわけではありません。NavTag を使わなくても、独自のスマート オブジェクトを統合することができます。ただし、NavTag をパス フォローイング システムに統合すると、キャラクタがスマート オブジェクトを含むパスをいつプランするかや、オブジェクトがコントロールするエリアにいつ近づくかを簡単に決定することができます。

一般的な方法は、NavData の各エリアが参照するスマート オブジェクトのタイプを決定するために、ランタイム時に使用できるカスタム IDを埋め込むために NavTag を使用する方法です。たとえば、ラダーを表す NavGraph にはある ID 値を使ってタグを付け、エレベータを表す NavGraph には別の値でタグを付けることができます。

NavData でどれくらい正確に NavTag を設定するかは、作成するオブジェクトのタイプによって異なります。

NavTag については、「カスタム データでタグ付けする」を参照してください。

TagVolume と動的な障害物については、「動的な障害物や TagVolume を使用する」を参照してください。

登録と登録解除に関する注意

使用する予定のあるキャラクタを追跡するには、スマート オブジェクトが必要な場合があります。これによって、スマート オブジェクトの状態の変化に合わせて、キャラクタに適切に対応させることができます。たとえば、ドアがロックされたり橋が壊された場合、キャラクタがパスを再計算して目標地点までの別のパスを探索できるようにする必要があります。通常これを実現するには、スマート オブジェクトを含むパスをプランする際に各キャラクタをスマート オブジェクトに登録することと、パスが変わりそのオブジェクトがパスから外れた場合に登録を解除することが必要になります。

パスに沿って配置されるスマート オブジェクトをキャラクタに登録したり登録解除したりするには、スマート オブジェクトの 1 つに関連付けられていた NavTag を使ってタグが付けられていたイベントに対して、新規作成された各パスをチェックする IPathEventListObserver のカスタム実装を使用することができます。

IPathEventListObserver の使用の詳細については、「PathEvent を監視する」を参照してください。

今後パス上に現れるスマート オブジェクトをチェックする

キャラクタがパスに沿って移動する場合、パス上に現れるスマート オブジェクトをモニタする必要があります。キャラクタがオブジェクトに近づくと、スマート オブジェクトに指示を求めます。

通常、これはキャラクタのパス上に現れる次の PathEvent の NavTag をチェックすることを意味します。Bot::GetUpcomingEventNavTag() を呼び出すことで、これを実行できます。返された NavTag がスマート オブジェクトに関連付けられている ID と一致すると、スマート オブジェクトに現在そのオブジェクトを横断しているキャラクタを登録することが可能になり、Bot に道順を教えることができます。キャラクタの動きを直ちにコントロールすることもできれば、特定の距離内に入るまで、Bot に通常どおりにパスを移動させ続けることもできます。

コントロールを取得する

最終的に、スマート オブジェクトは、キャラクタがオブジェクトを横断している間に、一定時間キャラクタの動きのコントロールを取得することになります。たとえば、キャラクタがドアを通り抜けたり、ラダーを上ったり、エレベータの上に立つと、特定のアニメーションが再生されるなどです。フル コントロールを取得したい場合には、 2 つのメソッド Bot::SetDoValidateCheckPoint()Bot::SetDoComputeTrajectory() を呼び出して、両方のメソッドに false を渡して、キャラクタのパス フォローイング システムを解除します。

コントロールを開放し、ターゲット ポイントを前進させる

キャラクタがスマート オブジェクトを通り抜けた後、またはスマート オブジェクトが実行する必要があると決定したキャラクタの動きが終了した後、2 つのメソッド Bot::SetDoValidateCheckPoint()Bot::SetDoComputeTrajectory() を再度呼び出して、両方のメソッドに true を渡すことで、パス フォローイング システムを再度有効にすることができます。

ユーザがパス フォローイングのコントロールを取得すると、ターゲット ポイントの計算が無効になります。したがって、Bot によって保持されている現在のターゲット ポイントは、ユーザがコントロールを取得した時点の場所にあります。通常は、キャラクタが横断したスマート オブジェクトの開始地点にあるパス イベントの後ろになります。コントロールを開放した場合、キャラクタがもう一度スマート オブジェクトを横断しないようにするため、スマート オブジェクトの終了時点に沿ってターゲット ポイントを前進させる必要があります。これは次のように実行することができます。

// Get the next NavTag along the path from the current position on the path.
// Since the current position is still where it was when the smart object took
// control, we know that this method will return the NavTag at the other end of the
// interval of the path that is controlled by the smart object.
const Kaim::NavTag* smartObjectTag = m_navBot->GetUpcomingEventNavTag();

// This class is a predicate that determines which NavTag we want to move through.
Kaim::NavTagMovePositionOnPathPredicate predicate(smartObjectTag);

// We retrieve the current position on the LivePath.
Kaim::PositionOnLivePath positionOnLivePath = m_navBot->GetProgressOnLivePath();

// This call moves the position on the path forward until the predicate says to stop.
// The NavTagMovePositionOnPathPredicate says to stop when a tag other than the
// smartObjectTag is reached, which will be the PathEvent that lies at the other end
// of the smart object.
m_navBot->MovePositionOnPathForwardToNextEvent( positionOnLivePath, &predicate );

新しいパスの要求を処理する

スマート オブジェクトの性質に応じて、スマート オブジェクトを使用している間の新しいパスの再計算を Bot に許可したい場合と許可したくない場合があります。たとえば、Bot のジャンプ中または飛行中に空中で方向が変わらないように、または Bot がエレベータを使用している間には、新しいパスの計算をしないようにしたほうがいいかもしれません。一方、Bot がはしごを登ったりドアを使用しているときは、新しいパスを許可した方がいいかもしれません。これに対処する一般的な方法としては、Bot クラスで新しいパスを計算する前に、現在のスマート オブジェクトをチェックするというものです。

ただし、場合によって、スマート オブジェクトは、NavMesh の境界から外側に遠すぎてパス ファインディング システムが NavMesh にフックできなくなるような場所まで Bot を連れて行く NavGraph にリンクされている場合があります。また、NavGraph の特定のエッジで Bot に強制的に新しいパスを開始させる必要がある場合があります。これらの場合でも Bot がスマート オブジェクトを使用している間に新しいパスを再計算できます。ただし、スマート オブジェクトを使用している間は、Bot の位置が NavMesh に空間化されないので、新しいパスを開始したい NavGraph のエッジまたは頂点を使って AStarQuery を設定する必要があります。

同様に、新しいパスを終了る NavGraph のエッジまたは頂点を使用して AStarQuery を設定することにより、目的地が NavMesh の内部になくても、スマート オブジェクトで終了するパスをプランすることができます。

詳細は、「AStarQuery オプション」を参照してください。

サンプル:

LabEngine プロジェクトには、ドア、エレベータ、ラダー、飛び越えなければならない溶岩など、さまざまなタイプのスマート オブジェクトのサンプルが含まれています。これらのオブジェクトは、Navigation Lab で起動できる SDK サンプルで使用できます。「Navigation Lab で作業を開始する」を参照してください。これらのオブジェクトの完全なソース コードは、お手本として使用するために用意されています。tools¥LabEngine¥include¥LabEngine¥smartobjectstools¥LabEngine¥src¥smartobjects ディレクトリのファイルを参照してください。