본문 바로가기

언리얼 개발자

[Unreal] Smooth Dynamic Spline using PathFinding Points

 이전 시간까지는 비동기 길 찾기에 대해서 알아보았습니다.

https://onecoke.tistory.com/entry/Unreal-%EB%B9%84%EB%8F%99%EA%B8%B0Async-PathFinding

 

[Unreal] 비동기[Async] PathFinding

https://onecoke.tistory.com/entry/Unreal-PathFinding-Following-Component-%EA%B5%AC%ED%98%84 저번에는 길 찾기를 요청하는 부분과 길을 따라 이동을 시키는 부분들을 구현했었습니다. 이번에 구현할 것은 '길 찾기 요

onecoke.tistory.com

 

 다음 차례는 네비 길 찾기로 나온 포인트들을 이용하여 부드러운 곡선형 이동을 구현하는 것입니다.

 

[ 곡선형 이동 왜 해야 해? ]

  기본적으로 언리얼의 길 찾기 경로는 위치(Vector)들의 모임입니다. 정확히는 Nav와 관련된 데이터들도 있지만 캐릭터가 이동을 하고 도착했다고 판단하는 기준은 Vector를 이용합니다. 그리고 그 경로를 이용하여 캐릭터를 이동시켜주는 PathFollowingComponent에서는 기본적으로 다음 경로를 직선으로 향한 이동 인풋을 줍니다. 아래의 영상을 보시면 캐릭터가 방향 전환이 있을 때마다 뚝뚝 끊기는 것을 볼 수 있습니다.

 

Ground Friction: 8

 위 영상은 Default Ground Friction 값을 이용할 때의 이동 모습입니다. 마찰 저항이 적어 캐릭터가 경로를 정확하게 따르지 않고 미끄러지면서 이탈하는 모습을 볼 수 있습니다. GIF상에서는 그럴듯해보이지만 급격한 코너링에서는 끔찍한 모습들이 나옵니다. 저는 그래서 일반적인 이동에서는 Ground Friction 값을 max로 세팅하는걸 선호합니다. 아래의 영상이 그 결과입니다.

 

Ground Friction : Max

 미끄러지는 모습은 없어졌지만 캐릭터가 정말 딱딱 끊어서 가게 됩니다. 누가 봐도 이동이 직선의 형태라고 보입니다.

넷마블의 '제2의 나라' 와 같은 게임처럼 자동 이동이 부드럽게 이루어지려면 추가 작업이 필요합니다.

 

https://www.youtube.com/watch?v=VaQHLIQLlUA

* 33분 28초를 보시면 부드러운 이동에 대한 내용이 있습니다.

 

[ 곡선 이동 어떻게 구현할까? ]

 곡선 이동을 구현하려면 먼저 이동에 필요한 곡선 데이터가 필요합니다. 다행히 언리얼에서는 SplineComponent 라는 곡선 기능이 있는 컴포넌트를 제공합니다. 곡선에 대한 지식이 많이 부족한 저도 잘 사용할 수 있도록 인터페이스가 만들어져 있습니다. SplineComponent 자체를 이용하진 않겠지만 내부 기능들은 모두 끌어다 사용할 예정입니다.

 

[ 왜 SplineComponent를 그대로 이용하지 않는가? ]

 SceneComponent는 레벨에 배치되기 때문에 SceneComponent를 상속하고 있습니다. 저에게 필요한건 Transform 정도와 곡선과 관련된 데이터들 뿐입니다. 따라서 SceneComponent를 그대로 사용하는건 알맞지도 않고, Actor를 Owner로 갖는 ActorComponent의 역할과도 맞지 않다고 생각해서 사용하지 않았습니다. 다만 Path가 어떻게 생성되었는지 레벨에 시각적으로 보여주기 위해 디버깅용으로는 SplineComponent를 이용할 것입니다.

 

[ 길 찾기를 통한 곡선 데이터가 만들어지는 과정은? ]

 곡선 데이터를 만드는 과정은 크게 두 가지로 나뉩니다.

1. 언리얼 네비메시 길 찾기 수행

2. 경로 포인트들을 Spline Point 로 적용

 정말 단순합니다. 심지어 위치(Vector) 정보를 이용해서 Spline Point를 추가하는 로직은 SplineComponent 에서 모두 구현이 되어 있습니다. 저는 그 기능들을 그저 끌어다 사용하면 됩니다.

 

[ 곡선 데이터 자료형은? ]

 SplineComponent 내부에 곡선 데이터들은 FSplineCurves 구조체로 이루어져 있습니다. 이 구조체를 이용할 것입니다.

 실제로 사용한 곡선형 경로 구조체는 아래의 사진과 같습니다.

중심 위치가될 Transform, 곡선 데이터를 담당할 FSplineCurves로 이루어져 있습니다.

 

[ 곡선 데이터를 만들자 ]

 USplineComponent::AddSplinePoint() 에 포인트를 추가하는 기능이 구현이 되어 있습니다.

저는 언리얼에서 길 찾기 결과로 뱉어주는 FNavigationPath 를 가져와서 Spline에 넣어줄 것입니다.

 위의 함수는 설명을 위해 작성한 테스트 함수입니다. SplineComponent와 매칭되는 함수들은 주석에 적어두었습니다. SplineComponent를 그대로 이용하신다면 주석에 있는 함수들을 참고하시면 됩니다. 놀랍게도 위와 같이 짧은 코드로도 FSplineCurves 내부 데이터들이 기본적으로 세팅이 됩니다.

 ESplinePointType은 스플라인의 지점들마다 세팅이 가능하며 점의 곡선형태를 지정해줄 수 있습니다. 제가 적용한 ESplinePointType은 'Curve' 입니다.

 

 위의 코드에 따라 생성된 Spline은 아래와 같습니다.

 사진에 보이는 흰색 선이 길 찾기 경로 포인트들을 이용해서 만든 곡선입니다. 뭔가 그럴듯하게 만들어진 것 같지만 빨강색 원에 있는 지점들을 보이시면 경로가 코너링마다 튀어나와 있습니다. 가까이서 보면 더 절망적입니다.

 

 캐릭터가 이 경로대로 따라간다고 하면 곡선 경로는 차라리 없는게 더 나을 겁니다.

 

[ Smooth Spline ]

곡선을 '캐릭터가 이동하기에 깔끔한 모습' 으로 수정할 필요가 있습니다. 먼저 결과부터 보여드리겠습니다.

솔루션 이후 곡선의 모습

 동그라미 친 부분들 위주로 비교하면 좀 더 곡선이 부드러워진 것을 볼 수 있습니다.

 

 곡선을 부드럽게 하기 위해 적용한 방법은 현재 3가지 입니다.

1. Clamp Leave Tangent Size

2. Clamp Arrive Tangent Size

3. Merge Points

 

 스플라인 포인트의 Leave Tangent와 Arrive Tangent의 사이즈를 조절했고 너무 가까운 스플라인 포인트들에 대해서는 병합시켰습니다. Leave Tangent와 Arrive Tangent는 에디터에서 작업해보셨으면 알겠지만 포인트의 탄젠트를 조정하면 보통 둘 다 같은 값으로 세팅되며 곡선의 모양을 결정합니다. 곡선의 모습이 부드럽게 이어지지 않고 돌출되어 있다면, PreviousPoint의 Leave Tangent 혹은 NextPoint의 Arrive Tangent의 크기가 너무 큰 지 확인이 필요합니다.

 

 저는 Leave TangentArrive Tangent의 '크기'만 조정하여 부드러운 곡선을 만들어볼 것입니다. 문제는 제한할 크기를 어떻게 설정하냐인데요, 저는 점과 점 사이의 거리를 이용했습니다. 또한 점과 점 사이가 설정한 값보다 작을 경우 중간 점으로 병합했습니다. 이해하시는데 도움을 줄 지 혼돈을 줄 지 모르겠지만, 사진 첨부하겠습니다.

곡선 포인트의 순서가  1 -> 2 -> 3 라고 보았을 때,

* Point 2 Leave Tangent Size < Point 2 ~ Point 3 Distance

* Point 3 Arrive Tangent Size < Point 2 ~ Point 3 Distance

위의 공식이 모든 점에 대해 적용된다고 보시면 됩니다. ( 0번 째 점은 제외 )

* Point 2 ~ Point 3 Distance < Merge Distance ? Use Center Point ( Point 2, Point 3 )

Merge Distance는 임의로 150정도 주었는데, 이 값에 대한 규칙은 추가로 필요할 것 같습니다.

병합 규칙도 0번 째 점은 제외입니다. 시작점은 지켜주어야 합니다. 

 

코드는 아래와 같습니다.

 

[ 마치며 ]

 곡선 이동의 기반이 될 곡선 데이터를 만드는 것까지 적용했습니다. 2022.12.24 기준 Git에 올라가 있는 코드는 아직 곡선형 이동 로직은 올라가 있지 않습니다. 추후 포스팅에서 올라갈 예정입니다.

 

 부드러운 곡선을 만드는 것은 제가 한 솔루션보다도 더 훌륭한 방법들이 있을 수 있고, 실제로 현재 적용한 방법들은 테스트가 충분하지 않은 상황이라 불안정합니다. 계속해서 개선해나갈 예정입니다.

 

[ Git 주소 ]

https://github.com/skyjpower/FunctionTestProject