몇일간 소스코드를 보면서 발악을 해보았지만 캐릭터 무브먼트를

필자의 입맛대로 구성해서 사용하도록 코드를 짠다는게 쉽지 않은일 이었습니다.


CharacterMovement클래스를 지겨울정도로 봤던거 같지만 아직도 전체를 다 이해하지는 못했습니다. 오히려 필요한 부분도 40%정도만 이해를 했기때문에 사용자 캐릭터는 다시 구성을 하겠지만 지금까지 들인 시간이 아까워서 이해한 부분에 대해서 정리해 두려고 합니다.


<급격한 분노를 참지 못해버린 필자>


잡담으로도 매우 대충 적어 두었지만 일단 언리얼에서 제공하는 CharacterMovement에서는 이동을 ENUM형으로 관리하고있습니다. 현재 캐릭터가 떨어지고있는지 수영하는지 걸어다닐수 있는 지형위에서 걷고 있는지 등을 확인해서말이지요.


그래서 기본적으로 현재 이동상태를 설정해주는 MovementMode라는 변수가 있고 이 변수의 변화에 관여하는 함수가 두어개 있습니다. 찾아가며 보기는 했는데 실제로 적용하는 코드는 제대로 못찾았습니다 넓으신 마음으로 읽는분들이 이해해 주시길 바랍니다.


코드가 만줄이 넘어가는 바람에 찾아서 읽고 다시 찾고 하는데 시간이 너무 오래걸렸습니다. 모든 분들이 그럴지는 모르겠지만 타인이 작성한 코드를 죽어라 읽고 있으면 진도는 안나가고 읽는것도 어렵고 이해하기도 어려워서 금방 지치게 됩니다. 사족이 길었네요 그냥 이렇다는 변명이 있는걸로만 알아주시면 됩니다.


지형 이동간에 버벅이는 구간을 해결하기 위해서 필요한 부분만을 짐작하여 집중적으로 보았고 필자가 확인한 바로는 약 9개의 함수와 2개의 구조체, 이동상태를 저장하는 변수, 현재 밟고있는 바닥오브젝트 에 대한 정보가 필요합니다.


가장 먼저 살펴볼 함수는 SimulateMovement입니다.

이동에 관해서 실질적으로 시작하는 함수라고 볼수 있으며 이 안에서 중력적용이라던가 현재 밟고 있는 혹은 이제 밟게될 이동가능한 지형에 대한 판단을 하게되는 부분입니다.


우선은 시작과 동시에 MoveSmooth함수를 통해서 이동을 먼저 확인해 봅니다.

함수에 진입하면 몇가지 다른 내용들이 있는데 가장 중요한건 현재 캐릭터가 지형위에서 움직이고 있는지를 먼저 IsMovingOnGround함수를 통해서 확인하고 지형위에서 움직이고 있다면 MoveAlongFloor함수로 넘어갑니다. 아닐경우 언리얼 소스코드에서는 날고있는지를 판단하기도 하지만 저는 날게할 생각이 없기 때문에 넘어갔습니다.


MoveAlongFloor함수에 들어가자마자 CurrentFloor가 걸어다닐수 있는 바닥인지 확인하고 아닐경우 바로 리턴을 해버립니다. 아닐경우 현재 캐릭터가 지형에서 걸어다니고 있는것인데 이경우 높낮이로 인하여 생기는 문제를 해결하기위해서 ComputeGroundMovementDelta함수를 이용합니다.


<필자가 계속해서 말하고있는 높낮이에 따른 문제점>

<발바닥에 끈끈이라도 붙었는지 언덕만가면 극심히 느려진다>


ComputeGroundMovementDelta함수에서는 충돌한 위치의 노말값과 지형의 해당 위치 노말값을 이용해서 부딪히지 않고서 지나갈수 있는 방향으로 이동값을 계산해줍니다. 이후에 반환받은 이동값을 통해 SafeMoveUpdatedComponent함수로 또 다시한번 검사를 통한 이동을 합니다.


이번 검사에서 다시 충돌이 일어나거나 충돌을 검사하는 시작지점이 오브젝트를 뚫었는지 확인하여 미끄러지게 하거나 오를수 있는 높이의 계단인지 등을 확인하여 동작합니다. 


필자가 이해한 바로는 bStartPenetrating 상태가 true면 앞에있는 물체가 거대하여 밟고 올라갈수 없기때문에 미끄러지게 하고 그것이 아니라 IsValidBlockingHit 상태가 true일 경우 부딪히기는 하였으나 물체가 몸을 가로막을정도로 큰것이 아니기에 밟고 지나갈수 있는지를 확인하는데 이때 사용하는 함수가 StepUp함수입니다.


StepUp함수에서는 이름과는 다르게 현재 캐릭터의 진행방향으로 가로막는 물체를 밟고 올라가는지와 그게 아니라면 전진, 하강 할수 있는지에 대해서 전부 확인해봅니다. 결과로 false가 나올시에는 미끄러지는게 다입니다.


여기까지 오면 MoveSmooth함수에서 나오게 됩니다. 함수를 통해서 이동을 기본적으로 처리했으며 다음으로는 캐릭터가 지형을 탈출해서 떨어지는지에 대해서 체크를 하게됩니다. 지금까지의 과정중 StepUp함수에서 FindFloor라는 함수를 이용하게 되는데 이 함수는 진행방향에 이동가능한 바닥이 있는지 찾아내주는 함수입니다. 그 결과가 FStepDownResult 변수에 들어오고 이를 통해서 확인하게 됩니다.


FStepDownResult에서 bComputedFloor가 true면 찾아낸 바닥으로 CurrentFloor를 변경합니다.

만약 떨어지고 있는 중이라면 아까 언급한 FindFloor를 한번더 실행하고 둘다 아니라면 CurrentFloor의 정보를 Clear시킵니다.


이제 현재 밟고 있는 CurrentFloor에 대한 정보가 변경이 되었고 이 바뀐 CurrentFloor가 걸어다닐수 없으면 현재 캐릭터의 이동상태를 Falling으로 바꿉니다. 만일 CurrentFloor가 걸어다닐수 있는 바닥이며 캐릭터의 이동상태가 Falling이면 바닥에 착지하게 해줍니다.


<분노를 강력히 표출하고 있는 필자>


좀더 정리를 하면서 코드를 읽으니까 느끼게 된것이지만 아직도 정확히 파악하고 있지 못하고있다는 사실을 알게되었습니다. 만줄씩이나 되는 코드에서 필요한 부분을 추적하며 공부하는건 참 쉽지 않은 일이었습니다. 그래도 들인 노력이 아까우니까 이해한 한도내에서 간략화 해서 약간 야매스럽게 코드를 구현해 보려고 합니다.

누가 그러지 않습니까? 일단 굴러가면 되는거라고 필자도 강력히 동의하는 바입니다. 최적화는 이미 죽인지 오래전이거든요


다음 포스팅때는 간략화 시킨 버전을 테스트하고 결과를 들고서 오겠습니다. 읽는 모든 여러분 필자와 같은 삽질은 피하시고 속편하게 Character클래스를 상속받아서 구현하시기 바랍니다.

Posted by 별수집가
,