Skip to content

브라우저에서 오픈 월드 만들기, 30부: 벽을 존중하는 카메라

글쓴이: Oleg Sidorkin, Cinevva의 CTO 겸 공동 창업자

처음 오셨나요? 시리즈 가이드를 보세요. spike가 무엇인지 설명하고 모든 파트로 연결해 둡니다.

29부에서는 어떤 몸이든 구동하는 컨트롤러 하나를 얻었습니다. 이제 몸은 제대로 움직입니다. 걷고, 미끄러지고, 수영하고, 활공하고, 동굴로 기어 들어가고, 돌출부 아래로 몸을 숙입니다. 문제는 그것을 지켜보는 쪽입니다. 29개 파트 동안 카메라는 플레이어를 따라다니는 평범한 오빗 리그였고, 망신을 피하려고 딱 한 가지 영리한 짓만 했습니다. 지평선 아래로 기울지 않으려 했고, 그래서 평평한 땅 밑으로 미끄러져 들어갈 수 없었습니다. 그 클램프가 바로 증거입니다. 카메라가 세계의 지오메트리가 실제로 어디에 있는지 전혀 몰랐기 때문에 존재하는 것이고, 클리핑을 막을 유일한 방어책은 클리핑이 가장 일어나기 쉬운 각도를 아예 금지하는 것뿐이었습니다. 언덕으로 다가가면 카메라가 언덕 안에 들어가 앉았습니다. 7부의 마칭 큐브 동굴 하나로 발을 들이면 바위 속을 들여다보게 됐습니다. 16부의 저작 도구로 집을 짓고 방 안에 서면, 카메라는 벽 바깥으로 떠올라 외벽 마감재를 바라봤습니다. 이번 파트는 카메라에게도 몸이 이미 가진 것과 같은, 지오메트리에 대한 존중을 줍니다.

문제의 모양, 그리고 해법의 모양

3인칭 카메라에는 어려운 일이 하나 있고 쉬운 일이 열두 가지 있습니다. 쉬운 쪽은 따라가기, 부드럽게 보정하기, 오빗 입력이고, 이건 이미 다 갖고 있었습니다. 어려운 쪽을 학계 문헌에서는 가시성 제약(visibility constraint)이라 부르고, 모두가 인용하는 서베이인 Christie와 Olivier의 Camera Control in Computer Graphics는 분야 전체를 이것을 중심으로 정리합니다. 세계를 존중하면서도 피사체를 프레임 안에 두고 가려지지 않게 유지하라. 런타임에서 이것은 매 프레임 던지는 속아 넘어가기 쉬울 만큼 단순한 질문으로 줄어듭니다. 플레이어가 피벗입니다. 사용자가 회전하고 줌해서 그들 뒤 어느 정도 거리에 원하는 카메라 위치를 정했습니다. 그 선을 따라 카메라가 무언가 단단한 것에 찔리기 전에 실제로 얼마나 뒤로 앉을 수 있을까요? 이 질문에 정직하게 답하면 카메라는 언덕 앞으로 몸을 집어넣고, 구석으로 후진할 때 붐을 따라 미끄러져 내려오며, 동굴 천장을 뚫는 대신 거기서 멈춥니다.

이 질문에 답하는 패턴은 오래됐고 검증됐습니다. Unreal은 스프링 암이라 부르고, Godot는 SpringArm3D 노드를 제공하며, Unity의 Cinemachine은 그것을 3인칭 팔로우 리그와 디오클루더(deoccluder) 확장으로 나눠 둡니다. 발상은 늘 같습니다. 카메라를 피벗에 고정된 붐 끝에 매답니다. 길이 트여 있으면 원하는 길이로 잡아두고, 무언가 가로막으면 피벗 쪽으로 거둬들이며, 길이 트이면 다시 펴 줍니다. Metroid Prime의 카메라 리드가 쓴 Mark Haigh-Hutchinson의 Real-Time Cameras는 이것의 순진한 버전이 플레이어를 멀미 나게 만드는 실패 모드에 챕터 여러 개를 통째로 씁니다. 우리는 그 패턴을 가져와 한자리에서 다 읽을 수 있을 만큼 작은 우리만의 것을 public/world/src/camera-rig.mjs에 만들었습니다.

피벗 (플레이어 머리)원하는 위치 (사용자 줌)카메라 + 프로브 반지름 rℓ (클램프됨)
붐은 장애물이 끼어들기 전까지 사용자가 원한 줌 거리에 카메라를 잡아둡니다. 그러다 같은 선을 따라 거둬들여, 근평면이 표면을 뚫는 대신 프로브 구가 표면에 가서 닿게 합니다.

자기 길이만 책임지는 붐

리그를 작게 유지해 준 설계 규칙은 29부 컨트롤러 작업에서 빌려온 것입니다. 한 가지를 완전히 책임지고 나머지는 거절하라. 리그는 붐의 길이를 책임지고 그 외에는 아무것도 책임지지 않습니다. 요(yaw), 피치, 오빗 댐핑, 터치와 휠 제스처, 이 모든 것은 OrbitControls에 남겨 둡니다. OrbitControls는 이미 그것들을 잘 풀어내고 있고, 우리는 그걸 다시 쓸 생각이 전혀 없습니다. 그래서 리그는 카메라 컨트롤러가 아닙니다. 오빗 계산이 끝난 뒤에 돌면서 딱 한 숫자, 피벗에서 카메라까지의 거리만 보정하는 후처리입니다.

이 결정은 깔끔하게 들리지만 거의 곧바로 깨질 뻔했습니다. OrbitControls가 생각하는 방식 때문입니다. 매 업데이트의 맨 위에서 OrbitControls는 카메라의 현재 위치를 읽고 거기서 오빗 반지름을 끌어냅니다. 보통은 보이지 않는 동작입니다. 그런데 우리 리그가 벽을 피하려고 카메라를 짧게 당기는 순간, 다음 프레임에 OrbitControls가 그 짧아진 위치를 읽고 사용자가 줌인했다고 결론 내린 다음, 그 짧아짐을 사용자가 원한 줌에 구워 넣습니다. 그게 몇 프레임 이어지면 카메라는 플레이어 머리 위로 무너져 내리고 다시 나오지 않습니다. 해법은 오빗 업데이트를 앞뒤로 감싸는 호출 두 개이고, 통합은 그게 전부입니다. OrbitControls가 돌기 전에 beforeControls()가 카메라를 지난 프레임의 온전한, 짧아지지 않은 거리로 복원해서 오빗 계산이 항상 사용자의 진짜 줌을 읽게 합니다. OrbitControls가 돈 뒤에 afterControls(dt)가 방금 오빗된 원하는 위치를 읽어 충돌을 해결하고, 길이를 댐핑하고, 카메라가 실제로 렌더링되어야 할 곳에 씁니다. 사용자의 의도와 충돌 보정은 서로 절대 닿지 않고, 달리(dolly)는 리그가 존재하기 전과 정확히 똑같이 반응합니다. 리그를 위해 우리가 쓴 헤드리스 테스트가 이것을 정확히 못박습니다. 붐을 60프레임 동안 벽으로 밀어 넣고, 벽을 벗어나면 길이가 충돌 거리에 붙어 있는 대신 사용자의 온전한 줌인 10미터로 다시 튀어 나옵니다.

계약 하나, 콜라이더는 무엇이든

리그는 세계가 무엇으로 만들어졌는지 절대 묻지 않습니다. 콜라이더는 그저 probe 메서드를 가진 객체일 뿐이고, 리그는 거기에 레이, 최대 거리, 카메라의 프로브 반지름을 건네주고 숫자 하나를 돌려받습니다. 그 콜라이더가 막기 전에 카메라가 갈 수 있는 가장 먼 거리입니다. 리그는 등록된 모든 콜라이더에 질의하고 가장 가까운 히트를 택합니다. 그게 계약의 전부이고, 캐릭터 컨트롤러가 이동을 플러그인 가능한 동작으로 바꿨을 때 한 것과 같은 수입니다. 지형이 끼워지고, 소품이 끼워지고, 건물 셸이 끼워지는데, 각각이 같은 probe 뒤에 있고, 리그는 그 모두에 대해 무지한 채로 남습니다. 새로운 종류의 장애물을 더하는 일은 카메라를 고치는 게 아니라 콜라이더를 목록에 더하는 일입니다.

계약 안의 한 가지 디테일이 제 몫을 합니다. 바로 프로브 반지름입니다. 우리는 피벗에서 카메라로 가느다란 레이를 쏘지 않고, 카메라의 근평면을 담을 만큼 큰 구를 쏩니다. 단일 레이는 카메라 중심을 벽에서 멈추지만, 근평면에는 폭이 있어서 그 모서리들은 중심 레이가 히트를 보고하기도 전에 이미 벽에 파묻혀 있습니다. 레이 대신 작은 구를 휘둘러 쓰는 것은 출시된 모든 구현이 하는 일이고, Unreal은 그것을 프로브 크기로 노출합니다. 표면에 깨끗하게 가서 멈추는 카메라와 화면 가장자리에서 너머가 비쳐 보이게 두는 카메라의 차이가 바로 이것입니다.

우리는 그 반지름을 추측하지 않고 도출합니다. 카메라에서 근평면의 가장 먼 점은 그 모서리 중 하나이고, 거기까지의 거리는 투영에서 곧장 떨어져 나옵니다. 근평면 n과 수직 시야각 θ에서, 절반 높이는 h=ntan(θ/2), 절반 폭은 w=haspect이고, 모서리는 다음 위치에 있습니다.

rnear=n2+w2+h2

프로브 반지름은 그 모서리 거리에 작은 안전 여유를 곱한 값이고, 아주 좁은 절두체에서도 합리적인 최솟값 아래로 떨어지지 않도록 고정 하한을 둡니다. 시야각, 종횡비, 근평면이 바뀔 때마다 반지름을 다시 계산해서, 창 크기 변경이나 투영을 건드리는 줌이 프로브를 보호해야 할 모서리를 덮지 못할 만큼 조용히 작게 남겨 두는 일이 없게 합니다.

동굴을 아는 콜라이더

지형 콜라이더가 흥미로워지는 지점입니다. 우리 엔진의 지형은 하이트맵이 아니기 때문입니다. 7부 이후로 그것은 부호 거리 필드(signed distance field)였습니다. 공간의 임의의 점이 가장 가까운 단단한 표면에서 얼마나 떨어져 있는지, 그리고 바위 안쪽인지 바깥쪽인지를 돌려주는 함수입니다. 양수는 공기, 음수는 바위이고, 바로 그 단 하나의 사실이 우리 카메라가 하이트맵 카메라로는 구조적으로 불가능한 일을 할 수 있는 이유입니다. 하이트맵은 어떤 x와 z에서의 지면 높이를 압니다. 천장이라는 개념은 없습니다. 어떤 점 위에는 언제나 표면이 하나뿐이기 때문입니다. 그래서 하이트맵 카메라는 당신이 언덕으로 걸어 들어가는 것은 막을 수 있어도, 돌출부 입술이나 동굴 지붕이 피벗 위에 걸려 있다는 것은 전혀 모르고 둘 다 그대로 뚫고 지나갑니다. 거리 필드는 3차원의 모든 표면을 알기 때문에, 언덕 비탈에서 카메라를 멈추는 같은 프로브가 단 하나의 특수 처리도 없이 동굴 천장에서 카메라를 멈춥니다.

동굴단단한 바위플레이어하이트맵: 뚫고 지나감 ✗SDF: 천장에서 멈춤 ✓
하이트맵은 기둥마다 표면을 하나씩 저장하므로, 플레이어 위에 놓인 바위 판을 절대 보지 못하고 붐이 천장을 뚫고 올라가게 둡니다. 거리 필드는 그 판 안쪽에서 음수이므로, 프로브가 거기에 닿아 카메라가 동굴 지붕 바로 아래에 머뭅니다.

필드를 따라 프로브를 걷게 하는 것은 이름과 논문이 있는 기법입니다. 1996년 John Hart의 Sphere Tracing은 거리 필드에 대해 레이를 행진시키는 표준 방법이고, 비결은 필드가 무언가에 부딪혔는지만 알려주는 게 아니라 부딪히지 않고 전진할 수 있는 안전 거리를 알려준다는 점입니다. 그래서 작고 고정된 보폭으로 살금살금 가는 대신, 필드를 샘플링하고, 보고된 여유만큼 앞으로 나아가고, 반복합니다. 트인 공기 속에서는 성큼성큼 걷고 표면에 가까워질수록 짧고 조심스럽게 걷습니다.

다만 우리 지형이 강요하는 함정이 하나 있습니다. 진짜 거리 필드는 가장 가까운 표면까지의 실제 유클리드 거리를 보고하고, 그 여유만큼 한 걸음 통째로 가는 것은 언제나 안전합니다. 그런데 지형이 깎인 복셀이 아니라 아직 하이트맵인 곳에서는, 우리가 싸게 샘플링할 수 있는 필드가 진짜 거리가 아니라 수직 여유(vertical clearance), 곧장 아래 지면까지의 간격입니다. 비탈에서는 가장 가까운 바위가 바로 아래가 아니라 옆쪽에 있기 때문에, 그 숫자는 카메라가 실제로 움직일 수 있는 거리를 과대 보고합니다. 정직한 거리는 경사도에 따라 커지는 인자 1+h2만큼 더 작아서, 보고된 여유에 맞춰 잡은 보폭은 과도하게 넘어가 능선을 깨끗이 뛰어넘어 버릴 수 있습니다. 해법은 과소 완화(under-relaxation)입니다. 보고된 여유 전부가 아니라 그 일부만큼만 전진하는 것으로, 대략 60도 경사까지 안전하게 유지되고 진짜 거리 복셀 영역에서는 샘플 몇 개를 더 쓰는 것 말고는 비용이 들지 않습니다. 여기에 보폭 하한을 짝지어, 한두 셀 두께의 동굴 벽이 깨끗이 건너뛰어지는 일이 없게 하고, 더 빡빡한 상한으로 행진을 싸게 유지합니다. 구가 마침내 표면에 닿으면 짧은 이분법으로 접촉점을 좁히고, 카메라는 자기 반지름만큼 물러나 거기에 머뭅니다.

써 놓고 보면, 붐은 피벗 p에서 단위 방향 d를 따라가는 레이 r(t)=p+td이고, 행진은 접촉에 이르기까지 필드 여유의 과소 완화된 일부만큼 전진하며 양 끝에서 클램프됩니다.

tn+1=tn+clamp(λ(Φ(r(tn))r),smin,smax)

여기서 Φ는 부호 거리로 공기 중에서 양수이고 바위 안에서 음수, r은 프로브 반지름, λ(0,1]은 과대 보고하는 하이트맵 필드가 비탈을 뛰어넘지 못하게 막는 과소 완화 인자, smin,smax는 얇은 벽이 건너뛰어지지 않고 행진이 너무 길어지지 않게 하는 보폭 클램프입니다. 접촉은 Φ(r(t))r인 첫 번째 t로, 구의 표면이 바위에 도달했다는 뜻이고, 카메라는 그 호 길이에서 반지름을 뺀 지점에 머뭅니다.

콜라이더는 안전망으로 메서드 하나를 더 지닙니다. 침투 해소(depenetration)입니다. 충돌은 애초에 카메라를 단단한 것 바깥에 두어야 하지만, 몇몇 상황이 그것을 슬쩍 빠져나갑니다. 붐이 그 안에서 시작될 만큼 얇은 벽에 걸쳐 선 피벗, 카메라가 앉아 있던 바위가 지형 도구로 방금 깎여 동굴이 되어버린 경우, 카메라 둘레로 떨어뜨려진 건물 조각 같은 것들입니다. 그런 경우를 위해 콜라이더는 카메라가 단단한 것 안에서 프레임을 끝냈는지, 곧 Φ(c)<r인지를 확인하고, 그렇다면 필드의 그래디언트를 읽습니다. Φ는 바위를 벗어날수록 커지므로 그래디언트는 트인 공기 쪽을 곧장 가리킵니다. 그 방향을 따라 카메라를 밖으로 밀어냅니다.

cc+(rΦ(c))Φ(c)Φ(c)

이런 반복 몇 번이면 r-등위면으로 수렴하고, 이것이 바로 조각 도구가 카메라 발밑의 땅을 파내도 화면이 까매지는 대신 다음 프레임에 시야가 회복되게 만드는 것입니다.

빠르게 들어가고, 느리게 풀어주며, 울타리 기둥에 움찔하지 않기

매 프레임 충돌 거리로 그냥 점프하는 붐은 붐이 없느니만 못합니다. 세계는 카메라가 한 프레임 동안 뒤로 지나치는 얇은 것들로 가득하기 때문입니다. 울타리 기둥, 가로등, 나무줄기, 그리고 그 하나하나를 피하려 달려들었다가 다시 달려드는 카메라는 메스껍습니다. Haigh-Hutchinson의 책과 Itay Keren의 사랑받는 카메라 모션 강연은 둘 다 같은 직관에 도달합니다. 카메라는 위협과 위험에는 거기서 풀려나는 것보다 더 빨리 반응해야 한다는 것입니다. 그래서 댐핑은 일부러 비대칭입니다. 가림막이 나타나 붐이 짧아져야 할 때는 거의 즉시 들어옵니다. 한 프레임의 클리핑은 보기 흉하고, 플레이어는 빠른 끼워 넣기를 용서하기 때문입니다. 가림막이 사라져 붐이 늘어나려 할 때는 천천히 풀려 나오고, 그것도 연속해서 트여 있는 짧은 대기 타이머가 지난 뒤에야 그렇게 합니다. 그 대기가 움찔거림을 죽이는 히스테리시스입니다. 얇은 기둥 옆을 카메라로 휙 지나가면 기둥은 느린 확장을 촉발할 만큼 오래 트이는 법이 없어서, 카메라는 그것이 없는 것처럼 미끄러져 지나갑니다. 바로 당신의 눈이 원하는 것이죠. Cinemachine은 같은 발상을 충돌로 들어가는 댐핑과 충돌에서 나오는 댐핑이라는 별도의 값으로 노출하고, 이 비대칭이 그것을 스프링이 아니라 카메라 오퍼레이터처럼 느껴지게 만드는 부분입니다.

코드로는 변화의 부호에 따라 비율을 전환하는 지수 평활화 한 줄입니다. 이 현재 붐 길이, a가 이번 프레임 충돌이 허용하는 길이, Δt가 프레임 시간이라면,

+(a)(1ekΔt),k={kinakouta>,kinkout

이고, 풀려 나오는 분기는 트인 상태가 대기 시간 τ 동안 유지된 뒤에만 돕니다. 1ekΔt 형태는 깔끔해 보이는 것 이상의 의미가 있습니다. 프레임 레이트와 무관하게 응답 시간 상수를 1/k로 고정해서, 카메라가 초당 30프레임에서도 144프레임에서도 똑같이 느껴지게 합니다. 순진한 상수 블렌드 +α(a)였다면 빠른 기계에서는 더 빨리 끼워지고 느린 기계에서는 뭉개졌을 것입니다.

마지막 동작은 이 파트 전체를 시작하게 만든 좁은 실내를 위한 것입니다. 붐이 카메라가 플레이어 바로 위에 올 만큼 짧게 무너지면, 플레이어 자신의 아바타를 숨기고 시야가 1인칭에 가깝게 앉게 둡니다. 비좁은 사당에서 Breath of the Wild가 하는 일이고, 대부분의 3인칭 게임이 구석에서 기대는 동작입니다. 대안인 벽에 박혀 머리 뒤통수를 노려보는 카메라는 쓸모가 없기 때문이죠. 리그는 이를 위해 플래그 하나를 노출하고, 월드 루프는 그 플래그를 읽어 로컬 아바타의 가시성을 토글합니다. 붐이 1미터 아래면 당신은 사실상 1인칭이고, 벽은 존중되며, 공간이 있는 방으로 후진하는 순간 아바타가 다시 페이드 인되고 붐이 늘어납니다.

다음에 끼워질 것

지형 콜라이더는 오늘 출시되고, 어려운 절반입니다. 지형은 어디에나 있고 거리 필드는 프로브하기 까다로운 대상이기 때문입니다. 저작 spike에서 나온 소품과 건물 셸은 쉬운 절반이고, 계약은 이미 그들을 기다리고 있습니다. 두 번째 콜라이더인 레이캐스트 콜라이더는 피벗에서 카메라를 향해 메시 목록에 대고 레이를 쏘고, 지형 콜라이더와 똑같은 방식으로 가장 가까운 히트를 보고합니다. 싼 버전은 단일 레이를 쏘는데, 소품 수가 늘기 전까지는 괜찮고, 업그레이드는 그 레이를 three-mesh-bvh를 쓴 휩쓸린 구로 바꾸는 것입니다. Garrett Johnson의 라이브러리로, 메시를 바운딩 볼륨 계층으로 감싸 공간 질의가 무차별 대입 대신 로그 시간에 돌게 합니다. 어느 쪽이든 리그는 바뀌지 않습니다. 더 긴 콜라이더 목록에 질의하고 가장 가까운 히트를 택할 뿐이고, 그것이 계약을 먼저 만들고 콜라이더를 나중에 만든 일의 전체 핵심입니다.

이 챕터에서 참조한 기술

숫자 하나만 책임지는 붐. 카메라 리그는 OrbitControls를 대체하는 것이 아니라 그 위의 후처리입니다. 붐의 길이를 책임지고, 요, 피치, 줌, 제스처 처리는 이미 신뢰하던 오빗 컨트롤러에 남깁니다. 통합은 앞뒤로 감싸는 호출 두 개입니다. beforeControls()가 지난 프레임의 온전한 거리를 복원해 오빗 계산이 충돌 짧아짐을 달리인으로 착각하지 않고 사용자의 진짜 줌을 읽게 하고, afterControls(dt)가 충돌을 해결하고 렌더링 위치를 씁니다. 이 한 쌍이 없으면 카메라는 몇 프레임에 걸쳐 플레이어 위로 무너집니다.

플러그인 가능한 콜라이더 계약. 콜라이더는 "이 레이를 따라 피벗에서 당신이 막기 전까지 카메라가 얼마나 갈 수 있는가"에 답하는 probe를 가진 임의의 객체입니다. 리그는 모든 콜라이더에 질의하고 가장 가까운 히트를 택하며, 장애물이 지형인지 소품인지 벽인지 모릅니다. 플러그인 가능한 캐릭터 컨트롤러가 이동에 쓴 것과 같은 한 가지만 책임지는 규율입니다. 프로브는 가느다란 레이가 아니라 근평면을 담도록 크기를 맞춘 휩쓸린 구라서, 중심 레이가 놓칠 표면을 절두체 모서리가 절대 클리핑하지 않습니다. 그 반지름은 투영에서 도출됩니다. 근평면 모서리까지의 거리 n2+w2+h2에 안전 여유를 곱한 값이고, 시야각, 종횡비, 근평면이 바뀔 때마다 다시 계산됩니다.

돌출부와 동굴을 존중하는 부호 거리 지형 프로브. 지형이 하이트맵이 아니라 부호 거리 필드이기 때문에, 언덕 비탈에서 카메라를 멈추는 같은 프로브가 동굴 천장에서도 카메라를 멈춥니다. 하이트맵 레이캐스트로는 구조적으로 볼 수 없는 경우입니다. 행진은 Hart 방식의 스피어 트레이싱으로, 필드가 보고하는 여유의 과소 완화된 일부만큼 나아가며 양 끝에서 클램프됩니다. 하이트맵 영역은 진짜 거리가 아니라 수직 여유를 보고해서 비탈에서 카메라가 움직일 수 있는 거리를 과대 보고하므로, 한 걸음 통째로는 능선을 뛰어넘기 때문입니다. 그래디언트 기반 침투 해소 패스가 카메라 발밑의 땅이 깎여 나갔을 때 시야를 회복시키는 안전망입니다.

대기 타이머가 딸린 비대칭 댐핑. 붐은 가림막이 나타나면 빠르게 들어가고, 가림막이 사라지면 천천히, 그것도 연속해서 트인 짧은 구간이 지난 뒤에야 풀려 나옵니다. 그래서 울타리 기둥을 휙 지나가도 카메라가 절대 달려들지 않습니다. 무너짐 임계값 아래에서는 리그가 1인칭에 가깝다는 플래그를 세우고 월드 루프가 로컬 아바타를 숨깁니다. 벽에 파묻힌 카메라 대신 좁은 실내에 쓰는 표준적인 대안입니다.

참고 문헌

카메라 제어를 가시성 제약으로 바라보는 틀은 Marc Christie와 Patrick Olivier의 Camera Control in Computer Graphics (Computer Graphics Forum, 2008)에서 왔습니다. 거리 필드 행진은 John C. Hart의 Sphere Tracing: A Geometric Method for the Antialiased Ray Tracing of Implicit Surfaces (The Visual Computer, 1996)입니다. 스프링 암 패턴과 그 프로브 구 충돌은 Epic의 Spring Arm Component, Unity의 Cinemachine DeoccluderThird Person Follow에 문서화되어 있습니다. 모션과 댐핑 직관은 Mark Haigh-Hutchinson의 Real-Time Cameras (Morgan Kaufmann, 2009)와 Itay Keren의 Scroll Back: The Theory and Practice of Cameras in Side-Scrollers (GDC 2015)에서 왔습니다. 메시 콜라이더 업그레이드 경로는 Garrett Johnson의 three-mesh-bvh입니다.


30부 중 30부. 이전 글: 29부 - 컨트롤러 하나로 어떤 몸이든 시리즈 가이드: /ko/blog/2026-02-25-open-world-browser-series-guide