관심 지점 사용

관심 지점은 지정된 위치에서 사용자 정의 데이터를 NavMesh에 공간화하고 특정 공간 영역 내에 있는 점을 신속하게 검색할 수 있는 오브젝트입니다.

PointOfInterest 클래스의 각 인스턴스는 게임에서 나타내는 오브젝트 또는 데이터의 유형을 식별(즉, 은폐 지점, 저격점 등)하기 위해 설정할 수 있는 정수 ID와 게임에서 특정 오브젝트(즉, 무기 또는 탄약 오브젝트, 헬스 팩 등)를 참조하도록 설정할 수 있는 빈 포인터를 유지합니다.

관심 지점은 전적으로 런타임에서 관리되며, 현재 지형에 대한 NavMesh를 사전 생성하는 데이터 생성 프로세스의 일부가 아닙니다. 필요할 때마다 언제든지 런타임에 관심 지점을 생성하고, 필요한 경우 이를 새 위치로 이동하며, 공간 쿼리를 사용하여 검색할 수 있습니다.

게임 쪽 클래스

게임에서 PointOfInterest 초기화 및 파괴를 관리하는 클래스를 설정할 수 있습니다. PointOfInterestGameware Navigation World 내에서 나타내는 오브젝트의 수명을 관리하는 클래스가 게임에 이미 있을 수도 있습니다. 이 경우 해당 클래스를 사용할 수 있습니다.

예: [Tutorial_PointOfInterest.cpp의 코드]

class MyGamePointOfInterest
{
public:
    MyGamePointOfInterest() : m_navPointOfInterest(KY_NULL) {}

    void Initialize(Kaim::World* world, const Kaim::Vec3f& position);
    void Destroy();

    void SetPosition(const Kaim::Vec3f& newPosition);

    Kaim::Ptr<Kaim::PointOfInterest> m_navPointOfInterest;
    ...
};

초기화

PointOfInterest를 초기화하려면 PointOfInterest에 필요한 데이터를 사용하여 설정하는 PointOfInterestInitConfig 구성 클래스의 인스턴스를 제공해야 합니다. 적어도 다음을 설정해야 합니다.

예: [Tutorial_PointOfInterest.cpp의 코드]

void MyGamePointOfInterest::Initialize(Kaim::World* world, const Kaim::Vec3f& position)
{
    ...
    // Set up the PointOfInterestInitConfig
    Kaim::PointOfInterestInitConfig pointOfInterestInitConfig;
    pointOfInterestInitConfig.m_world = world;
    pointOfInterestInitConfig.m_startPosition = position;
    pointOfInterestInitConfig.m_poiType = Kaim::PointOfInterestType_FirstClient;

    // Create and initialize the point of interest, and add it to its World
    m_navPointOfInterest = *KY_NEW Kaim::PointOfInterest;
    m_navPointOfInterest->Init(pointOfInterestInitConfig);
    m_navPointOfInterest->AddToWorld();

    // Set a pointer to your own data
    m_navPointOfInterest->SetUserData(this);
    ...
}

업데이트

PointOfInterest가 나타내는 오브젝트가 해당 위치 또는 게임 내 다른 데이터를 변경할 때마다 PointOfInterest를 업데이트하여 새 상태를 반영해야 합니다. PointofInterest::SetPosition() 함수를 사용하면 새 상태를 반영할 수 있습니다.

이 경우 PointOfInterest가 즉시 수정되는 것은 아닙니다. 다음에 World가 업데이트될 때까지 업데이트가 지연됩니다.

예: [Tutorial_PointOfInterest.cpp의 코드]

void MyGamePointOfInterest::SetPosition(const Kaim::Vec3f& newPosition)
{
    m_navPointOfInterest->SetPosition(newPosition);
}

파괴

PointOfInterest를 파괴하려면

예: [Tutorial_PointOfInterest.cpp의 코드]

void MyGamePointOfInterest::Destroy()
{
    m_navPointOfInterest->RemoveFromWorld();
    m_navPointOfInterest = KY_NULL;
}

관심 지점 검색

관심 지점은 Bot 및 동적 장애물과 같은 공간화된 WorldElements의 다른 클래스에서 사용하는 메커니즘과 마찬가지로, 내부 SpatializedPoint 오브젝트를 사용하여 NavMesh에 공간화됩니다. SpatializedPointCollectorInAABBQuery 클래스의 인스턴스를 만들고 실행하여 지정된 경계 상자 내에서 공간화된 점을 검색할 수 있습니다.

기본적으로 쿼리에서는 모든 종류의 공간화된 점을 검색하지만, 결과에 관심 지점만 포함되도록 쿼리에 대한 필터를 제공할 수 있습니다.

예: [Tutorial_PointOfInterest.cpp의 코드]

void CollectAndRenderNearbyPointsOfInterest(Kaim::Database* database, const Kaim::Vec3f& collectorBoxCenter, KyFloat32 collectorBoxHalfExtentFloat)
{
    ...

    // Set up a filter
    Kaim::SpatializedPointCollectorFilter_SelectiveCollect selectiveCollect;
    selectiveCollect.Select(Kaim::SpatializedPointObjectType_PointOfInterest);

    // Instantiate the query
    Kaim::SpatializedPointCollectorInAABBQuery<Kaim::SpatializedPointCollectorFilter_SelectiveCollect> query(selectiveCollect);
    query.BindToDatabase(database);

    // Set up the query parameters
    const Kaim::Vec3f collectorBoxHalfExtentVec3f(collectorBoxHalfExtentFloat, collectorBoxHalfExtentFloat, collectorBoxHalfExtentFloat);
    const Kaim::Box3f collectorBoxExtent(collectorBoxHalfExtentVec3f, collectorBoxHalfExtentVec3f);
    query.Initialize(collectorBoxCenter, collectorBoxExtent);

    // Perform the query
    query.PerformQueryBlocking();
    ...

쿼리가 완료되면 결과를 반복하여 검색된 점을 처리할 수 있습니다. 예를 들어 다음 코드는 각 관심 지점의 ID를 Navigation Lab에서 렌더링하도록 시각적 디버깅 프레임워크로 푸시합니다. [Tutorial_PointOfInterest.cpp의 코드]

    ...

    Kaim::ScopedDisplayList displayList(database->GetWorld(), Kaim::DisplayList_Enable);
    displayList.InitSingleFrameLifespan("Nearby POIs", "Tutorial_PointOfInterest");
    Kaim::VisualShapeColor displayColor;
    displayColor.m_lineColor = Kaim::VisualColor::Magenta;
    displayList.PushBox(query.ComputeAABB(), displayColor);
    if (query.GetResult() == Kaim::SPATIALIZEDPOINTCOLLECTOR_DONE)
    {
        Kaim::QueryDynamicOutput* queryDynamicOutput = query.GetQueryDynamicOutput();
        if (queryDynamicOutput)
        {
            for(KyUInt32 i = 0; i < queryDynamicOutput->GetSpatializedPointCount(); ++i)
            {
                Kaim::SpatializedPoint* spatializedPoint = queryDynamicOutput->GetSpatializedPoint(i);
                if (spatializedPoint)
                {
                    const Kaim::Vec3f& position = spatializedPoint->GetPosition();
                    displayList.PushArrow(position + Kaim::Vec3f::UnitZ(), position, 0.1f, displayColor);
                    if (spatializedPoint->GetObjectType() == Kaim::SpatializedPointObjectType_PointOfInterest)
                    {
                        Kaim::StringStream displayText;
                        Kaim::PointOfInterest* pointOfInterest = (Kaim::PointOfInterest*)spatializedPoint->GetObject();
                        MyGamePointOfInterest* myGamePointOfInterest = (MyGamePointOfInterest*)pointOfInterest->GetUserData();
                        displayText << "   POI #" << myGamePointOfInterest->m_id;
                        displayList.PushText(position + Kaim::Vec3f::UnitZ(), Kaim::VisualColor::White, displayText.CStr());
                    }
                }
            }
        }
    }
}