此页面介绍了如何在您的游戏中创建、更新和销毁 CylinderObstacle。
有关障碍物管理系统中 CylinderObstacle 类的作用的介绍,请参见使用动态障碍物和 TagVolume。
有关 NavTag 系统的背景信息,请参见使用自定义数据进行标记。
您需要在游戏中创建一个用于管理 CylinderObstacle 的初始化和销毁的类。您的游戏中可能已经有一个类在管理 CylinderObstacle 计划在 Gameware Navigation 世界中表示的对象或玩家角色的寿命。如果是这样,则可以使用该类。您可能在物理系统中也有类似对象,用于检索对象在每一帧的位置和速度。
例如:[Tutorial_ObstacleIntegration.cpp 中的代码]
class MyGameCylinderObstacle { public: MyGameCylinderObstacle() : m_navCylinderObstacle(KY_NULL) {} void Initialize(Kaim::World* world, KyFloat32 radius, KyFloat32 height, const Kaim::Vec3f& position, const Kaim::Vec3f& linearVelocity); void Destroy(); void Update(KyFloat32 simulationStepsInSeconds); RigidBodyPhysics m_rigidBodyPhysics; Kaim::Ptr<Kaim::CylinderObstacle> m_navCylinderObstacle; };
要初始化 CylinderObstacle,必须提供 CylinderObstacleInitConfig 配置类的实例,您将使用 CylinderObstacle 需要的数据来设置该类。您必须以最小值设置:
例如:[Tutorial_ObstacleIntegration.cpp 中的代码]
void MyGameCylinderObstacle::Initialize(Kaim::World* world, KyFloat32 radius, KyFloat32 height, const Kaim::Vec3f& position, const Kaim::Vec3f& linearVelocity) { // Initialize the object that represents this obstacle in the physics system. m_rigidBodyPhysics.Initialize(position, linearVelocity); // Set up the CylinderObstacleInitConfig Kaim::CylinderObstacleInitConfig cylinderObstacleInitConfig; cylinderObstacleInitConfig.m_world = world; cylinderObstacleInitConfig.m_radius = radius; cylinderObstacleInitConfig.m_height = height; cylinderObstacleInitConfig.m_startPosition = m_rigidBodyPhysics.GetPosition(); // This sets the NavTag as non-walkable: it will "cut a hole" in the NavMesh. cylinderObstacleInitConfig.m_navTag.SetAsExclusive(); // Create and initialize the CylinderObstacle, and add it to its World. m_navCylinderObstacle = *KY_NEW Kaim::CylinderObstacle; m_navCylinderObstacle->Init(cylinderObstacleInitConfig); // We want to draw a maximum amount of information m_navCylinderObstacle->SetCurrentVisualDebugLOD(Kaim::VisualDebugLOD_Maximal); }
每当 CylinderObstacle 在游戏中表示的对象更改其位置或速度时,您都需要更新 CylinderObstacle 以反映新的状态。您可以使用 CylinderObstacle 中的函数反映新的状态。
请注意,此操作不会立即修改 CylinderObstacle;更新将推迟到世界的下次更新。
例如:[Tutorial_ObstacleIntegration.cpp 中的代码]
void MyGameCylinderObstacle::Update(KyFloat32 simulationStepsInSeconds) { ... // Update the object in the physics system. m_rigidBodyPhysics.Update(simulationStepsInSeconds); // Update the CylinderObstacle. m_navCylinderObstacle->SetPosition(m_rigidBodyPhysics.GetPosition()); m_navCylinderObstacle->SetVelocity(m_rigidBodyPhysics.GetLinearVelocity()); }
如果障碍物停止运动并静止下来,您可能会希望将其集成到 NavMesh,以便游戏中的人物在规划通过地形的路径时可以考虑到它的存在,而不是仅在路径跟随的动态回避阶段对其存在做出反应。
如果障碍物静止下来,请调用其 CylinderObstacle::DoesTriggerTagVolume() 方法,并传递 True。下次更新世界时,障碍物将以相同的位置、尺寸透明地生成 TagVolume,并带有初始化 CylinderObstacle 时设置的 NavTag。然后此 TagVolume 会集成到 NavMesh 中,并以自定义数据对区域进行标记或将其标记为“排他”然后从 NavMesh 中移除。集成完成且 NavMesh 更新后,障碍物的体积会自动从所有动态回避计算中移除,因为其存在现在是通过 NavMesh 进行管理。
如果障碍物再次开始移动,请调用 CylinderObstacle::DoesTriggerTagVolume() 并传递 false 以反转过程。
例如:[Tutorial_ObstacleIntegration.cpp 中的代码]
void MyGameCylinderObstacle::Update(KyFloat32 simulationStepsInSeconds) { const bool isStopped = m_rigidBodyPhysics.IsSleeping(); m_navCylinderObstacle->SetDoesTriggerTagVolume(isStopped); if (isStopped) return; ... }
销毁 CylinderObstacle:
例如:[Tutorial_ObstacleIntegration.cpp 中的代码]
void MyGameCylinderObstacle::Destroy() { m_navCylinderObstacle->RemoveFromWorld(); m_navCylinderObstacle = KY_NULL; }