에임 오프셋
내 프로젝트에서는 카메라와 캐릭터 시선이 항상 같지 않다. 캐릭터는 이동, 카메라는 자유 시점.
이때 "카메라가 보는 방향으로 상체만 조준"이 돼야 활/지팡이 원거리 조준감이 산다. 그래서 컨트롤 로테이션과 엑터 로테이션의 차이를 애니메이션으로 반영하는 "Aim Offset"이 필요하다.
구현에 필요한 핵심 개념
- ControlRotation : 플레이어 입력/ 카메라 기준의 회전(컨트롤러가 본 방향)
- ActorRotation : 실제 캐릭터 메시에 적용된 월드 회전
- NormalizeDeltaRotator(A,B) : A-B의 차이를 (-180, 180)범위로 정규화한 회전 -> 카메라-캐릭터의 각도 차를 얻기 위함
- FInterTo : 프레임마다 부드럽게 타겟으로 수렴(뚝뚝 끊키는거 방지)
구현부
void UPC_AimComponent::CalcAimOffset(float DeltaTime)
{
check(OwnerCharacter.Get());
FRotator ControlRotation = OwnerCharacter->GetControlRotation();
FRotator ActorRotation = OwnerCharacter->GetActorRotation();
FRotator NormalizedDeltaRotation = UKismetMathLibrary::NormalizedDeltaRotator(ControlRotation, ActorRotation);
float NewPitch = FMath::FInterpTo(AimOffsetRotation.Pitch, NormalizedDeltaRotation.Pitch, DeltaTime, 30.f);
float NewYaw = FMath::FInterpTo(AimOffsetRotation.Yaw, NormalizedDeltaRotation.Yaw, DeltaTime, 30.f);
AimOffsetRotation = FRotator(NewPitch, NewYaw, 0.f);
}
- NormalizedDeltaRoator 쓰는 이유: 350도와 10도의 차이는 340이 아니라 -20여야 상식적인 회전으로 간다. 이 함수가 그걸 보장
애니메이션 연동
- Layered Blend per Bone : UpperBody부터 조준 애니 적용, 하체는 이동 애님 유지
- AimOffset Asset : Pitch/Yaw파라미터로 조준 포즈 보간
가드 -> 스페셜 통합(무기별 행동 스위치)
- 소드 : SpecialAction => Guard
- 스태프 : SpecialAction => Aim
조준 카메라 전환 (CameraType 데이터화)
- CameraType(Enum) : Normal, Aim
- CameraData(DataAsset) : TargetArmLength, SocketOffset, Fov, Rot
- 상태 전환 시 카메라 파라미터를 RInterep/Lerp로 자연스럽게 스위칭
const FVector TargetOffset = FPC_GameUtil::GetCameraData(CurrentCameraType)->SocketOffset;
const FRotator TargetArmRotation = FPC_GameUtil::GetCameraData(CurrentCameraType)->CameraRot;
const float TargetArmLength = FPC_GameUtil::GetCameraData(CurrentCameraType)->TargetArmLength;
const float TargetFOV = FPC_GameUtil::GetCameraData(CurrentCameraType)->CameraFov;
// 보간 처리
const FVector NewOffset = FMath::VInterpTo(SpringArmComponent->SocketOffset, TargetOffset, DeltaTime, 30.f);
const FRotator NewRot = FMath::RInterpTo(CameraComponent->GetRelativeRotation(), TargetArmRotation, DeltaTime, 30.f);
const float NewLen = FMath::FInterpTo(SpringArmComponent->TargetArmLength, TargetArmLength, DeltaTime, 30.f);
const float NewFOV = FMath::FInterpTo(CameraComponent->FieldOfView, TargetFOV, DeltaTime, 30.f);
애임오프셋 구현 결과
원거리 공격 설계
- 콜리전 2중 구조
1) 대상 상호작용 콜리전 = 큼 : 투사체가 타겟을 살짝 빗나가도 맞게 허용
2) 환경 상호작용 콜리전 = 작음 : 벽 모서리/틈 사이에서 불필요한 충돌 방지, 매끄럽게 통과
- ProjectileMovementComponent : 속도, 중력 스케일, 바운스, 호밍 등 투사체를 쉽게 데이터로 제어 가능
- SkillObject 클래스 추가 : BeginOverlap,EndOverlap, DespanSound 등등 기본적인 구현
- 스폰 위치
FVector Location = SkeletalMeshComponent->GetSocketLocation(TEXT("hand_l"));
FRotator Rotation = PlayerController->GetControlRotation();
원거리 공격 구현 결과
이번에 막힌 지점
- 문제 : 카메라를 350도 -> 10도로 넘길 때 상체가 반대쪽으로 빙빙돔 => NormalizedDeltaRotator 로 정규화처리
- 벽 모서리에 투사체가 자꾸 걸림 => 환경 충돌 콜리전을 작게, 대상용은 크게 분리. 각각 콜리전 채널 다르게 처리
'Unreal > 포트폴리오 제작' 카테고리의 다른 글
[Unreal Portfolio] 10화 - 정확한 타격 판정을 위한 어택 트레이스 시스템 (0) | 2025.10.03 |
---|---|
[Unreal Portfolio] 9화 - 가드 Guard / 구르기 Roll 액션 (0) | 2025.10.02 |
[Unreal Portfolio] 8화 - 무기 다양화 / 무기 스왑 (0) | 2025.10.01 |
[Unreal Portfolio] 7화 - 벡터 내적으로 캐릭터 방향 제어 & 락온 시스템 구현 (0) | 2025.09.30 |
[Unreal Portfolio] 4화 – 보스의 스킬 구현, 하늘에서 쏟아지는 파이어볼 (1) | 2025.09.27 |