텔레포트(Teleport)
4.9버전에서 저희는 teleport 옵션을 여러 블루프린트 노드에서 보일 수 있도록 하였고, 이번 포스트는 teleport가 어떻게 동작하는지 자세한 설명을 드릴 좋은 기회 같습니다.
물리적 물체(물리계산이 이루어지고 있는 물체)를 움직일 때는 속도와 충돌 반응에 관심을 갖게 됩니다. 보통 물체의 위치(또는 회전시)가 변경되면, 물리 엔진은 추정 속도를 계산하고 이 값을 오브젝트가 움직이는 데 사용합니다. 이런 과정을 통해 물체는 올바른 속도로 튕겨나가게 됩니다.
이러한 추정 속도로부터의 부작용으로 생겨나는 멋진 효과는 캐릭터에 붙은 시뮬레이트 바디(포니테일이나 주머니)가 물리적으로 흔들리는 것입니다. 하지만, 이 효과는 아주 먼 거리를 짧은 순간에 이동시켰을 때(리스폰 등과 같이) 문제를 발생시킵니다. 이런 경우, 추정 속도가 엄청나게 커질 것인데, 왜냐하면 속도= 움직인 거리 / 프레임사이 걸린 시간 이기 때문이죠.
이런 문제로부터 벗어나기 위해, 저희는 위치가 즉시 바뀌어도 관성에 영향을 주지 않도록 하는 teleport 옵션을 넣었습니다.
예제:
이 예제에서 단순한 구체 위에 앞뒤로 흔들리는 물리 시뮬레이션이 되는 안테나를 붙였습니다. 만약 SetWorldLocation을 이용해서 벽을 통과해서 순간이동 시킨다고 한다면 (박스가 쌓여있는 벽) 올바로 시뮬레이션이 되지 않을 것인데, 왜냐하면 안테나에 엄청난 추정 속도가 계산될 것이기 때문입니다.
teleport 옵션에 체크를 하면, 캐릭터가 이동시 속도가 유지되며, 안테나에 영향을 끼치지 않게 됩니다.
스윕(Sweep)
sweep옵션은 움직임에 제한을 줄 때 사용됩니다. 예를 들어서, 플레이어가 벽을 통과해서 걷지 못하게 하려면 sweep에 체크를 하면, 이동 중간에 처음 닿는 것이 있을 때 멈추게 됩니다. sweep와 teleport는 서로 완전히 연관이 배제되어 있고, 여러분은 이 둘을 어떻게 조합하느냐에 관해 관심을 갖고 계실 것입니다.
예제
여기 예제에는 AddActorLocalOffset을 매 프레임마다 불러서 움직이게 만듭니다. 저희는 두 가지 옵션에 대한 총 4개의 시뮬레이션 결과를 보여드립니다. teleport가 꺼져 있으면 안테나는 관성 때문에 천천히 움직이게 됩니다. teleport가 켜져 있으면, 안테나는 구와 같은 속도로 움직이게 됩니다. sweep이 켜져 있으면 박스와 닿았을 때 멈추고, sweep가 꺼져 있을 때, 박스를 치고 지나가게 됩니다.
아래는 결과를 정리한 표입니다.
Teleport = False | Teleport = True | |
---|---|---|
Sweep = False |
최종 위치는 사용자에 의해 정해짐 최종 위치에 따라 속도가 결정됨. 충돌 가능 물체는 추정 속도의 영향 또한 받음 |
최종 위치는 사용자에 의해 결정됨 속도에 영향을 받지 않음 실제 충돌만 일어남 |
Sweep = True |
진행중 첫 번째로 충돌하는 물체가 있는 경우 정지 최종 위치에 따라 속도가 결정됨 sweep에 의해 충돌이 방지됨 |
진행중 첫 번째로 충돌하는 물체가 있는 경우 정지 속도에 영향을 받지 않음 sweep에 의해 충돌이 방지됨 |
CCD
여러분은 왜 벽을 통과하는 첫 번째 예제에서 벽에는 아무런 물리적 영향이 없는지에 대해 궁금해 하실 수 있습니다. 그것은, 물리 엔진이 단순 이동과 순간 이동을 판단할수 있느냐는 질문으로 귀결됩니다.
물리 엔진의 계산 방식에서 기본적으로 적용되는 성질에서 그 답을 구할 수 있습니다. 실제로 물체를 움직이도록 해서 그 사이에 있는 반응들을 계산하는 것에는 비용이 많이 듭니다. 대신에, 물리엔진은 최종 위치에(프레임간이라면 다음 프레임의 위치에) 놓고, 충돌이 있는지를 감지합니다. 만약 teleport 옵션이 켜져 있으면, 충돌 가능한 오브젝트들은 추정 속도가 적용되지 않습니다 (실제로 관련된 속도를 무시합니다). 만약 teleport가 꺼져 있으면, 충돌 가능한 물체는 추정된 속도 때문에 뒤로 확 제껴질 것입니다.
하지만, 여러분은 지속적 충돌 감지(CCD)를 켬으로써 이를 해결할 수 있습니다. 이 것은 계산적으로는 비용이 비싸지만, 아주 빠른 움직임을 표현해야 하는 물리 기반 게임에 꼭 필요한 기능입니다.
Sweep, Teleport 와 CCD는 택일적으로 사용할 수 있습니다. teleport가 켜져 있다면 CCD가 꺼져 있다는 걸 말합니다.
시뮬레이션 된 오브젝트들
시뮬레이션 되는 오브젝트의 속도는 물리 시뮬레이션에 의해 결정됩니다. 이런 속성 때문에, 시뮬레이션 된 오브젝트의 모든 움직임은 묵시적으로 teleport 처리가 됩니다. 게다가, 운동 중으로 시뮬레이션 되고 있는 물체는 특별한 처리를 해야 합니다. 시뮬레이션 중이 아닌 오브젝트의 위치가 teleport 사용 없이 바뀐 경우를 가정해 보죠. 이런 경우에는 우리가 물리 엔진에게 오브젝트가 마지막 프레임에 도착하도록 물체의 속도를 변경하라고 시키는 것이 됩니다. 하지만, 시뮬레이션을 하는 것으로 갑자기 변경하면, 지정한 마지막 위치가 무시되는 것을 알 수 있습니다. 이 것은, 물리 시뮬레이션이 적용되지 않았고, 새롭게 계산된 추정 속도가 적용된 것을 의미합니다. 이 결과는 우리가 요청한 원래 설정이 효과적으로 무시되었다는 것을 말합니다. 만약 우리가 최종 위치를 확정하고 싶다면, 반드시 teleport를 사용해야 합니다.
씬 쿼리
보통의 오브젝트의 움직임은 물리 시뮬레이션측에 거치됩니다.(시뮬레이션 중에는 움직임을 계산할 때 속도만을 사용합니다.)하지만, 씬 쿼리로 오게 되면(레이 캐스트, 캡슐 스윕 등..) 결과물은 즉시 일어난 것 처럼 다뤄집니다. 이런 불일치는 설계된 것이고, 일반적인 게임 플레이의 경우를 생각해보신다면 여러분은(원컨대) 동의하게 되실 것입니다.
두 개의 캐릭터가 있는 경우를 생각해 보겠습니다. 여러분은 캐릭터들이 벽을 통과해 (또는 캐릭터끼리) 원하지 않는다고 하면 sweep 에 체크를 해서 움직이게 될 것입니다. 그리고 나서 두 캐릭터가 같은 위치로 가는 경우를 가정해 보겠습니다. 1번 플레이어가 먼저 움직이고, 지정된 위치로 sweep을 적용하면서 움직입니다. 그 위치에는 아무것도 없기 때문에 먼저 가서 물리 엔진에게 해당 위치로 움직이라고 전달을 하게 됩니다. 그리고 나서 2번 플레이어가 캡슐을 기준으로 sweep을 합니다. 씬쿼리는 위치 이동을 즉시 처리하기 때문에 1번 플레이어가 이미 해당 위치에 가 있다는 사실을 반환받을 수 있습니다. 2번 플레이어는 최종 위치쪽으로 가기는 하지만, 1번 플레이어와 부딪히는 순간 멈추게 됩니다.
씬쿼리가 물리 시뮬레이션처럼 거치식을 사용하였다면 2번 플레이어는 1번 플레이어의 위치를 감지하지 못하고(실제 위치 변경이 이루어지지 않았기 때문) 1번 플레이어와 2번 플레이어는 동일한 위치에 겹쳐서 나타나게 될 것입니다. 피해가려던 결과가 나타나는 것이죠.