“智能对象”是一种对象的通称,这种对象在角色跟随路径时管理任何类型的与角色的特殊交互,也就是说,它们是任何不由路径跟随系统以本机方式管理的对象。智能对象可以采用多种可能的形式,具体取决于情景和游戏玩法的需要,以及要与动画子系统交互的方式等等。例如,智能对象可能:
Gameware Navigation SDK 不提供智能对象的任何默认实现。但是,它提供用于编写您自己的自定义智能对象(可在路径跟随过程的特定时间部分或完全控制角色的运动)所需的所有工具。
当您编写自己的智能对象时,必须在代码中执行的确切步骤很大程度上取决于您试图制造的效果。但是,大多数典型的智能对象类型可能会使用此页面上显示的大多数(若非全部)策略。
您可能需要使用 NavTag 来标记要由每个智能对象控制的地形区域。该步骤并非绝对必要;您可以在不使用 NavTag 的情况下成功集成自己的智能对象。但是,NavTag 会集成到路径跟随系统中,为您提供一种简单的方法来确定角色规划包含智能对象的路径的时间,以及接近由智能对象控制的区域的时间。
典型的方法是使用 NavTag 嵌入自定义 ID,以便在运行时用于确定每个 NavData 区域涉及的智能对象的类型。例如,表示梯子的 NavGraph 可使用一个 ID 值标记,而表示电梯的 NavGraph 会使用不同的值进行标记。
在 NavData 中设置这些 NavTag 的具体方式取决于要创建的对象的类型。
有关 NavTag 的信息,请参见使用自定义数据进行标记。
有关 TagVolume 和动态障碍物的信息,请参见使用动态障碍物和 TagVolume。
您可能需要智能对象来跟踪计划使用的角色。因此,您可以使角色正确响应智能对象的状态更改。例如,当门锁上之后或者桥销毁后,您可能希望角色重新计算其路径以找到可通往其目标的不同路径。这通常包括当角色规划包含智能对象的路径时向智能对象注册每个角色,但如果其路径发生更改,则会注销角色并且不再包括对象。
要向沿其路径的智能对象注册和注销您的角色,可以使用 IPathEventListObserver(用于检查每个新建路径是否存在使用与其中一个智能对象相关联的 NavTag 进行标记的事件)的自定义实现。
有关使用 IPathEventListObserver 的详细信息,请参见监视 PathEvent。
在角色跟随其路径的同时,您需要监视即将出现的智能对象。当您的角色接近对象时,它们应开始向智能对象请求指令。
通常,这意味着检查即将在角色路径上出现的下一个 PathEvent 的 NavTag。您可以通过调用 Bot::GetUpcomingEventNavTag() 执行此操作。如果返回的 NavTag 与和智能对象关联的 ID 相匹配,可以使您的智能对象在当前穿过角色时注册角色,并可以开始向 Bot 发出指示。它可能会立即控制角色的运动,也可能使人物正常地继续跟随其路径,直到其到达某个距离范围内。
最后,您的智能对象可能要在角色穿越对象的限定时间内控制角色的运动:如穿过门、爬梯子、站在电梯上、播放特定动画等。当您想实施完全控制时,应通过调用 Bot::SetDoValidateCheckPoint() 和 Bot::SetDoComputeTrajectory() 并将 false 传递给这两种方法来取消激活角色的路径跟随系统。
角色成功穿越智能对象后,或完成智能对象确定需要执行的任何运动后,可以通过再次调用 Bot::SetDoValidateCheckPoint() 和 Bot::SetDoComputeTrajectory() 并将 true 传递给这两种方法来重新启用路径跟随系统。
请注意,在控制路径跟随时,目标点计算处于禁用状态。因此,在控制时,人物保留的当前目标点仍处于原位置:通常会回到位于角色刚穿过的智能对象起点处的路径事件。解除控制时,您可能因此需要向前推进目标点直到智能对象的结尾处,以确保角色不会再次尝试穿过智能对象。您可以按如下所述执行该操作:
// 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 );
取决于智能对象的特性,您可能希望或不希望允许人物在使用智能对象时重新计算新路径。例如,您可能要在人物跳跃时停止计算新路径,以防止其在半空中更改方向;或当人物使用电梯时停止计算新路径。另一方面,您可能希望在人物爬梯子或使用门时计算新路径。典型的处理方法是先让人物类与当前的智能对象协商,然后再计算新路径。
但是,在某些情况下,您的智能对象所链接到的 NavGraph 可能会将人物带到 NavMesh 边界外太远的地方,以至于寻径系统无法将自身连接到 NavMesh。或者,您可能需要强制人物在 NavGraph 的特定边开始新的路径。在这些情况下,您仍然可以在人物使用智能对象时重新计算新路径;但是,在人物使用智能对象时,因为人物的这一位置不是空间化到 NavMesh 中,您必须通过希望启动新路径的 NavGraph 边或顶点,设置 AStarQuery。
同样,通过希望新路径结束的 NavGraph 边或顶点,设置 AStarQuery,可以规划结束于智能对象的路径,即使该目标不在 NavMesh 内,也是如此。
详细信息请参见AStarQuery 选项。
LabEngine 项目包含多个不同类型智能对象的示例,包括门、电梯、梯子、需要跳过的岩浆等等。SDK 示例中使用了这些智能对象,您可以在 Navigation Lab 中启动这些示例;请参见Navigation Lab 快速入门。为您提供了这些对象的完整源代码以用作模型。请参见 tools\LabEngine\include\LabEngine\smartobjects 和 tools\LabEngine\src\smartobjects 目录下的文件。