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