개요
이번 포스트에서는 언리얼 엔진 5를 활용해 구현한 락온 시스템(Lock-On System) 에 대해 소개합니다. 이 시스템의 목적은 화면 중심에 가장 가까운 적을 자동으로 락온하고, 카메라와 캐릭터가 타겟을 따라가도록 만드는 것입니다. 또한 락온 중에는 전환 키를 통해 우측에 위치한 다음 타겟으로 전환할 수 있고, 언제든지 락온을 해제할 수 있습니다. HUD 위젯을 활용해 시각적 피드백도 제공합니다.
✅ 시스템 목표 요약
- 화면 중심에 가까운 적을 자동 락온
- 락온 시 캐릭터와 카메라가 타겟을 따라감
- 락온 중 전환 키로 우측 타겟 순차 전환
- 락온 중 해제 가능
- UI 위젯을 통한 타겟 마커 표시
📁 주요 멤버 변수 (ADW_CharacterBase)
bool bIsLockOn = false; // 락온 여부
AActor* LockOnTarget = nullptr; // 현재 락온된 대상
TArray<AActor*> LockOnCandidates; // 전환 가능한 후보
int32 LockOnIndex = 0; // 현재 후보 인덱스
FTimerHandle LockOnRotationTimer; // 회전 보정 타이머
FTimerHandle LockOnMarkerUpdateTimer; // 마커 위치 업데이트 타이머
UUserWidget* LockOnWidgetInstance = nullptr; // 타겟 UI 인스턴스
TSubclassOf<UUserWidget> LockOnWidgetClass; // 타겟 UI 클래스
🔧 주요 함수 설명
🧭 락온 시스템 동작 흐름 요약
- 입력: 플레이어가 락온 키 입력
- 타겟 탐색: FindBestLockOnTarget() 또는 FindClosestTarget() 호출
- 타겟 설정: 유효한 대상이 있으면 bIsLockOn = true, 타겟 저장
- 회전 보정 및 UI 갱신 시작:
- UpdateLockOnRotation() → 캐릭터/카메라 회전
- UpdateLockOnMarkerPosition() → 마커 위치 표시
- 전환 입력 시 SwitchLockOnTarget() 으로 타겟 교체 가능
- 해제 입력 시 모든 상태 초기화 및 UI 숨김
🔘 ToggleLockOn()
락온 상태를 전환합니다. 위젯 표시 및 타이머도 포함됩니다.
void ADW_CharacterBase::ToggleLockOn();
- 락온이 켜져 있다면:
- bIsLockOn 해제
- 타겟 초기화
- LockOnRotationTimer, LockOnMarkerUpdateTimer 정지
- 위젯 숨김 처리
- 락온이 꺼져 있다면:
- FindBestLockOnTarget() 호출해 유효 타겟 탐색
- 위젯 인스턴스 생성 및 뷰포트에 추가
- 타이머 두 개 시작:
- UpdateLockOnRotation() (회전 보정)
- UpdateLockOnMarkerPosition() (타겟 UI 위치)
🔍 FindBestLockOnTarget()
화면 중심에 가장 가까운 적을 찾는 함수입니다.
- UGameplayStatics::GetAllActorsOfClass()로 후보 수집
- ProjectWorldLocationToScreen()으로 화면상의 위치 계산
- LineOfSightTo()로 가시성 체크
- 화면 중심에서 가장 가까운 타겟 반환
🧲 FindClosestTarget(float MaxDistance)
거리 기반으로 가장 가까운 적을 찾는 보조 함수입니다.
- FVector::Dist()로 거리 비교
- LineOfSightTo()로 가시성 확인
- MaxDistance 이내 가장 가까운 타겟 반환
🧭 UpdateLockOnRotation()
락온 타겟을 향해 캐릭터와 카메라의 회전을 보정합니다.
- FRotator::RInterpTo()로 부드러운 회전 구현
- 주기적으로 호출되며 회전 정렬
FRotator InterpRot = FMath::RInterpTo(GetControlRotation(), DesiredRotation, GetWorld()->GetDeltaSeconds(), 10.f);
GetController()->SetControlRotation(InterpRot);
🧿 UpdateLockOnMarkerPosition()
UI 위젯을 타겟 위치에 스크린 좌표로 표시합니다.
- ProjectWorldLocationToScreen() 사용
- 현재는 캡슐 콜리전의 높이 값을 기준으로 보정해 마커 위치를 계산합니다.
- 타겟의 애니메이션에 따라 위치가 정확하지 않을 수 있으므로, 향후에는 소켓(Skeletal Mesh의 특정 본 위치)을 기준으로 위치를 계산할 예정입니다.
- SetPositionInViewport()로 마커 위치 갱신
- 참고로, 현재 락온 중에도 플레이어가 마우스로 카메라를 회전할 수 있지만, 향후에는 락온 상태일 때 수동 카메라 회전을 제한할 예정입니다.
이를 위해 입력 매핑을 일시적으로 비활성화하여, 카메라가 오직 타겟을 따라가는 방향으로만 고정되도록 구현할 계획입니다.
↔️ SwitchLockOnTarget()
우측에 위치한 타겟들 중 다음 타겟으로 전환합니다.
- UpdateLockOnCandidates() 호출해 후보 갱신
- 우측 타겟 배열을 순환하여 락온 타겟 변경
🔄 UpdateLockOnCandidates()
화면 기준 오른쪽에 위치한 타겟들을 수집하고 정렬합니다.
- ScreenPos.X > ScreenCenter.X 조건으로 필터링
- DistSquared()를 이용한 거리 기반 정렬로 순서 유지
🧩 시각적 요소 - 락온 마커
- UUserWidget 기반 위젯을 활용해 타겟 표시
- ToggleLockOn()에서 생성 및 표시
- UpdateLockOnMarkerPosition()에서 위치 실시간 갱신
- 현재는 캡슐 컴포넌트 위치 기준이지만, 애니메이션 동기화를 위해 곧 소켓 위치 기반으로 개선 예정입니다.
마무리
이번에 구현한 락온 시스템은 전투 중 목표 집중도 향상과 UI 피드백을 동시에 제공하는 기능입니다. UE5에서 제공하는 ProjectWorldLocationToScreen, LineOfSightTo, FMath::RInterpTo 등 강력한 기능을 활용해 부드럽고 직관적인 락온 경험을 구성할 수 있었습니다.
앞으로는 락온 해제 조건, 전환 방향 반전 등의 확장 기능도 고려해볼 수 있습니다.
'언리얼 엔진' 카테고리의 다른 글
| Unreal Character - 캐릭터 공격 판정 트러블슈팅 정리 (0) | 2025.05.29 |
|---|---|
| Unreal Character - 캐릭터 공격 판정 시스템 구현 정리 (0) | 2025.05.29 |
| Unreal Engine - 오픈월드 개발 기술스택: World Partition과 PCG (1) | 2025.05.21 |
| Unreal UI - 범용 버튼 UI 컴포넌트 구축기 (0) | 2025.05.14 |
| Unreal UI - 범용 슬라이더 UI 만들기 (0) | 2025.05.12 |