[UE5] Climb 강의 문제해결

2024. 2. 26. 23:26강의/UE5 Climbing System

 

 

Ledge

 

Ledg를 판별할 때 빗면이 있을 경우 부자연스러운 상황이 발생

 

- Ledge를 판별할 때 빗면이 있을 경우 부자연스럽게 Climbing 상태가 종료되는 상황이 있었습니다.

- Normal과 Up Vector 의 각도가 캐릭터가 걸을 수 있는 각도 이하일때만 Climb 상태에서 Walk 상태로 변환하게 처리했습니다. (이 각도는 직접 실험을 통해 측정: 40도)

 

 

 

Ceiling

 

 

 

- 위와 같이 벽과 천장 사이를 이동할 때 머리가 반대방향으로 이동하는 문제가 있었습니다.

- 이 부분이 부자연스럽게 보였기에 문제점이 무엇인지 찾아보았습니다.

- 이유는 바로 MakeFromX 때문이었습니다.

 

FRotationMatrix::MakeFromX(-CurrentClimbableSurfaceNormal)

 

- 강의에서는 Normal 을 MakeFromX에 넣어 RotationMatrix를 만들었습니다.

- MakeFromX의 구현은 다음과 같습니다.

 

template<typename T>
TMatrix<T> TRotationMatrix<T>::MakeFromX(TVector<T> const& XAxis)
{
	TVector<T> const NewX = XAxis.GetSafeNormal();

	// try to use up if possible
	TVector<T> const UpVector = (FMath::Abs(NewX.Z) < (1.f - UE_KINDA_SMALL_NUMBER)) ? TVector<T>(0, 0, 1.f) : TVector<T>(1.f, 0, 0);

	const TVector<T> NewY = (UpVector ^ NewX).GetSafeNormal();
	const TVector<T> NewZ = NewX ^ NewY;

	return TMatrix<T>(NewX, NewY, NewZ, TVector<T>::ZeroVector);
}

 

- UpVector가 고정되어 있는 것을 확인할 수 있습니다.

    FVector UpVector = (FMath::Abs(-CurrentClimbableSurfaceNormal.Z) < (1.f - UE_KINDA_SMALL_NUMBER)) ? FVector(0, 0, 1.f) : FVector(1.f, 0, 0);
    const float Angle = FMath::RadiansToDegrees(FMath::Acos(FVector::DotProduct(FVector::UpVector, -CurrentClimbableSurfaceNormal)));
    if(Angle < 20.0f)
    {
        UpVector = UpdatedComponent->GetUpVector();
    }
    FMatrix RotationMatrix = FRotationMatrix::MakeFromXZ(-CurrentClimbableSurfaceNormal, UpVector);

 

- 그래서, 저는 위처럼 내적으로 천장인지 판별한 후,

- 천장이면 캐릭터의 UpVector를 가져와 MakeFromXZ 함수에 넣었습니다.

(만약, UpVector를 항상 캐릭터의 Up방향으로 설정하면, 벽-> 천장-> 반대쪽 벽 으로 이동할 때 머리가 아래부분으로 향하게 되어, 천장일때만 적용하였습니다.)

 

- 결과는 위와 같습니다.