스파르타 내일배움캠프/Today I Learned

Today I Learned - Day 31 [움직이는 플랫폼과 유닛의 동시이동]

불면증 도사 2024. 10. 28. 22:41

금일은 '어떤 물체과 같이 이동시키는 방법'에 대해서 정리해 볼까 한다.

 

이런 요소에 대해서 알아보기에 앞서, '왜 이런 방법이 따로 필요한가'에 대해서 설명하자면, 기본적으로 모든 객체는 독립적인 구성이라서 그렇다. 이에 대해서 알기가 힘들 수도 있다. 그래도 일단 중요한 건 '독립적이라서'인 것이다.

독립적으로 구성되기 때문에 한 쪽에 힘이 가해져도 닿아있는 물체에는 영향이 하나도 없다. 마찰력을 넣을 수는 있겠지만, 그것으로 조절하는 것에도 한계가 있을 뿐 아니라, 조절을 잘못하면 어색하기 짝이 없는 무언가가 만들어진다.

[물론, 실제로는 이동할 때 따라가게 하는 것은 마찰력이 맞다.]

그렇기 때문에 '닿아있는 물체의 이동에 따라가는 로직'이 따로 필요하게 되는 것이다.

 

그렇다면, 이제 세부 로직으로 알아보자.

 


이동 주체를 알아보기 이전에, 이동 방식에 대해서 먼저 생각 해 보자.

 

선택할 수 있는 선택지는 아래와 같다.

A. 닿은 대상의 위치를 자신과 동일한 위치 변화량으로 변화시킨다.

B. 닿은 대상에게 자신과 같은 속력을 부여한다.

C. 탑승자를 가둬서 강제로 함께 이동시킨다.

[취소선 처리 되어있으나, 의외로 써봄직 한 방법이다. 특히 플랫폼의 속도감을 살리고자 하는 경우에는 나름 괜찮은 방법. 물론, 어디까지나 편법이고, 실질적인 해결 방법은 아니니까 지금은 넘어가자.]

 

A. 닿은 대상의 위치를 자신과 동일한 위치 변화량으로 변화시킨다.

플랫폼의 이동을 transform.position 변화로 구성할 경우 편하게 구성되지만, Rigidbody를 이용할 때에서 사용 자체는 가능하나, 위치 변화량을 계산해서 적용해야 하는 등의 추가 조치가 필요해도 적용 가능하다.

전체적으로 안정적으로 이동이 가능하지만, 속도가 더해지는 것은 아닌 지라, 이를 이용한 발사대 같은 심화 동작은 힘들다. 그래도 별다른 조치 없이도 플랫폼 위에서 이동이 가능하기 때문에 편하게 구성되기는 한다.

다만, 플랫폼의 이동이 transform.position 변화로 구성되어 있다면, 후술할 3번 항목으로 인해서 사용하기는 다소 아쉬운 방법이긴 하다.

 

B. 닿은 대상에게 자신과 같은 속도를 부여한다.

특수 목적이 있거나 가속도가 있는 게임에서 쓰기 좋은 방법. 이동 속도의 잔여량을 이용한 발사 시스템을 구성할 수 있어서 이런 류의 시스템이 필요하면 유용하게 사용할 수 있다.

다만, 플랫폼이 복잡한 궤적을 그리는 경우에는 난처해 지는 데다가, 플레이어가 플랫폼 위에서 이동도 해야하는데 속도를 고정하던 추가하던 복잡한 추가 작업이 필요하기 때문에 일반적인 상황에서 사용하기에는 다소 난감한 편이다.


그럼 이번에는 이동시키는 주체를 무엇으로 두느냐를 통해서 알아보자.

필자가 알아본 것은 아래 3가지가 있다.

[알고리즘 적인 요소라서 아마 이것 보다 더 많이 존재하긴 할 것이다.]

1. 플랫폼(= 이동 주체)이 탑승자에게 변화를 주는 것.

2. 탑승자(= 피 이동 객체)가 닿은 대상화 함께 이동하는 것.

3. 탑승자를 플랫폼의 하위 객체로 넣는 것.

 

1. 플랫폼(= 이동 주체)이 탑승자에게 변화를 주는 것.

플랫폼이 이동하는 주체라서 이쪽이 정석이라고 생각하기 쉽다. 실제로도 본인도 플랫폼 주체로 이동하게끔 구성하려고 했었다가 다른 방법을 찾아보면서 그만 뒀던 것이다. [시스템 부하가 조금 높을 것 같았다.]

 

이렇게 구성했을 경우의 장점은 '이동에 특성을 주기가 쉽다'는 것. 주체가 플랫폼이기 때문에, 캐릭터에게 변화를 줄 때 약간 특징을 준 상태로 변화를 주기만 하면 되기 때문에 다른 방식에 비해서 편하다.

대신 상술했듯, '다량의 객체가 올라 서 있는 경우'에 대한 판정의 시스템 부하가 어떨지는 한번 고민을 해 봐야할 것이다.

 

2. 탑승자(= 피 이동 객체)가 닿은 대상과 함께 이동하는 것.

상당히 복잡한 방법. 글로만 봐도 알겠지만, '자신이 닿은 게 플랫폼인지 판별한 뒤, 해당 플랫폼의 이동을 인식하여 자신의 이동에 적용해야 한다'라는 글로만 봐도 복잡한 절차를 거쳐야 하기 때문에 구성하려면 다소 머리가 아플 수도 있다.

 

대신, '복수 플랫폼에 닿아있을 경우의 판정'을 다룰 수가 있다는 강점이 존재한다.

다른 방식은 주체가 플랫폼이기 때문에 탑승자가 복수 닿아있는 지 판정하려면 어마어마하게 복잡해지고 구조 상으로도 좋지 못한데, 탑승자가 이동하도록 구성한다면 그냥 탑승자에게 2개가 닿아있는 지를 판정하거나, 특정한 기준점을 잡아버리면 되기 때문에 이런 문제를 다루기가 상대적으로 편한 편이다.

 

3. 탑승자를 플랫폼의 하위 객체로 넣는 것.

그냥 충돌 시작에 탑승자를 플랫폼의 하위 객체로 넣었다가, 충돌에서 벗어나면 최상위 객체로 다시 빼면 되는 아주 간단한 방법. 전체적으로 시스템 부하도 적고, 플랫폼의 이동이 복잡하던 아니던 하위 객체라서 그냥 따라가기 때문에 후술할 '특정 문제' 을 고려하지 않아도 되는 상황이라면 적극적으로 활용해도 좋다.

 

다만, 치명적인 문제가 존재하는데, 플랫폼 이동을 반드시 transform.position 변화로 구현해야 한다는 것.

탑승자를 하위 객체로 보낸다고 해도 탑승자와 플랫폼의 Rigidbody가 별개라서 플랫폼 이동이 Rigidbody를 사용한다면 탑승자가 따라가지를 못한다.

 

더군다나  여러 플랫폼에 동시에 닿아 있는 경우에는 오류가 나기 쉽다는 문제도 있다. 아래 흐름을 보자.

  1. 탑승자가 플랫폼 1에 닿아서 플랫폼 1의 하위 객체가 된다.
  2. 플랫폼 1에 닿은 상태에서 플랫폼 2에 닿아서 플랫폼 2의 하위 객체가 된다.
  3. 플랫폼 1에서 떨어져서 탑승자가 최상위 객체가 된다.
  4. 플랫폼 2에 닿아있음에도 탑승자는 최상위 객체라서 플랫폼을 따라가지 않게 된다.

이러한 문제가 발생할 수 있기 때문에 '동시에 닿을 수 있는 환경'이라면 방어 코드를 추가해 줘야한다. 특히, '동시에 닿았다가 돌아가는 경우'와 '동시에 닿았다가 나아가는 경우' 모두를 고려해야 하므로 주의.

그리고, 포함관계가 흐트러지는 요인이기도 하기 때문에, 편한 방법이기는 하지만, 사용하기 전에 한번 고민을 해 보는 것이 좋다.


복합적으로 사용하는 것도 고려해봄직 하다. 수직 발사대 같은 경우에는 x와 z축 좌표는 transform.position 변화를 사용하고 y축 이동은 속도 변화로 구현하는 식.

물론, 오히려 복잡해지는 구성이기도 하기 때문에, 어떤 방식이 오류가 적고 편하게 구성 가능한지를 잘 생각해 보고 결정해야 할 것이다.

 


사실,  금일 작성한 내용은 게임의 구성에 따라서 다르게 작동해야 하는 요소라서 정답이라고 할 것은 없다.

내용에서도 나와 있듯이 각자의 방식 마다 장단점이 있는 데다가, 방식이 이것 만 있는 것도 아니다.

[좀 오버하자면, 매니저로 일괄 관리하는 것도 가능하다. 물론, 어지간하면 별로 좋지 않다.]

그러니, '이것이 정답이다'라고 생각하기 보다는 그때 그때 무엇이 필요한지를 판단하고 직접 설계하는 것이 좋을 것이다.

 

 

p.s. 적고 나서 생각해 보니, Laycast로 바닥을 인식하는 걸 이용해서 바닥의 이동을 따라가도록 처리하는 것도 나쁘지 않은 거 같다. 물론, 이 경우에는 바닥의 정보를 Laycast 하는 객체에서 들고 있어야 하겠지만, 측면에 붙어서 따라간다거나 하는 경우가 발생하지 않게 되니까...