您可以通过多种方法为角色自定义路径跟随系统,有简单的(如调用类方法),也有复杂的(重新实现核心类)。本主题以及本部分中的其他主题概述了用于控制路径跟随系统各种元素的操作的一些最常用的选项和策略。
您可以在 BotConfig 对象中设置 Bot 配置参数,该对象在 Bot::Init 调用初始化时提供。该方法允许您创建和设置单个配置对象,可用于通过一组相同配置参数来设置多个游戏角色。
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);
也可以通过调用 Bot API 的方法,为每个角色动态设置 BotConfig 中的所有配置参数。
BotConfig 的简单数据成员将通过 Bot 类的方法直接公开。对于 BotConfig 公开的从属配置对象,Bot 类还公开了取值函数方法以获取并设置当前实例。
bot->SetEnableAvoidance(true); Kaim::ShortcutTrajectoryConfig shortcutConfig; shortcutConfig.SetDefaults(); shortcutConfig.m_maxDistanceFromBot = 20.0f; bot->SetShortcutTrajectoryConfig(shortcutConfig);
但是,查询支持的配置选项多于 PathFinderConfig 中公开的配置选项。如果要使用其中的任何其他选项,或动态设置不同的选项用于一次性路径计算,您需要直接设置查询。请参见获取静态路径下的“高级”路径计算方法。
您可以使用 PathProgressConfig 类来设置一些参数,以确定路径跟随系统如何跟踪 Bot 沿其路径的前进情况。
例如,如果您广泛使用检查点系统,可能需要自定义 PathProgressConfig::m_checkPointRadius 值,用于确定允许 Bot 继续通过检查点前其必须达到的与检查点的接近程度。请参见使用检查点。
您可以在 BotConfig::m_pathProgressConfig 中,或通过调用 Bot::SetPathProgressConfig() 来设置 PathProgressConfig。
例如,您可以控制 Bot 检查新捷径的频率、捷径的最远距离、其沿路径检查的候选点的间距等。
例如,您可以控制 Bot 到通道边界对角的最小距离、重新计算其样条线的频率、每个样条线所需的长度等。
角色的最大期望速度 (LocomotionModelConfig::m_maxDesiredLinearSpeed) 也通过 Bot 类中的捷径取值函数 Bot::SetMaxDesiredLinearSpeed() 和 Bot::GetMaxDesiredLinearSpeed() 公开。
NavigationProfile 是提供用于路径计算和路径跟随的类实例的对象工厂。有三种主要用途:
World 可以在初始化时创建并维护默认 NavigationProfile,以提供对 SDK 随附的所有默认寻径和路径跟随类的实例的访问。除非另外指定,否则每个 Bot 都会在初始化时自动设置为使用该默认 NavigationProfile。
请注意,默认 NavigationProfile 是开箱即用的完备功能,其服务的默认对象集可以高度自定义(有关详细信息,请参见上一部分)。当然,您可以继续在项目中使用此默认轮廓。如果因特定原因需要针对其服务的一个或多个类覆盖默认实现,您只需使用不同的 NavigationProfile。
NavigationProfile 中最常见的用户自定义需求包括:
在所有这些情况下,您都需要设置 NavigationProfile 的自定义类以为自定义实现提供服务。
NavigationProfile 由 World 集中管理。每次设置新的 NavigationProfile,World 都会为其指定一个唯一 ID。您可以使用该 ID 值通过应该使用的轮廓来设置其他对象(通常为 Bot 和寻径查询)。
请注意,默认 NavigationProfile 的唯一 ID 始终为 0。
但是,请注意,如果您使用自定义寻径查询或自己预先计划好的路径设置 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 中进行可视调试时渲染为蓝色,而非默认的黄色。
还请注意,根据您控制角色移动的时长和距离,可能需要在解除控制时强制当前目标点沿路径向前移动。请参见创建智能对象。