나만의 작은 도서관
[TIL][C++] 251028 MMO 서버 개발 124일차: [언리얼] ProjectWorldToScreen() 함수 예제, 위젯 컴포넌트를 사용한 경우와 비교했을때 차이점은 무엇일까? 본문
Today I Learn
[TIL][C++] 251028 MMO 서버 개발 124일차: [언리얼] ProjectWorldToScreen() 함수 예제, 위젯 컴포넌트를 사용한 경우와 비교했을때 차이점은 무엇일까?
pledge24 2025. 10. 29. 04:14주의사항: 해당 글은 일기와 같은 기록용으로, 다듬지 않은 날것 그대로인 글입니다.
[언리얼] ProjectWorldToScreen() 함수 예제
- ProjectWorldToScreen은 3D 월드 좌표를 유저가 보는 스크린(뷰포트) 좌표로 변환할 때 사용하는 함수이다.
- APlayerController에 정의되어 있기 때문에 APlayerController를 끌고 와야 사용할 수 있으며, ProjectWorldToScreen() 함수의 소스 코드는 아래와 같이 되어있다.
bool APlayerController::ProjectWorldLocationToScreen(FVector WorldLocation, FVector2D& ScreenLocation, bool bPlayerViewportRelative) const
{
return UGameplayStatics::ProjectWorldToScreen(this, WorldLocation, ScreenLocation, bPlayerViewportRelative);
}
- 단순히 UGameplayStatics의 함수를 호출하는 형태이며, 넘겨받은 매개변수 + 자신이 가지고 있는 데이터로 인자를 넘겨주고 있는 걸 알 수 있다.
- 추가적으로 설명하자면 ProjectWorldLocationToScreen() 함수는 인자로 넣어준 ScreenLocation에 결과가 저장되고, 리턴값인 bool은 “스크린 상에 표시되는가?”를 의미한다.
사용처 및 사용 예제
- 월드 공간의 특정 지점 위에 HUD 요소를 표시하기 위해 사용한다. 주로 표시하는 HUD 요소는 이름표나 체력 바 등이 있다. 아래 예제는 월드에 배치된 액터의 월드 좌표를 스크린 좌표로 변환하는 예제이다.
#include "Kismet/GameplayStatics.h"
// AMyHUD는
void AMyHUD::DrawWidgetOnActor(AActor* TargetActor)
{
APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
if(PlayerController && TargetActor
{
// Actor의 월드 좌표 추출
FVector WorldPos = TargetActor->GetActorLocation();
FVector2D ScreenPos;
// ProjectWorldLocationToScreen() 함수 실행
if(bool bOnScreen = PlayerController->ProjectWorldLocationToScreen(WorldPos, ScreenPos, true))
{
// 스크린 상에 위치
}
else
{
// 스크린 상에 위치 X
}
}
}
위젯 컴포넌트를 사용한 경우와 비교했을 때 차이점은 무엇일까?
- 액터에 위젯 컴포넌트를 부착하는 방식으로 액터의 HP바나 이름바를 표시할 수 있다. 이 방식을 사용하면 ProjectWorldLocationToScreen() 함수를 사용하는 경우와 차이점은 무엇일까?
- 위젯 컴포넌트의 경우 Space 설정을 할 수 있다. Space 설정은 위젯이 표시될 공간을 설정하는 것으로, World와 Screen이 있다. 각각을 적용했을 때 효과는 아래와 같다.
Space::World로 적용할 경우
- 위젯이 월드 공간에 배치된다.
- BP에서 설정한 Transform 위치가 3D 월드 좌표에 그대로 적용되기 때문에 아래와 같은 특징을 가진다.
- 벽이나 다른 지형지물 뒤로 이동하면 가려진다.
- 액터가 카메라에서 멀어지면 작아지고, 가까워지는 커지는, 즉, 원근감이 위젯에 적용된다.
- 액터의 회전이 위젯에 적용되며, 플레이어가 위젯을 바라보면 회전된 상태의 위젯을 보게 된다. (위젯 컴포넌트의 위젯의 뒷면은 투명해서 위젯 뒤에 있으면 위젯이 보이지 않는다.)
Space::Screen으로 적용할 경우
- 위젯이 Screen 공간에 배치된다.(즉, HUD 공간)
- BP에서 설정한 Transform에서 Location만 사용되어 스크린에 투영되기 때문에 아래와 같은 특지를 가진다.
- HUD 공간에 있으므로 월드에 존재하는 오브젝트에 의해 가려지지 않는다.
- 액터와 카메라와의 거리와 관계없이 위젯은 고정된 크기를 가진다.
- 액터의 회전이 위젯에 적용되지 않는다.
Space 설정 비교 정리
| 배치된 공간 | 지형 지물에 가려지는가? | 카메라와의 거리가 크기에 영향을 주는가? | 회전값이 존재하는가? | |
| Space::World | 3D 월드 좌표 | O | 거리에 따라 크기 변동 | O |
| Space::Screen | 2D 스크린(HUD) | X | 항상 고정된 크기 | X |
그래서 차이점은?
- Space를 World로 설정하는 경우는 크게 다른 걸 알 수 있으니 제외하고, Space::Screen과 ProjectWorldLocationToScreen() 함수를 사용하는 경우를 비교하자면, 표시되는 결과는 같은 것 같다. 다만, 각 몬스터마다 위젯 컴포넌트를 추가하는 방식은 Draw Cost가 높다고 한다. 그래서 최적화를 위해 위젯 컴포넌트를 부착하는 방식보다 따로 관리하는 것을 선호한다고 한다.
- 최적화에 대해서 좀 말하자면, 따로 매니저를 두고 Hp바나 이름 바를 관리한다면, 오브젝트 풀링을 활용하기 편하고, 한 번에 관리하기도 쉬워진다.
