ここでは、ゲームで CylinderObstacles を作成、更新、および破棄する方法について説明します。
障害物の管理システムにおける CylinderObstacles クラスの役割については、「動的な障害物や TagVolume を使用する」を参照してください。
NavTag システムのバックグラウンド情報については、「カスタム データでタグ付けする」を参照してください。
CylinderObstacle の初期化と破棄を管理するクラスをゲーム内で作成する必要があります。ゲーム内に既に Gameware Navigation World 内で CylinderObstacle が表しているオブジェクトやプレイヤー キャラクタのライフスパンの寿命を管理するクラスがある場合があります。その場合は、そのクラスを使用できます。また、各フレームでのオブジェクトの位置と速度を取得できる、類似オブジェクトが物理システム内に存在していることもあります。
例: [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 はすぐに変更されないことに注意してください。更新は World の次の更新まで遅延されます。
例: [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 に統合することが望ましくなります。これは、ゲーム内の Bot が、パス フォローイングのダイナミック回避フェーズ中にだけ障害物の存在に反応するのではなく、地形を通るパスをプランする場合にもその存在を考慮できるようにするためです。
障害物が停止状態になったら、その障害物の CylinderObstacle::DoesTriggerTagVolume() メソッドを呼び出し true を渡します。World の次の更新時に、障害物によって 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; }