对于最常见的路径计算情景,通常建议使用 AStarQuery 类:通过 NavMesh 和 NavGraph 查找到达特定预定目标的路径。它提供了一些选项,可用于控制自己生成的路径的特性,以及调节寻径计算的性能。
不过,在特殊情况下,您可能希望使用不同的查询类生成 Path,从而满足某些特定条件。这既可以是 Gameware Navigation SDK 中提供的备选寻径查询类,也可以是您为了满足游戏情景的特定需要而编写的自定义查询类。
此页介绍了 Gameware Navigation SDK 中提供的另一种寻径查询类以及编写自己的自定义寻径查询的要求。
有关如何设置 Bot 以使用备用寻径查询的详细信息,请参见获取静态路径。
与 AStarQuery 不同,BestGraphVertexPathFinderQuery 不会查找预定目标的路径。相反,它允许您选择目标,这目标必须是 NavGraph 中的顶点,在路径计算中是动态的。例如,您可以使用此查询,将人物移动到最接近的掩护点、狙击点位置、医药包、武器升级等等。
查询通过 NavMesh,从指定的起点向各个方向对外传播。对于其发现的可作为潜在目标的各个 NavGraph 顶点,此查询调用您编写并作为模板参数提供的自定义谓词命令类的实例,此自定义谓词命令类与您提供给 AStarQuery 的自定义谓词命令类似,可供您确定是否将此顶点选作最终目标。
此查询将继续浏览 NavMesh,以查找候选 NavGraph 顶点,直到自定义谓词命令表明搜索应停止,或直到超过此查询的最大路径成本设置。
由于此查询类只将 NavGraph 顶点作为潜在目标进行测试,您需要确保,在您希望此查询可能选择的 3D 空间中的每个点,都已创建了 NavGraph 顶点。例如,如果要使用此查询选择掩护点,则必须创建 NavGraph,为每个潜在掩护点添加一个顶点,然后将 NavGraph 添加到要用于查询的 Database。
有关此过程的详细信息,请参见创建 NavGraph。
您提供给 BestGraphVertexPathFinderQuery 的模板类应该用于实现常用 TraverseLogic 接口,以确定是否禁止变换到不同的 NavTag,并且其需要具有与用于确定是否允许单向 NavTag 变换相同的类型定义。有关详细信息,请参见 SimpleTraverseLogic 类和禁止选择、避免选择和优先选择 NavTag。
此外,您必须提供以下虚拟方法的实现以通过 NavData 监视查询的传播:
static OnGraphVertexVisitedResult OnGraphVertexVisited(void* userData, const NavGraphVertexRawPtr& currentGraphVertex, const NavGraphVertexRawPtr& bestGraphVertex, Ptr<Path> pathToBest);
在搜寻期间,此查询每当遇到 NavGraph 顶点都会系统地调用此方法。此方法用于评估在 currentGraphVertex 参数中传递的 NavGraph 顶点的匹配性,确定它作为目标是否好于 bestGraphVertex 参数中传递的顶点。它通过其返回值表示是否要将此候选顶点记为目前找到的最佳目标,以及是否应继续搜索。
如果您需要检查候选顶点的路径,然后决定是否应将此顶点应用为目前找到的最佳目标,OnGraphVertexVisited() 方法可以请求此查询来计算路径。在这种情况下,该查询调用 OnPathToGraphVertexComputed() 方法,如下所示。
static OnPathToGraphVertexComputedResult OnPathToGraphVertexComputed(void* userData, const NavGraphVertexRawPtr& currentGraphVertex, Ptr<Path> pathToCurrent, const NavGraphVertexRawPtr& bestGraphVertex, Ptr<Path> pathToBest);
仅当 OnGraphVertexVisited() 方法表示它需要检查候选顶点的路径,并确定是否应将候选顶点选为目前找到的最佳目标时,此查询才会调用此方法。此方法可以比较当前候选顶点的路径与目前找到的最佳顶点的路径。它通过其返回值表示是否要将此候选顶点记为目前找到的最佳目标,以及是否应继续搜索。
BestGraphVertexPathFinderQuery 类支持 AStarQuery 所提供的大多数相同选项。详细信息请参见AStarQuery 选项。
唯一的区别是,此查询不是使用矩形框约束传播,而是使用圆,其半径值通过调用 BestGraphVertexPathFinderQuery::SetPropagationRadius() 设置。
通常情况下,AstarQuery 或 BestGraphVertexPathFinderQuery 用于查找目标的路径。但是,如果您知道用于形成在运行时要跟随的路径的连续的 3D 位置(多段线),您可以使用 PathFinderFromPolyline 查询,而不是其他查询。PathFinderFromPolyline 查询利用多线段的输入 3D 位置创建 Kaim::Path 的实例。多线段必须完全位于 NavMesh 内,以便 PathFinderFromPolyline 查询成功。
您可以写入自己的查询类,以查找您的人物所要遵循的路径。这使您能够完全控制路径计算,而不影响人物路径跟随系统的任何其他子系统。只要类遵循下面的概述,它应完全兼容其余的寻径和跟随系统。
您必须从 Kaim::IPathFinderQuery 衍生类,或从 Gameware Navigation SDK 中提供的寻径查询类之一(如 AStarQuery)衍生类。
如以下部分所述,您必须在 Kaim::IPathFinderQuery 基本类中提供对所有纯虚拟方法的实现。另请参见此文档和 Kaim::IPathFinderQuery、Kaim::ITimeSlicedQuery 和 Kaim::IQuery 基本类的头文件。
另请参见 AStarQuery 和 BestGraphVertexPathFinderQuery 类的实现,作为示例实现。
这是 API 的主方法,由人物调用,响应您对 Bot::ComputeNewPathAsync() 的调用,执行实际的路径计算。您的实现应执行以下操作:
请注意,为了确保人物使用的路径跟随系统与用于生成路径的设置兼容,每个 Path 均维护着要跟随该路径所必须使用的 NavigationProfile 的唯一 ID。只要 Bot 跟随插入的路径,其路径跟随系统将自动使用该 NavigationProfile 以检索其应该用于控制路径跟随的所有可自定义对象,如 TraverseLogic 和 IPathEventListObserver。
默认情况下,您从头创建的新 Path 对象将设置为使用 World 维护的默认 NavigationProfile。如果新 Path 对于其跟随的路径有任何要求使用自定义 NavigationProfile 的特殊要求,则必须通过调用 Path::SetNavigationProfileId() 在您的 Path 中设置相应的轮廓 ID。
此方法对于每个查询类将返回一个唯一的标识符。编辑 iquery.h 中的 QueryType 枚举,以便在 QueryType_FirstCustom 值后为查询添加新的条目,然后从该方法返回此值。