본문 바로가기

게임프로그래밍/실습2

[실습2] 62. 일정 범위 안에 있는 액터 배열에 담기

1. 서론

 

일정 범위 안에 있는 액터의 정보가 필요할 수 있다. 오버랩을 이용하여 실시간으로 확인하는 방법도 있지만 굳이 실시간으로 알 필요없이 특정 시점에만 어떤 액터가 있는지 알아야 한다면 쿼리를 이용하면 된다.


2. 함수 선언

 

static void GetLivePlayersWithinRadius(const UObject* WorldContextObject, TArray<AActor*>& OutOverlappingActors, const TArray<AActor*>& ActorsToIgnore, float Radius, const FVector& Origin);

 

매개변수를 살펴보자.

const UObject* WorldContextObject

 

스태틱 함수이기에 필요한 월드 컨텍스트 오브젝트이다.

 

TArray<AActor*>& OutOverlappingActors, const TArray<AActor*>& ActorsToIgnore

 

범위안에 있는 액터를 담을 배열과 제외할 액터의 정보를 담은 배열이다.

 

 float Radius

 

구형 범위를 탐색할 것인데 이 구의 크기를 정하는 변수이다.

 

const FVector& Origin

 

구의 중심 위치를 담을 백터 변수이다.

 

이제 이를 구현해보자.


3. 함수 구현하기

 

FCollisionQueryParams

 

위의 구조체는 충돌 쿼리를 설정할때 사용하는 구조체이다.

 

 

함수를 살펴보면 이러한 설정들을 할 수 있는 것을 볼 수 있다.

 

FCollisionQueryParams SphereParams;
SphereParams.AddIgnoredActors(ActorsToIgnore);

 

이제 구조체를 만들고 무시할 액터 배열만 추가하였다.

 

다음으로 아래의 구조체 배열을 만든다.

TArray<FOverlapResult> Overlap;

 

해당 배열은 일반적인 트레이스에서 HitResult와 비슷한 OverlapResult 들을 담는 구조체로 여기에 오버랩된 액터들의 정보가 담긴다.

 

이제 UWorld 클래스에 존재하는 오버랩 함수를 통해 이 구조체를 채워 최종적으로 아웃오버래핑 배열을 채울 것이다.

 

그러기 위해서 월드 객체를 얻어야 할 것이다.

const UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull

 

해당 구문은 월드 객체를 얻는 것인데 두번째 매개변수는 오류가 발생시 어떻게 반응할지를 나타내는 매개변수이다.

 

OverlapMultiByObjectType

 

이제 이 함수를 호출해 채워보도록 하자. 함수의 선언을 먼저 살펴볼 것이다.

bool OverlapMultiByObjectType(TArray<struct FOverlapResult>& OutOverlaps, const FVector& Pos, const FQuat& Rot, const FCollisionObjectQueryParams& ObjectQueryParams, const FCollisionShape& CollisionShape, const FCollisionQueryParams& Params = FCollisionQueryParams::DefaultQueryParam) const;

 

매개변수에 대한 설명은 챗GPT에게 물어봐보았다.


매개변수 설명

1. TArray<FOverlapResult>& OutOverlaps

  • 설명: 겹치는 결과를 저장할 배열입니다.

2. const FVector& Pos

  • 설명: 충돌 쿼리의 중심 위치입니다.

3. const FQuat& Rot

  • 설명: 충돌 쿼리의 회전값(Quaternion)입니다.

4. const FCollisionObjectQueryParams& ObjectQueryParams

  • 설명: 검색할 객체 유형을 지정합니다.
  • 타입: FCollisionObjectQueryParams
  • 이 매개변수는 어떤 **객체 유형(Object Type)**을 검색할지 결정합니다.
    • 예: ECC_WorldStatic, ECC_Pawn, ECC_PhysicsBody 등

5. const FCollisionShape& CollisionShape

  • 설명: 충돌 테스트에 사용할 형태(Shape)입니다.

6. const FCollisionQueryParams& Params

  • 설명: 충돌 쿼리의 추가 설정을 지정합니다.
  • 타입: FCollisionQueryParams
  • 이 매개변수는 충돌 테스트의 세부 동작을 제어합니다. 기본값은 FCollisionQueryParams::DefaultQueryParam입니다.
  • 주요 설정:
    • bTraceComplex: 복잡 충돌 여부 설정.
    • AddIgnoredActor: 특정 액터를 충돌 검사에서 제외.
    • AddIgnoredComponent: 특정 컴포넌트를 제외.
    • TraceTag: 디버깅 태그 설정.

 

이제 매개변수들을 직접 설정하자.

 

World->OverlapMultiByObjectType(
    Overlap,
    Origin,
    FQuat::Identity,
    FCollisionObjectQueryParams(FCollisionObjectQueryParams::InitType::AllDynamicObjects),
    FCollisionShape::MakeSphere(Radius),
    SphereParams
);

 

이런식으로 설정이 가능하다. 이렇게 하면 Overlap 배열에 중복된 액터들의 정보가 담기고 그 정보를 가져오면 된다.

 

OutOverlappingActors.AddUnique(OverlapResult.GetActor());

 

이렇게 하면 액터의 정보를 담을 수 있게 된다.

 

전체구조는 아래와 같다.

 

void UAuraAbilitySystemLibrary::GetLivePlayersWithinRadius(const UObject* WorldContextObject,
    TArray<AActor*>& OutOverlappingActors, const TArray<AActor*>& ActorsToIgnore, float Radius, const FVector& Origin)
{
    FCollisionQueryParams SphereParams;
    SphereParams.AddIgnoredActors(ActorsToIgnore);

    TArray<FOverlapResult> Overlaps;
    if (const UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull))
    {
       World->OverlapMultiByObjectType(
          Overlaps,
          Origin,
          FQuat::Identity,
          FCollisionObjectQueryParams(FCollisionObjectQueryParams::InitType::AllDynamicObjects),
          FCollisionShape::MakeSphere(Radius),
          SphereParams
       );
       for (FOverlapResult& OverlapResult : Overlaps)
       {
          OutOverlappingActors.AddUnique(OverlapResult.GetActor());
       }
    }
}

 

이렇게 해서 일정 범위 안에 있는 액터의 정보를 담을 수 있게 되었다.