キャラクタのパス フォローイング システムをカスタマイズするには、単純なもの(クラス メソッドの呼び出しなど)から複雑なもの(コア クラスの再実装)まで、さまざまな方法を使用できます。このトピックおよびこのセクションの他のトピックでは、パス フォローイング システムのさまざまな要素の動作をコントロールするための最も一般的なオプションと戦略の概要について説明します。
各 Bot は、パスを検出して追従する方法をコントロールする幅広い設定パラメータを受け入れます。
Bot 設定パラメータは、Bot::Init() の呼び出しの初期化時に指定する BotConfig オブジェクトで設定することができます。このアプローチによって、複数のゲーム キャラクタを同じ設定パラメータのセットで設定するのに使用できる、単一の設定オブジェクトを作成および設定することができます。
BotConfig クラスはいくつかの単純なデータ メンバを含み、その他のパラメータを機能カテゴリ別に下位の設定オブジェクトへとグループ化します。
Kaim::BotConfig botConfig; botConfig.m_enableAvoidance = true; botConfig.m_shortcutTrajectoryConfig.m_maxDistanceFromBot = 20.0f; ... Kaim::Ptr<Kaim::Bot> bot = *KY_NEW Kaim::Bot(); bot->Init(botInitConfig, botConfig);
BotConfig のすべての設定パラメータは、Bot API のメソッドを呼び出すことにより、各キャラクタに対して動的に設定することもできます。
BotConfig の単純なデータ メンバは、Bot クラスのメソッドを通じて直接公開されます。BotConfig によって公開される下位の設定オブジェクトについては、Bot クラスが現在のインスタンスを取得したり設定するアクセサ メソッドも公開します。
bot->SetEnableAvoidance(true); Kaim::ShortcutTrajectoryConfig shortcutConfig; shortcutConfig.SetDefaults(); shortcutConfig.m_maxDistanceFromBot = 20.0f; bot->SetShortcutTrajectoryConfig(shortcutConfig);
ただし、クエリーは PathFinderConfig で公開される設定オプションよりも多くのものをサポートしています。これらその他のオプションのいずれかを使用する場合、または 1 回限りのパス計算中に異なるオプションを設定する場合は、クエリーを直接設定する必要があります。「静的パスを取得する」の「上級」のパス計算方法を参照してください。
パスに沿った Bot の進行状況をパス フォローイング システムがどのように監視するかを決めるいくつかのパラメータを設定する為にPathProgressConfig クラスを使用することができます。
たとえば、チェック ポイント システムを広範囲に使用する場合は、PathProgressConfig::m_checkPointRadius 値をカスタマイズすることができますが、この値によって Bot がチェック ポイントにどの程度近づくとそのチェック ポイントを通過して先に進むことができるのかが決定されます。「チェック ポイントを使用する」を参照してください。
PathProgressConfig は、BotConfig::m_pathProgressConfig によって、または Bot::SetPathProgressConfig() を呼び出すことによって設定できます。
たとえば、Bot が新しいショートカットをチェックする頻度、ショートカットを離すことができる距離、パスに沿ってチェックする候補ポイントの間隔などをコントロールできます。
たとえば、Bot がコーナー上のチャネル境界にどのくらい近づくことができるか、どのくらいの頻度でスプラインを再計算する必要があるか、各スプラインの望ましい長さなどをコントロールできます。
キャラクタの望ましい最大速度(LocomotionModelConfig::m_maxDesiredLinearSpeed)は、Bot クラスのショートカット アクセサ Bot::SetMaxDesiredLinearSpeed() および Bot::GetMaxDesiredLinearSpeed() を介しても公開されます。
NavigationProfile は、パス計算中およびパス フォローイング中に使用されるクラスのインスタンスを提供するオブジェクト ファクトリです。主な目的は、次の 3 つです。
World は、初期化時にデフォルトの NavigationProfile を作成し、維持します。これは、SDK で提供されるデフォルトのすべてのパス ファインディングおよびパス フォローイング クラスのインスタンスへのアクセスを提供します。すべての Bot は、別途指定しない限り、このデフォルトの NavigationProfile を使用するように初期化時に自動的に設定されます。
デフォルトの NavigationProfile は、何も設定しなくても完全に機能しますが、提供される一連のデフォルト オブジェクトは高度なカスタマイズが可能です(詳細については、前のセクションを参照)。このデフォルト プロファイルは、プロジェクトで問題なく使用し続けることができます。NavigationProfile が提供する 1 つまたは複数のクラスのデフォルトの実装をオーバーライドする特別な必要性がある場合にのみ、別の NavigationProfile を使用してください。
NavigationProfile でユーザによるカスタマイズが必要になる一般的なケースは次のとおりです。
これらのすべての場合で、カスタム実装を提供するために NavigationProfile のカスタム クラスを設定する必要があります。
NavigationProfiles は、World によって一元管理されます。新しい NavigationProfile を設定するたびに、World は一意の ID をそれに割り当てます。その他のオブジェクト(通常は Bot およびパス ファインディング クエリー)をその他のオブジェクトが使わなければならないプロファイルで設定するために、この ID 値を使用します。
デフォルト NavigationProfile の一意の ID は常に 0(ゼロ)であることに注意してください。
Bot のカスタム NavigationProfile を設定するには:
ただし、そのページの「上級」のパス計算方法で説明されているとおり、カスタムのパス ファインディング クエリーまたは独自の事前計画済みパスを使用して Bot を設定する場合、Bot はそのパスに追従している間はクエリーや Path オブジェクトに設定されたプロファイル ID を自動的に使用します。Bot でカスタム プロファイルを使用する場合は、IPathFinderQuery::SetNavigationProfileId() または Path::SetNavigationProfileId() メソッドを呼び出して、カスタム プロファイルの ID を使用してカスタム クエリーまたは Path オブジェクトを設定する必要もあります。
// The NavigationProfile in this example uses a custom TraverseLogic and a custom IPathEventListObserver. class MyTraverseLogic : public Kaim::DefaultTraverseLogic { public: static KY_INLINE bool CanTraverseNavTriangle(void* userData, const Kaim::NavTriangleRawPtr& triangleRawPtr, const Kaim::NavTag& navTag, KyFloat32* costMultiplier) { ... } }; class MyPathEventListener : public Kaim::IPathEventListObserver { public: virtual void OnPathEventListBuildingStageDone(Kaim::Bot* bot, Kaim::PathEventList& pathEventList, KyUInt32 firstIndexOfNewEvent, FirstIntervalStatus firstIntervalStatus) { ... } virtual void OnPathEventListDestroy(Kaim::Bot* bot, Kaim::PathEventList& pathEventList, DestructionPurpose destructionPurpose) { ... } }; class MyNavigationProfile : public Kaim::NavigationProfile<MyTraverseLogic> { public: virtual Kaim::Ptr<Kaim::IPathEventListObserver> GetSharedPathEventListObserver() { if (m_myPathEventListener == KY_NULL) m_myPathEventListener = *KY_NEW MyPathEventListener(); return m_myPathEventListener; } public: Kaim::Ptr<MyPathEventListener> m_myPathEventListener; }; ... // in your World initialization code: const KyUInt32 databaseCount = 1; m_world = *KY_NEW Kaim::World(databaseCount); Kaim::Ptr<MyNavigationProfile> myNavigationProfile = *KY_NEW MyNavigationProfile(); KyUInt32 navigationProfileId = m_world->AddNavigationProfile(myNavigationProfile); ... // in your Bot initialization code: m_navBot = *KY_NEW Kaim::Bot; Kaim::BotInitConfig botInitConfig; botInitConfig.m_database = m_world->GetDatabase(0); botInitConfig.m_startPosition = m_position; botInitConfig.m_startNewPathNavigationProfileId = navigationProfileId; m_navBot->Init(botInitConfig); // We add the Bot to our Database. m_navBot->AddToDatabase(); ...
特定のアニメーションを再生したり(はしごを登る、ジャンプするなど)、カットシーンを再生したりするために、キャラクタの動きを一時的に完全にコントロールしたいことがあります。
コントロールを一時的に取得するために、パスへの追従だけを通常どおりに続けて、パス フォローイング システムによって計算された速度は無視することができます。
ただし、Bot::SetDoValidateCheckPoint() と Bot::SetDoComputeTrajectory() の両方 を呼び出して、一時的にパス フォローイングを無効にすることをお勧めします。キャラクタの動作を完全にコントロールする必要がなくなったとき、パス フォローイングを再度アクティブにするには、これらを再び呼び出します。例:
void MyJumpObject::ManageTraversing() { // Take control m_navBot->SetDoValidateCheckPoint(false); m_navBot->SetDoComputeTrajectory(false); ... // manage playing the jump animation if (animationIsFinished) { // Release control m_navBot->SetDoValidateCheckPoint(true); m_navBot->SetDoComputeTrajectory(true); } }
この方法でパス フォローイング システムが無効になっている間、Navigation Lab でのビジュアル デバッグでは Bot がデフォルトの黄ではなく青でレンダリングされることに注意してください。
また、キャラクタの動作のコントロールを保持している時間、および動かした距離によっては、コントロールを解放するときに現在のターゲット ポイントを強制的にパスの前方にする必要がある場合があることにも注意してください。「スマート オブジェクトを作成する」を参照してください。