-
[Unreal] 액터가 volume 안에 있는지 확인하기쾌락없는 책임 (공부)/Unreal 2024. 4. 20. 10:16반응형
개요
마을의 '영역'을 만들게 되면서 해당 영역에 Enter 하게 되면 플레이어가 해당 영역에 있다는걸 나타낼 예정입니다. 그런데 문제는 플레이어가 마을에서 스폰하게 되는 경우입니다. 이 경우에는 BeginPlay 시점에 Overlap 이벤트가 자동적으로 불리게 되지 않아 문제가 됩니다.
이를 해결하기 위해 BeginPlay 시점에 특정 액터가 안에 있음을 알게 하는 방법 2개를 알아보도록 하겠습니다.
bGenerateOverlapEventsDuringLevelStreaming
위 변수 딸깍이면 레벨이 로드되는 중에도 Overlap 이벤트를 발생시킬 수 있게 됩니다.
에디터에서 위 옵션을 체크하거나 생성자에서 true 로 설정해주면 됩니다.
void UPrimitiveComponent::BeginComponentOverlap(const FOverlapInfo& OtherOverlap, bool bDoNotifies) { // ... const bool bComponentsAlreadyTouching = (IndexOfOverlapFast(OverlappingComponents, OtherOverlap) != INDEX_NONE); if (!bComponentsAlreadyTouching) { UPrimitiveComponent* OtherComp = OtherOverlap.OverlapInfo.Component.Get(); if (CanComponentsGenerateOverlap(this, OtherComp)) { //.... // 여기서 해당 옵션이 켜져 있는지를 검사 const bool bLevelStreamingOverlap = (bDoNotifies && MyActor->bGenerateOverlapEventsDuringLevelStreaming && MyActor->IsActorBeginningPlayFromLevelStreaming()); if (bDoNotifies && ((World && World->HasBegunPlay()) || bLevelStreamingOverlap)) { // first execute component delegates if (IsValid(this)) { // 이곳에서 이벤트를 부르게 됩니다. OnComponentBeginOverlap.Broadcast(this, OtherActor, OtherComp, OtherOverlap.GetBodyIndex(), OtherOverlap.bFromSweep, OtherOverlap.OverlapInfo); }
위 변수의 사용처는 PrimitiveComponent 의 BeginComponentOverlap입니다.(End 역시 동일)
해당 옵션이 켜져 있다면 HasBegunPlay 상태가 아니라 하더라도 이벤트를 호출하게 되는것을 알 수 있습니다. 이러면 추가적인 로직 없이 변수 딸깍으로 설정할 수 있게 되는 것입니다.
AVolume::EncompassesPoint
만일 Overlap 이벤트가 너무 많은 비용을 차지할 것 같다면 해당 함수를 고려해볼 수 있습니다. 이 함수는 특정 3D 좌표의 점이 Volume 안에 있는지를 파악해주는 검사로
if(PlayerPawn != nullptr && EncompassesPoint(PlayerPawn->GetActorLocation())) { UE_LOG(LogTemp, Warning, TEXT("*** *** *** overlap player encompasses")); }
위와 같은 방식으로 사용하면 됩니다.
bool AVolume::EncompassesPoint(FVector Point, float SphereRadius/*=0.f*/, float* OutDistanceToPoint) const { if (GetBrushComponent()) { #if 1 FVector ClosestPoint; float DistanceSqr; if (GetBrushComponent()->GetSquaredDistanceToCollision(Point, DistanceSqr, ClosestPoint) == false) { if (OutDistanceToPoint) { *OutDistanceToPoint = -1.f; } return false; } #else FBoxSphereBounds Bounds = GetBrushComponent()->CalcBounds(GetBrushComponent()->GetComponentTransform()); const float DistanceSqr = Bounds.GetBox().ComputeSquaredDistanceToPoint(Point); #endif if (OutDistanceToPoint) { *OutDistanceToPoint = FMath::Sqrt(DistanceSqr); } return DistanceSqr >= 0.f && DistanceSqr <= FMath::Square(SphereRadius); } else { UE_LOG(LogVolume, Log, TEXT("AVolume::EncompassesPoint : No BrushComponent")); return false; } }
위 함수의 구현을 보면 BrushComponent를 기반으로 동작하는걸 알 수 있습니다.
- GetSquaredDistanceToCollision 에서 가장 가까운 거리를 구함
- 만일 return 이 false 라면 가장 가까운 거리가 발견되지 않은 것이라 return
- OutDistanceToPoint로 거리 계산
- 이후 검사 결과와 거리 안에 들어와 있는지를 검사
이를 통해 따로 Overlap 이벤트를 기대하지 않아도 검사가 가능하게 됩니다.
반응형'쾌락없는 책임 (공부) > Unreal' 카테고리의 다른 글
[Unreal] 에디터를 재 실행했을 시 BP 클래스가 깨지는 경우 (1) 2024.10.11 [Unreal] 언리얼 NetMode 비교시 짤막 팁 (0) 2024.03.21 [Unreal] Enum을 String 으로 변경하는 템플릿 함수 (0) 2024.01.14 [Unreal] Sound Cue 랜덤한 곡 루프 재생 (0) 2023.07.19 [Unreal] Spectator 에서 스팀 이름 가져오기 (0) 2023.07.14 - GetSquaredDistanceToCollision 에서 가장 가까운 거리를 구함