Tick 함수 안에서 현재 PC의 Control 회전값을 TargetRotation 으로 회전하는 코드

PlayerController->SetControlRotation(FMath::QInterpConstantTo(
    PlayerController->GetControlRotation().Quaternion(),
    TargetRotation.Quaternion(),
    GetWorld()->DeltaTimeSeconds,
    RotateSpeed
).Rotator());

 

의도 (Pitch 값을 현재에서 40 만큼 증가)

TargetRatator :  P=-51.462800 Y=-47.524287 R=0.000000
시작ControlRotator :  P=-11.462800 Y=-47.524287 R=-0.000000
회전끝ControlRotator :  P=-51.462800 Y=-47.524287 R=0.000000

 

때때로는 위의 의도처럼 잘 될 때가 있지만 문제는 Rotator -> Quat -> Rotator 로 변환하였더니 Roll이 0에서 180 으로 되는 현상이 있다.


TargetRatator  :  P=-87.518949 Y=115.043328 R=180.000000
시작ControlRotator  :  P=-52.481051 Y=-64.956672 R=0.000000
회전끝ControlRotator :  P=-87.325985 Y=114.555076 R=89.900002

Pitch값을 40 만큼 증가시키려하였는데 40도 아니고 심지어 다른 회전값도 변해버림

 

언리얼에는 PlayerCameraManager 이라는 클래스가 있는데 말 그대로 카메라의 최소 최대 Control Rotation 값을 정의한다.

여기엔 기본적으로 Pitch 와 Roll 값이 -89~89 사이로 막아져있다.

(Pitch의 90을 막은 이유는 짐벌락 현상 때문 -> Yaw 와 Roll 축이 겹침)

카메라의 Pitch값 (-89.9 ~ 89.9) 그 밖으로 나가지 못한다

 

그래서 Roll 값이 0 -> 180 으로 증가하다가 뷰 롤 최대 값 (89.9..) 에서 막아져서 위와 같은 현상이 벌어졌던 것

 

FRotator 특성 상, 0도, 180도 또는 -180도 Rotator 쿼터니언 사이의 변환에서 같은값으로 판별하기 때문에 생기는 원인

 

일반적으로 카메라에선 Roll 값을 잘 안사용하기 때문에 0을 강제로 설정해주면 위와같은 문제는 발생하진 않는다.

TargetRotation.Roll = 0.f;
    
PlayerController->SetControlRotation(FMath::QInterpConstantTo(
    PlayerController->GetControlRotation().Quaternion(),
    TargetRotation.Quaternion(),
    GetWorld()->DeltaTimeSeconds,
    RotateSpeed
).Rotator());

혹은 SpringArmComponent를 사용하고 있다면 bInheritRoll 옵션을 비활성화 할 수도 있다.

 

 

FRotator 

Pitch (y축 회전 right axis) 

Yaw (z축 회전 up axis)

Roll (x축 회전 forward axis)

 

C++ 에선 FRotator { Pitch , Yaw , Roll }

블루프린트에선 회전 축으로 Roll , Pitch , Yaw 순으로 사용

 

일반적으로 각도를 직관적으로 표현하기 위해 0~360 범위를 조절할 수 있는데 일반적으로 계산을 위해 -180 ~ 180 방식을 사용 (회전의 방향성을 단일값으로 표현 / 회전의 연속성)

 

Yaw = 270도는 FRotator에서 Yaw = -90도랑 같다.

Yaw = 360도는 FRotator에서 Yaw = 0도랑 같다.

그래서 Rotator에는

Normailzed -> -180 ~ 180 사이로 변환

Denormalized -> 0 ~ 360 사이로 변환해주는 함수가 있다.

 

0도, 180도 또는 -180도 Rotator쿼터니언 사이의 변환에서 생기는 문제도 쿼터니언을 Rotator로 변환할 때, 값이 이 범위로 매핑되기 때문

 

 

Rotator 를 비교할 때 둘 다 Nomailzed 하여서 비교

PC->GetControlRotation().GetNormalized().Pitch == TargetRotator.GetNormalized().Pitch

 

 

TargetRotator = PC->GetControlRotation() + AdditionalRotator;

// BasePos * AddRotate
TargetQuat = PC->GetControlRotation().Quaternion()* AdditionalQuat;

 

'언리얼 > 언리얼 기능' 카테고리의 다른 글

쿼터니언 정규화  (0) 2024.11.14
채널 프리셋  (1) 2024.09.23
언리얼 보간 (Interpolation)  (1) 2023.10.19
UStruct static_cast  (0) 2023.09.04
Delegate 관리  (0) 2023.07.23

+ Recent posts