Unity

Locomotion System 구현(2) - 기울기에 따른 움직임

1bio 2024. 7. 4. 15:43

움직이는 오브젝트에는 어떠한 콜라이더든지 존재한다. 콜라이더가 없으면 충돌을 처리할 수 없다.

하지만 콜라이더 컴포넌트를 추가하면 계단이나 오르막길 같은 구조물에 올라갈 수 없다. 

두 개의 콜라이더가 충돌하면서 더이상 물리적인 계산이 적용되지 않기 때문이다.

 

그래서 콜라이더를 띄운 상태에서 물리적인 힘을 계산하는 것이 좋다.

따라서 위의 사진처럼 기울기가 있어도 콜라이더가 충돌을 하지 않기 때문에 자연스럽게 올라갈 수 있다.

먼저 대각선의 각도를 얻기 위해서는 수직항력이라는 것을 생각해야 한다.


수직항력이란? 

 

표면에서 물체에 수직으로 향해지는 힘이다. 이러한 힘은 중력에 의해 상쇄되면서 각도가 낮은 방향으로 벡터의 방향이 정해진다. 이것을 이용하여 기울기에 따라서 콜라이더를 띄어보자.

각도를 구하려면 두 가지의 벡터가 필요하다. 하나는 오브젝트의 Raycast를 아래로 향하는(Vector3.down) Ray 벡터와 대각선 표면의 수직항력, 즉 오브젝트가 표면과 충돌했을 때 표면한 충돌체의 수직으로 향하는 벡터를 얻는다.

 

그리고 Ray벡터에 음수를 곱해준다. Vector3.down은 (0,-1,0)을 반환한다. 따라서 음수가 곱해졌기 때문에 반대 방향의 각도가 구해질 것 이다. 따라서 아래 축 방향의 반대방향인 벡터를 얻기 위해서 음수를 곱해줘야한다.

SetSlopeAngle의 Animation Curve x축: 각도, y축: 시간

그리고 얻은 groundAngle의 값에 따라서 속도를 다르게 설정해준다. 각각의 각도에 따라 속도는 가변한다. 

0도 ~ 15도 : 1

15도 ~ 55도 : 0.75

55도 ~ 65도 : 0.5

65도 ~ 90도 : 0

경사면이 65도 보다 더 기울어져있다면 속도는 0이 된다. 따라서 갈 수 없는 지형이 된다. 

 

Float 메소드

구해준 groundAngle을 사용해서 SetSlopeSpeedModifierOnAngle 메소드에 인자로 넘겨준다. SetSlopeSpeedModifierOnAngle메소드는 Animation Curve에서 지정해준 경사면 각도에 따라서 달라지는 속도를 반환해준다.

 

만약, 오브젝트의 콜라이더와 hit.distance 충돌체의 거리를 빼줬을 때 0이 된다면 경사면에 있지 않다는 의미다. 

따라서 추가적인 힘을 가해주지 않아도 된다. 하지만 경사면에 있다면 GetPlayerVerticalVelocity 메소드를 사용해서 현재 수직 방향으로 가해지는 힘을 얻은 후 제거한다. 콜라이더의 CenterY값으로 부터 충돌체의 거리를 정확히 계산하기 위함이다. 

 

이렇게 liftForce를 얻었다면 Y축 방향으로 Rigidbody.Addforce를 활용하여 힘을 가해준다. 

 

결과 화면

이렇게 캡슐 콜라이더의 Y축을 고정해둔 상태에서 아래 방향의 사이즈만 줄일 수 있다. Box Collider는 isTrigger 처리 해놨기 때문에 물리적 충돌이 이루어지지 않는다. 따로 레이어의 처리를 하기 위해 구현된 것이다.