슈팅 게임에 맞게 애니메이션 재구성하기
기존 BlendSpace 1D 에서 BlendSpace 2D로 변경
개요
기존에 사용하던 애니메이션 구성은 슈팅게임에 적합하지 않았다. 앞으로 이동하는 애니메이션과 이동 방향으로의 캐릭터 회전을 통해 움직임을 나타냈기 때문이다. 이 구성에서는 캐릭터가 플레이어를 마주보고 폭탄을 던지는 일 마저 발생했다. 그렇기에 일반적인 TPS 슈팅게임의 애니메이션 구조로 변경하고자 한다.
개선 방향
-
캐릭터는 오로지 전방을 바라본다.
플레이어 컨트롤러가 바라보는 방향을 전방으로 삼는다. 캐릭터는 해당 방향을 바라본 상태에서 전후좌우로 움직인다.
-
움직이는 방향으로 회전하지 않는다.
뒤로 움직일 때는 뒤로 회전하는 것이 아닌, 뒷걸음질을 쳐야한다.
기본 설정 변경
캐릭터가 움직이는 방향으로 회전하는 것은 캐릭터 무브먼트 컴포넌트의 bOrientRotationToMovement 값이 true이기 때문이다. false로 변경하였다.
컨트롤러와 캐릭터가 함께 회전하기를 원한다. 따라서 컨트롤러의 회전값을 캐릭터 또한 사용하도록 폰의 bUseControllerRotationYaw 를 true로 변경하였다.
새로운 BlendSpace 2D 생성하기
기존에는 캐릭터의 이동 속도에만 의존하는 BlendSpace 1D를 사용했었다. BlendSpace 2D 사용을 위해서 Udemy 강의의 SimpleShooter 프로젝트를 참고했다. 새로운 블랜드 스페이스에서는 가로축으로 방향(Angle)을, 세로 축으로 속도(Speed)를 사용한다.
- 속도 - 캐릭터 무브먼트 컴포넌트에서 얻은 Velocity.
- 미리 얻어놓은 GroundSpeed를 그대로 활용
- 속도가 0일 때는 정지를, 값이 커질수록 빠르게 달려나간다
- 방향 → 캐릭터가 바라보는 방향을 기준으로 이동하는 벡터와의 각도
- 0도가 전방이다. 내가 바라보는 방향으로 움직인다는 의미이기 때문.
- 180, -180은 후방이다. 내가 바라보는 방향과 정 반대로 움직인다는 의미이기 때문.
참고자료에서는 해당 값을 구하는 BP를 위와 같이 구성했다. 코드로 나타내면 아래와 같다.
Velocity = CharacterMovementComponent->Velocity;
GroundSpeed = Velocity.Size2D();
FTransform CharacterTransform = Character->GetActorTransform();
FVector CharacterLocalXDirection = CharacterTransform.InverseTransformVectorNoScale(Velocity);
Angle = CharacterLocalXDirection.ToOrientationRotator().Yaw;
-
캐릭터의 Transform, Velocity를 구한다.
둘 모두 월드 좌표계에서의 정보이다. Speed는 캐릭터 평면 이동 속도의 크기를 나타낸다.
GetActorRotation().Yaw를 사용하지 않는 이유는 이 역시 월드 좌표계이기 때문이다. 내가 원하는 것은 캐릭터의 정면을 기준으로 이동 벡터의 회전값을 얻는 것이다.
-
캐릭터의 로컬 좌표계를 구한다.
캐릭터의 월드 트랜스폼은 로컬 트랜스폼에 변환 매트릭스를 곱한 결과이다. 따라서 월드 트랜스폼에 변환의 역을 곱하면 로컬 트랜스폼을 얻을 수 있다. 캐릭터의 정면 벡터를 얻을 수 있는 것.
TransformVectorized.h의 InverseTransformVectorNoScale() 메소드가 이를 담당한다.
-
캐릭터의 정면 벡터를 기준으로 움직이는 방향 벡터로의 회전 값을 구한다.
앞서 얻은 정면 벡터는 기준이 된다. Math/UnrealMath.h의 ToOrientationRotator() 메소드는 이 벡터를기준으로 하여 Rotator 값을 반환한다.
캐릭터가 바라보는 방향으로 이동하면 0을, 반대 방향으로 이동하면 -180을 반환하는 것이다.
최종 움직임
이렇게 움직임을 수정하였다. 슈팅 게임에 보다 적합해진 모습이다.
+추가) Velocity X, Y / XAxisVector, YAxisVector
캐릭터 무브먼트의 Velocity에서 X, Y 값을 얻어 블랜드 스페이스의 인자로 사용해보았다.
Velocity = CharacterMovementComponent->Velocity;
XAxisValue = Velocity.X; //(동일) XAxisValue = Velocity.Component(0);
YAxisValue = Velocity.Y; //(동일) YAxisValue = Velocity.Component(1);
이 값은 월드 좌표계에서 X, Y축 방향으로의 값을 의미한다. 캐릭터가 바라보는 방향과는 관계 없이 해당 축을 기준으로 속도 벡터의 +, -가 결정된다. X+방향으로 전진하면 앞으로 뛰지만, X- 방향으로 전진하면 뒤로 걷는 동작이 재생되는 이유이다.
XAxisVector, YAxisVecotr는 진짜로 해당 축으로의 단위 벡터이다. 각각 (1,0,0), (0,1,0)을 의미한다.
참고자료
- Unreal Engine 5 C++ Developer: Learn C++ & Make Video Games - http://udemy.com/course/unrealcourse/
- https://erikanes.tistory.com/358