Gameware Navigation에는 레벨 형상에 대해 공간의 두 점 사이에서 고성능 충돌 테스트(광선 투사)를 수행할 수 있는 복잡하지 않은 경량 시스템이 포함되어 있습니다.
예를 들어 이 시스템을 사용하여 다음을 수행할 수 있습니다.
이러한 테스트는 물리적 하위 시스템에 의해 수행되는 경우가 자주 있습니다. 그러나 많은 게임(대부분 MMO)에서 네트워크 통신 속도 지연, 기술 복잡성 및/또는 런타임 성능 오버헤드는 완벽한 기능을 갖춘 물리 시스템을 통합하는 데 있어 문제 또는 비용 부담을 야기할 수 있습니다. 이러한 상황이 사용자의 프로젝트에 해당되지만 게임 레벨의 형상에 대해 이러한 종류의 충돌 테스트를 여전히 수행해야 하는 경우 Gameware Navigation 충돌 시스템을 활용할 수 있습니다.
기본 제공 충돌 시스템은 지세에 대한 NavData와 구분되는 사전 생성된 데이터를 사용합니다. 따라서 데이터 생성 프로세스 중 제공한 지세의 정적 요소에서만 충돌을 감지할 수 있습니다. 이 시스템은 런타임 시 추가되는 동적 오브젝트를 지세에 대한 NavData에 통합하는 경우에도 해당 오브젝트를 고려하지 않습니다.
충돌 데이터를 생성하려면 C++ NavData 생성 API를 사용합니다. NavData 생성 API를 게임 편집기, 레벨 디자인 도구 또는 빌드 프로세스에 아직 통합하지 않은 경우 통합 단계 6: NavData 생성 API 사용을(를) 참조하십시오.
NavData 생성 코드에서 지세의 원하는 각 섹터에 대해 충돌 데이터 생성을 활성화해야 합니다.
섹터에 대해 NavData를 생성하면 해당 섹터에 대해 NavData 생성 시스템으로 전달하는 삼각형에서 충돌 데이터도 자동으로 생성됩니다. 각 섹터에 대한 데이터는 해당 섹터에 대해 생성되는 .NavData 파일과 동일한 파일 이름을 사용하여 동일한 위치에 .ColData 파일로 디스크에 기록됩니다.
// Create a sector... Kaim::GeneratorSectorConfig sectorConfig(Kaim::KyGuid::GetDefaultGuid(), generationName); Kaim::GeneratorSector* sector = env.m_generatorInputOutput.AddSector(sectorConfig); ... // Activate collision data generation sector->SetColDataBuildMode(Kaim::GenFlags::SECTOR_COLDATA_BUILD_ENABLED); ... // Generate NavData and collision data KyResult result = m_generator->Generate(m_generatorInputOutput);
지세의 각 섹터를 구성하는 개별 삼각형에 NavData 생성 시스템을 제공하는 대신 heightfields 및 삼각형 메시를 제공할 수 있습니다.
heightfield는 간단한 단층 지세의 고도를 나타내는 최적화된 방법입니다. 지세 메시를 구성하는 모든 삼각형을 포함하는 대신 단일 원점과 원점 주변의 일반 그리드에서 샘플링된 고도 값 세트로 구성됩니다. 이 데이터는 전체 삼각형 메시보다 훨씬 더 간단하고 덜 복잡하기 때문에 런타임 메모리 사용이 줄고 충돌 테스트의 성능이 훨씬 더 향상됩니다.
heightfields 사용의 부정적인 측면은 일반적으로 그리드에 있는 샘플의 간격 내에서 발생하는 높이의 로컬 변형에 대해 정확성이 떨어질 수도 있다는 점입니다. 그러면 NavMesh가 heightfields에서 생성될 수 있으므로 이에 대해 수행되는 충돌 테스트의 정확성이 떨어질 수 있습니다. 이렇게 정확성이 떨어지는 문제를 해결하기 위해 지세의 더 작은 기능에 대해 보다 정확한 사실성이 요구되는 보다 복잡한 지세 영역에는 삼각형 메시를 제공할 수도 있습니다.
효율성과 정확성 사이에서 최상의 절충안을 얻으려면 heightfields를 사용하여 벌판과 같이 넓게 펼쳐진 영역을 나타내고 삼각형 메시를 사용하여 도시 블록과 같이 보다 많은 정확성이 필요한 영역을 나타냅니다. 예를 들면 다음과 같습니다.
섹터에 heightfields 및 인덱스 처리된 메시를 제공하려면 NavData 생성 파이프라인에서 사용하는 GeneratorInputProducer에서 GeneratorInputProducer::Produce()의 구현을 업데이트하여 NavData 생성 시스템에 지세 형상을 전달해야 합니다.
이 방법을 사용할 경우 heightfields 및 삼각형 메시에 NavData가 생성됩니다. 따라서 개별 삼각형을 ClientInputConsumer로 직접 제공할 필요가 없습니다.
각 World는 CollisionWorld 클래스의 인스턴스를 해당 World::m_collisionWorld 클래스 구성원에서 유지합니다. 이 클래스는 메모리에 로드되는 충돌 데이터 집계와 해당 데이터에 대해 수행하는 충돌 테스트 관리를 담당합니다. 이 작업은 World를 초기화한 후 제공해야 하는, ICollisionInterface를 구현하는 클래스 인스턴스의 메서드를 호출하여 수행합니다.
Gameware Navigation에는 오픈 소스 Bullet 물리학 및 충돌 테스트 시스템을 사용하는 ICollisionInterface 구현이 포함되어 있습니다. 자세한 내용은 www.bulletphysics.org를 참조하십시오.
기본 ICollisionInterface 구현을 사용하려면
m_navigationWorld = *KY_NEW Kaim::World(databaseCount); Kaim::Ptr<Kaim::ICollisionInterface> visInterface = *KY_NEW CollisionInterface(m_navigationWorld); m_navigationWorld->m_collisionWorld->SetCollisionInterface(visInterface);
지세에 대해 만든 충돌 데이터에 대해 충돌 테스트를 수행해야 하는 경우 충돌 데이터를 메모리로 로드하고 충돌 표준에 추가해야 합니다. 일반적으로 이 작업은 메모리 내부 및 외부의 해당 섹터에 필요한 NavData 및 다른 종류의 데이터를 스트리밍할 때 동시에 지세의 각 섹터에 대해 수행합니다. 이 프로세스는 Database 내부 및 외부의 NavData 스트리밍과 매우 유사합니다.
Kaim::Ptr<Kaim::CollisionData> colData = *KY_NEW Kaim::CollisionData; if (Kaim::Result::Fail(colData->Load(GetAbsoluteInputFileName(fileName).c_str(), &m_fileOpener))) return KY_NULL; GetWorld()->m_collisionWorld->AddCollisionData(colData);
World로 로드한 충돌 데이터에 대해 충돌 테스트를 실행하려면 CollisionRayCastQuery 클래스의 인스턴스를 설정하고 시작합니다.
예를 들어 다음 코드는 점 A와 점 B 사이의 직선 경로를 따라 충돌을 테스트합니다.
Kaim::CollisionRayCastQuery query; query.BindToWorld(m_navigationWorld); query.Initialize(pointA, pointB); query.PerformQuery(); if (query.GetResult() == Kaim::RayHit) ... // A collision was found if (query.GetResult() == Kaim::RayDidNotHit) ... // No collision was detected
또한 쿼리 시스템에서 제공하는 메커니즘을 사용하여 World에서 유지하는 대기열 또는 직접 만들고 프레임당 최대 시간 예산으로 설정한 사용자 정의 대기열에서 비동기로 CollisionRayCastQuery를 실행할 수 있습니다. 게임이 동일한 프레임에서 여러 가지 충돌 테스트를 요청해야 하는 경우 이러한 방법을 사용하면 CPU 피크를 방지할 수 있습니다.
자세한 내용은 쿼리 시스템 사용을(를) 참조하십시오.