Catmull-Rom Spline이란?
Catmull-Rom Spline은 보간 스플라인의 한 종류로, 최소 4개의 Control Point를 정의하면 Alpha 값을 통해 P1과 P2 사이의 벡터 값을 얻을 수 있다. Catmull-Rom Spline의 가장 큰 특징은 제어점을 무조건 지난다는 것이다. 그렇기에 제어점을 지나지 않는 Bezier Curve와 B-Spline 대신 Catmull-Rom Spline을 선택하게 되었다.
적용
추후 Spline의 활용을 염두에 두고 Leap 클래스와 분리하였다. Spline 클래스에는 제어점을 가지는 Points 변수와 Vector 값을 계산하는 Compute 함수만을 두어, Spline 알고리즘에만 집중하였다.
Leap 클래스에서는 제어점을 설정하고, 제어점을 바탕으로 캐릭터의 위치를 설정한다. 여기서 주의할 점은 크게 6가지였다.
1. 보스와 플레이어의 키 차이, 땅의 높이 차이, 점프
- 보스가 플레이어에게 도약할 때 서로 높이가 다를 수 있고, 점프로 인해 공중에서 도약이 끝날 수 있다.
- 보스는 root 본의 위치 값을 사용하고, 플레이어는 플레이어의 아래에 있는 땅의 위치 값을 사용해서 계산하였다.
- 실제로 위치를 변경할 때는 초기화 때 계산해둔 root와 실제 위치의 delta 값을 Z에 더한 위치로 이동하였다.
- 그러나 공격할 때 팔의 Z 값은 고려하지 못했다. 절차적 애니메이션 등의 방법으로 보강할 필요가 있다.
2. 플레이어의 이동
- 플레이어는 움직일 수 있기에 매 프레임 제어점을 갱신해야 한다.
- 0번, 1번 제어점은 보스의 시작점에 해당하기에 매 프레임 갱신할 필요가 없다.
- 도약 중 모든 프레임마다 갱신하면 플레이어가 이를 피할 수가 없기에, 내려오는 중에는 갱신하지 않도록 했다.
3. 2번 제어점 설정
- 2번 제어점은 도약 시 최대 높이일 때의 위치이다.
- 시작 위치와 플레이어의 위치 값을 선형 보간해서 그 값을 구할 수 있다.
- 선형 보간의 Alpha 값은 미리 받아둔 MaxHeightRatio를 사용한다.
- 선형 보간으로 얻은 값의 Z에 미리 받아둔 MaxHeight를 더하여 실제 위치를 구할 수 있었다.
4. 도약 중 지형과 충돌
- 지형과 충돌하면 도약을 즉시 멈추어야 한다.
- SetActorLocation의 Sweep을 true로 세팅하고, 반환 값이 false일 경우 도약을 멈추게 하여 해결할 수 있었다.
5. 보스 캐릭터와 무기 간의 거리
- 4번 제어점, 즉 실제로 이동할 위치는 플레이어의 위치에서 무기 거리만큼의 간격을 두어야 한다.
- 플레이어 위치에서 보스의 시작 위치를 뺀 값을 정규화하여 단위 벡터를 구하고, 여기에 공격 사거리를 곱한 값을 4번 제어점으로 설정하였다.
- Z 값은 같아야 하기에, 단위 벡터를 구하기 전에 Z 값을 0으로 설정하였다.
- 5번 제어점이 있는 땅의 위치와 4번 제어점이 있는 땅의 위치가 다를 수 있음을 고려하지 못했다. 값을 구한 뒤, 땅으로 Trace 하여 충돌 위치를 4번 제어점으로 할 필요가 있다.
6. 도약 지속 시간과 도약 이동 거리의 동기화
- 매 프레임마다 Alpha 값을 갱신하여 위치를 구해와야 하는데, 단순히 Alpha에 DeltaTime을 더하면 지속 시간과 이동 거리가 맞지 않는다.
- DeltaTime에 도약 지속 시간을 나눈 값을 Alpha에 더하면 지속 시간과 이동 거리의 동기화가 가능하다.
- 단, 도약을 하는 시간과 하강을 하는 시간은 다르기에, 도약 중일 경우 도약 비율, 하강 중일 경우 (1 - 도약 비율)을 도약 지속 시간과 곱해서 지속 시간과 이동 거리, 애니메이션을 동기화할 수 있었다.
- 추후 애니메이션에 섹션을 두어 데이터의 변경만으로 Leap 클래스가 애니메이션을 제어할 수 있게끔 할 것이다.
'Memorize: RECALL' 카테고리의 다른 글
자연스러운 무기 교체 (2) (0) | 2020.09.22 |
---|---|
자연스러운 무기 교체 (1) (0) | 2020.09.22 |
UObject에서 Replication 지원하기 (0) | 2020.09.21 |
Weapon 초기화를 위한 새로운 설계 (0) | 2020.06.12 |
Runtime에 생성된 Anim Instance의 BeginPlay (0) | 2020.06.12 |