此页面包含有关 Gameware Navigation 世界和 Navigation Lab 提供的可视调试系统的一些详细信息。
每个世界均包含一个内置的 VisualDebugServer 类实例。此类使用 Navigation Lab 管理所有运行时通信:
如果激活 VisualDebugServer,需要提供 VisualDebugServerConfig 配置对象。此配置对象包含若干可以根据需要进行设置的参数。
最重要的配置参数可能是端口设置 VisualDebugServerConfig::m_serverPort 和 VisualDebugServerConfig::m_broadcastPort,它们可确定服务器将用来侦听传入连接并传播其可用性的端口。如果在将 Navigation Lab 连接到游戏时遇到问题,请确保这些端口已打开,或者在游戏中以及尝试连接到 Navigation Lab 时更改这些端口。
衍生自 WorldElement 类的每个对象(例如人物、动态障碍物、TagVolume 和关注点)会在每一帧将数据通过网络自动发送到 Navigation Lab,以指示其当前位置、速度等信息。默认情况下,每个对象配置为仅发送最重要的常用信息项,例如其当前位置、尺寸、速度等。调试 Navigation Lab 中的游戏时,对于 Visual debug 面板中每一类的 WorldElement,可以选择要查看的项。
每种类型的对象还都可以将其他细节发送到 Navigation Lab;例如,人物可以发送关于它们的路径跟随和动态回避计算状态的详细信息。但是,为了避免过度占用游戏与 Navigation Lab 之间的网络通信带宽,默认情况下不发送这些详细信息。
如果需要查看可以为对象录制和发送的整个范围的数据,您可以在游戏代码中将该对象设置为使用最大详细级别 (LOD)。如果执行此操作,则该对象会在内部创建其他显示列表,并将其发送到 Navigation Lab 上显示。这些其他显示列表出现在 Visual debug 面板的 Display lists 标题下。但是,对于设置为使用最大细节层次的人物而言,其他显示列表大多出现在 Visual debug 面板中的 Bot 标题下。与任何其他显示列表类似,您可以显示或隐藏包含在其他显示列表中的数据。
您可以通过设置 ScopedDisplayList 类的实例,将自己的 2D 图形和 3D 体积从游戏中发送到 Navigation Lab。
您创建的每个 ScopedDisplayList 仅发送到 Navigation Lab 一次(在用户创建的帧之后)。但是,每个显示列表都有指定的寿命,确定 Navigation Lab 会在多长时间内显示其数据。
寿命为单帧的显示列表仅在 Navigation Lab 从游戏中接收时渲染一次。为了使单帧显示列表中的数据能在 Navigation Lab 中跨多个帧持续显示,必须对每一帧重新创建新的 ScopedDisplayList 对象。此方法通常用于经常更改的数据。例如:
{ Kaim::ScopedDisplayList displayList(navWorld); displayList.InitSingleFrameLifespan("Display list name", "Category name"); displayList.PushLine(gameBot->GetPosition(), Kaim::Vec3f::Zero(), Kaim::VisualColor::White); ... // Add more shapes here } // Here the ScopedDisplayList is sent to the Navigation Lab.
寿命为多帧的显示列表同样会发送到 Navigation Lab 一次,但它们会在这之后的每一帧中进行渲染,直到您对其进行修改或将其删除。如果您有数据在游戏玩法会话中保持静态,此方法可避免涉及在每个帧中重新创建该显示列表的计算,并节省在每个帧中重新发送显示列表所使用的网络带宽。
寿命为多帧的显示列表可通过提供的类别名称和显示列表名称组合,或通过 DisplayListManager 生成的数字 ID 唯一标识:
您可以使用该类别和名称组合或唯一 ID,以标识显示列表从而对其进行修改或将其删除:
// Get a unique ID m_displayListId = navWorld->GetDisplayListManager()->GenerateDisplayListId(); // Create a ScopedDisplayList: { Kaim::ScopedDisplayList displayList(navWorld); m_displayListId = displayList.InitUserControlledLifespan("Display list name", "Category name", m_displayListId); displayList.PushLine(gameBot->GetPosition(), Kaim::Vec3f::Zero(), Kaim::VisualColor::White); ... // Add more shapes here } // Here the ScopedDisplayList is sent to the Navigation Lab and rendered every frame. ... // Modify the existing ScopedDisplayList: { Kaim::ScopedDisplayList displayList(navWorld); m_displayListId = displayList.InitUserControlledLifespan("Display list name", "Category name", m_displayListId); ... // Add different shapes here } // Here the ScopedDisplayList is sent to the NavigationLab, replacing the previous display list. ... // Remove the existing ScopedDisplayList: { navWorld->GetDisplayListManager()->RemoveDisplayList(m_displayListId); // The list is no longer displayed in the Navigation Lab. }
每次 Navigation Lab 在为游戏中的帧显示数据时,它会在 Visual debug 面板中的 Display lists 标题下列出对此帧有效的所有显示列表,并按您为显示列表提供的类别名称加以组织。您可以使用这些控件切换 3D 视图中每个显示列表的可见性。
例如,在下面的图像中,“MeleeCombat”为包含不同显示列表名称(“MeleeDistance”、“MeleeEdgeCollector”、“MeleeTarget”和“VisitedTriangles”)的显示列表所设置的类别名称。每个显示列表有自己的复选框,组织在共享类别名称下面。
您可以将 ScopedDisplayList 与特定 WorldElement(例如人物或动态障碍)相关联。当显示列表与 WorldElement 相关联时,可以控制此显示列表在 Navigation Lab 中的渲染以及该对象相关信息的其他项。
若要将 WorldElement 与 ScopedDisplayList 关联,请通过调用其 GetVisualDebugId () 方法检索 WorldElement 对象的 ID,并在 ScopedDisplayList 的初始化中提供该 ID。您仍然可以提供类别名称,该名称将用于在 Visual debug 面板中组织该 WorldElement 的显示列表。
对于用户控制的寿命的显示列表,如前面部分所述,您可以通过类别名称和显示名称的组合或通过明确指定唯一的 ID 来标识显示列表。
如果将游戏摄影机姿势和参数发送到可视调试器,您可以使 Navigation Lab 中 3D 视图下的摄影机跟随游戏摄影机的位置和方向。
m_navigationWorld.GetVisualDebugServer()->SendGameCameraAttitude( m_coordSystem.ClientToNavigation_Pos(pos), m_coordSystem.ClientToNavigation_Normal(right), m_coordSystem.ClientToNavigation_Normal(up), m_coordSystem.ClientToNavigation_Normal(front), m_FOV);
可在游戏中将 VisualDebugServer 设置为接受来自 Navigation Lab 中的命令行的自定义命令。这样可在调试期间在游戏中触发事件。
有关代码示例,请参见 Tutorial_VisualDebug.cpp 文件。