멀티플레이 개발
FMath::FixedTurn(CurrentYaw, TargetYaw, TurnSpeed * DeltaSeconds);
FixedTurn은 현재 각도에서 목표 각도까지 "이번 프레임에 최대 몇 도 돌릴지" 정해서 회전시키는 함수다. CurrentYaw 에서 TargetYaw 까지 Turn * DeltaSeconds만큼, 이번 프레임에 회전할 최대 각도다.
다른 방법으로는 Lerp도 있다.
const float NewYaw = FMath::Lerp(TurnStartYaw, TurnTargetYaw, Alpha);
Lerp는 진행률(Alpha)에 따라 바뀌는 방식이다. 그래서 Turn 액션의 진행률을 명확하게 관리하고 싶을 때 는 Lerp가 직관적이라 좋다.
하지만 그냥 Rotate만 하고 다른 Action은 하지 않는다고 하면 FixedTurn을 사용해 간단하게 표현 할 수 있다.
FMath::Abs는 절댓값이다.
FMath::Abs(-30.f); // 30
FMath::Abs(30.f); // 30
FMath::FindDeltaAngleDegrees(CurrentYaw, TargetYaw)는 두 각도 사이의 가장 짧은 각도 차이를 구해준다. 결과는 음수 일 수도 있음.
방향은 필요 없고 몇도 차이인지만 알고 싶으면 Abs 사용.
const float MovedDistance = FVector::Dist2D(GetActorLocation(), TurnStartLocation);
프로젝트를 진행하다가 Tick에서 사용하는 Alpha를 Dist2D 즉 시작 위치에서 얼마나 멀어졌는지 계산해서 Alpha값을 보정하면 직관적이고 편할 것이라 생각했다.
여기서 문제가 발생한 것은 Dist2D는 방향을 모른다. 오른쪽으로 가야 하는데 왼쪽으로 밀려도 시작점에서 멀어졌다고 계산될 수 있다.
그래서 반대 방향으로 Turn할 때, 가속도나 공중 관성 때문에 캐릭터가 잠깐 이전 방향으로 밀리면 Alpha가 이상하게 튀거나 멈추는 문제가 생겨서 이상하게 조작 됐다.
const FVector MoveDirection = GetMoveVector(FacingMoveDirection).GetSafeNormal();
const FVector FromStart = GetActorLocation() - TurnStartLocation;
const float SignedDistance = FVector::DotProduct(FromStart, MoveDirection);
이 문제를 줄이려고 DotProduct를 써서 "내가 원하는 방향으로 얼마나 갔는지"를 계산했다.
DotProduct는 어떤 벡터가 특정 방향으로 얼마나 진행했는지 보는 데 쓸 수 있다. 반대 방향이면 음수가 나온다.
하지만 공중에서 반대 방향으로 전환할 때는 실제 위치가 목표 방향으로 움직이기 전까지 Alpha가 계속 0에 머무는 문제가 있어서 결국 Turn Visual은 시간 기반으로 바꾸는 게 더 안정적이었다.
FVector Direction = MoveVector.GetSafeNormal();
GeetSafeNormal()은 벡터를 길이 1짜리 방향 벡터로 바꿔준다. 그래서 None방향이나 ZeroVector가 들어와도 터질 가능성이 줄어든다.