设置 CylinderObstacle

此页面介绍了如何在您的游戏中创建、更新和销毁 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;
}