https://www.factorio.com/blog/post/fff-385
FFF #385 - 소행성 수집기
게시자 Earendel, Hrusa
2023-11-17
안녕하세요,
이미 FFF-380에서 우주 플랫폼의 처리 공정을 보여드렸습니다. 이 모든 것을 가능하게 하는 기계, 즉 소행성 수집기에 대해 조금 더 이야기해 보겠습니다.
촉수의 기원 - Earendel
초기 우주 플랫폼 콘셉트 작업을 하면서 움직이는 우주선이 어떻게 생겼을지 고민할 때 소행성의 파편을 우주선에 실을 수 있는 방법이 필요하다는 것은 인지하고 있었지만 어떻게 할지는 결정하지 못했습니다. 이 초기 단계에서는 모든 새로운 구조물에 매우 단순한 플레이스홀더 그래픽이 사용되었습니다.
회색 상자로 시작하지만 가능한 한 빨리 더 적절한 것으로 교체하는 것이 가장 좋습니다. 가장 초기의 플레이스홀더는 보통 일반적인 모양을 빠르게 스케치하거나, 기존 그래픽에서 적당히 덧붙인 것 또는 제 모드에서 가져온 것을 사용합니다. 소행성 수집기의 경우, 상당히 일반적인 측면 장착 구조물을 플레이스홀더로 사용했습니다. 이런 구조물을 계속 사용했다면 중력 빔 같은 것을 사용해 소행성 덩어리를 끌어당겼을 것입니다. 중력 빔(또는 전기 그래플 등)은 애니메이션과 코딩이 간단한 개념이기 때문에 이런 상황에서 쉽게 대체할 수 있는 옵션입니다.
중력 빔은 팩토리오답지 않게 느껴졌어요. 너무 마법같거나 공상과학적인 느낌이 강하고 흔하게 사용되니까요. 저는 좀 더 기계적인 것을 원했고 Albert도 동의해서 중력 빔은 제외되었습니다. 팩토리오에 첨단 기술이 없다는 것이 아니라, 가능하면 좀 더 실감나고 산업적인 방식으로 하는 것이 더 낫다는 것이죠.
여러 가지 대체 옵션을 생각해 보았지만 여기에는 컨셉 아트와 함께 5가지 옵션을 소개하겠습니다.
1. 로켓 유도 작살 or 가방
충돌 시 소행성 덩어리를 가방에 감싼 다음 견인 줄을 사용하여 수집기 입구로 끌어당기는 소형 로켓입니다.
2. 길쭉한 투입기 같은 팔
투입기와 비슷하지만 소행성 덩어리를 잡는 데만 사용됩니다. 소행성 덩어리를 기계의 '입'에 넣거나 뒤에 있는 벨트에 직접 올려놓습니다.
3. 패들
투입기 팔과 비슷하지만 덩어리를 잡을 필요가 없습니다. 수집기의 입구 방향으로 소행성을 때려서 날아가게 합니다.
4. 깔대기
수집기 자체는 플랫폼 쪽에 구멍을 뚫기만 한 것으로, 그 안으로 떨어지는 덩어리만 모으는 것입니다. 여기에 쐐기 모양의 블록 세트를 플랫폼 전면에 추가하면 이동 중에 덩어리가 쐐기에 부딪히면 튕겨져 나가도록 하여 덩어리를 수집기 구멍으로 유도할 수 있습니다. 이 아이디어는 배의 전면 모양을 중요하게 만들기 때문에 처음에는 재미있어 보이지만, 단점은 대부분의 배는 획일적인 V, W 또는 WWW 모양으로만 만들어질 수 있다는 것입니다.
5. 유연한 스네이크 팔
투입기 팔과 달리 소행성 덩어리 및 플랫폼 자체와 동일한 평면에서 작동하므로 튀어나온 방어선을 따라 뱀처럼 움직여야 합니다. 플랫폼 모양이 도달 시간에 영향을 미치므로 흥미로운 옵션입니다.
저는 유연한 팔 아이디어로 꽤 멋진 것을 만들 수 있다고 생각했습니다. 저는 다양한 기계 구조와 수집기 입구 모양을 묘사하는 스케치 세트로 시작했습니다. 팔 자체는 실제 뱀 로봇의 디자인과 가장 유사하지만 한쪽 끝에 고정되어 있어 '촉수'라는 이름으로 빠르게 알려지게 되었습니다. 분쇄 기능을 소행성 수집기에서 전용 기계로 옮긴 것도 주목할 만합니다. 이를 통해 게임 후반 고급 레시피에서 분쇄기를 다시 사용하고 플랫폼 중앙을 확장할 수 있습니다.
아래는 제가 Kovarex에게 제시한 콘셉트 아트입니다. 이때까지만 해도 사람들은 뱀이나 촉수 아이디어에 회의적이었기 때문에 콘셉트 아트로 사람들의 마음을 사로잡지 못하면 다시 원점으로 돌아갈 수도 있었습니다. 다행히도 Kovarex가 이 콘셉트 아트를 보자마자 동의했고 다른 사람들도 확신을 가졌습니다. Hrusa는 이 아이디어를 현실로 만들기 위해 뛰어들었고, 이제부터는 그가 맡아서 진행할 수 있게 되었습니다.
개념에서 현실로 - Hrusa
이제 시간을 거슬러 올라가 그동안 게임플레이 측면에서는 어떤 일이 벌어졌는지 이야기해 보겠습니다.
우주 플랫폼 공정의 핵심 기능인 이 수집기는 Earendel의 손에서 회색 상자로 삶을 시작했습니다. 더 단순했던 시절이었죠. 당시에는 소행성이라는 개념조차 없던 시절이었습니다! 따라서 이 기계는 허공에서 덩어리를 계속 만들어내는 조립 기계에 불과했습니다.
소행성이 게임에 등장하면서 실제로 소행성을 수집하는 첫 번째 버전에서는 소행성 주위에 단순한 직사각형이 그려졌습니다. 소행성 덩어리가 화면안에 들어가면 즉시 수집기의 인벤토리로 순간이동했습니다. 화려하지는 않지만 플레이 테스트에는 충분했습니다.
다음 발전은 소행성을 기계적으로 수집하는 것이었습니다. Rseding은 Earendel의 초기 작살 아이디어를 구현하는 것으로 일을 시작했습니다:
이 시점에서 수집기는 플랫폼의 어느 곳에나 배치할 수 있었습니다. 해양 펌프처럼 가장자리에만 놓도록 하는 방안도 고려되었지만 그땐 아직 결론을 내리지 못했었습니다. 자체적인 제한을 두고 테스트를 진행한 결과 중요한 문제가 빠르게 드러났습니다.
유효 도달 범위가 상대적으로 매우 길었기 때문에 최적의 전략은 항상 플랫폼 가장자리에서 멀리 떨어진 곳에 수집기를 배치하는 것이었습니다. 이러한 설정은 플레이어의 의사 결정을 거의 요구하지 않았습니다. 가장자리 전체는 포탑 전용으로 사용할 수 있고 내부에는 소행성 덩어리를 내리고 처리할 수 있는 충분한 공간을 확보할 수 있었습니다. 무엇보다도 플랫폼 차원에서 작살이나 팔이 다른 건물 위로 뻗어 덩어리를 가져가는 시각적 효과는 모호했습니다.
논리적인 결론은 수집기들이 열린 공간에 접근해서 건설하도록 강제해야 한다는 것이었습니다. 이렇게 하면 방어와 자원 수집 사이에 흥미로운 역학 관계가 형성되고 효율적인 벨트 사용에 대한 보상이 주어집니다. 당시 Earendel은 보다 유기적인 느낌의 구부릴 수 있는 팔에 대한 콘셉트를 구상하고 있었고, 이 콘셉트는 결국 게임에 적용되었습니다.
촉수의 날
이제 이 모든 것을 실현하는 방법을 알아내는 것은 제 몫이었습니다. 예상되는 동작이 정해지면 팩토리오를 플레이할 때와 마찬가지로 작업을 여러 개별 기능으로 분리할 수 있었습니다. 각 기능들이 독립적으로 작동할 수 있는 단위로 움직이기를 원합니다.
- 팔을 그리는 것만 가능. 다른 동작이나 기능은 없습니다.
- 포즈와 다른 포즈 사이에 팔을 구동하기.
- 플랫폼 주위에 팔을 끼이거나 충돌하지 않고 엮기. 모든 상황에 대응이 가능할까요?
- 수집기들이 같은 덩어리를 놓고 싸우느라 시간을 낭비하지 않도록 하기.
나중에 도움이 될 수 있도록 특정 포즈를 분할된 선, 즉 밑면에서 시작하는 일련의 각도의 목록으로 표현하기로 결정했습니다. 또한 각 포즈에는 확장 길이값이 포함됩니다. 이렇게 하면 새로운 점을 계산하지 않고도 커브의 길이를 따라 팔을 위아래로 움직일 수 있습니다.
팔의 포즈는 각도와 확장되는 길이의 목록으로 표현됩니다.
수집기 팔을 그리는 데 사용되는 링크들의 회전된 모습들입니다.
다음으로 팔의 움직임에 약간의 스윙을 넣는 컨트롤 커브를 추가하려고 했지만 결과가 약간...
계획 변경
수집기에 대해 생각하던 중, 수집기가 확장된 후에도 추가 덩어리를 수확할 수 있어야 한다고 결정했습니다. 팔은 일련의 각도로 표현되기 때문에 각각의 각도를 블렌딩하여 시작 포즈와 원하는 포즈 사이를 블렌딩할 수 있습니다.
이상적으로는 팔의 끝에 위치한 갈고리가 일정한 속도로 움직이기를 원합니다. 하지만 각도를 블렌딩하기 때문에 속도가 크게 달라집니다. 팔을 10단위로 연장하느냐 또는 20단위까지 연장하느냐에 따라 베이스를 5°만 돌려도 결과가 크게 달라집니다. 수집기의 경로 범위는 원형으로 보이지만 실제로는 쉽게 측정할 수 없는 복잡한 모양입니다.
대신 모든 개별 각도에 가중치를 부여하고 팔 위치를 원에 투영하는 방법을 찾았습니다. 그런 다음 원에서 두 팔의 포즈 사이의 거리를 측정하여 이동 거리를 일관성 있게 추정할 수 있었습니다.
계산을 테스트하기 위해 만든 팔 블렌드 시뮬레이션입니다. 팔을 청록색 원에 투영하여 이동 거리를 추정합니다.
최종 디자인 문제는 팔이 두 포즈 사이에서 이동하는 방법이 매우 다양하다는 것입니다. 이는 위에서 언급한 각속도 관계 때문입니다. 팔이 짧을수록 더 빠르게 회전할 수 있습니다. 하지만 최적의 이동 거리에 도달하기 위해 팔을 접고 펴는 데도 시간이 걸립니다.
호 거리와 마찬가지로 수학적 문제를 표현하고 진정한 해를 구하기 위해 시간을 보냈습니다. 그러다 훨씬 적은 노력으로 정말 가까이 갈 수 있다는 것을 깨달았죠. 스윙하기에 가장 좋은 절대적인 확장 길이를 찾는 대신 일정한 간격으로 확장 길이를 선택해 각각에 대한 이동 거리를 계산한 다음 가장 좋은 확장 길이를 선택했습니다. 실제로는 그 경로가 절대적으로 가장 좋은 경로에서 ±0.5단위 떨어져 있는지조차 알 수 없습니다.
이동에 고려되는 경로 중 세 가지를 표시합니다. 회전 반경이 고려되는 증가 비율이 강조표시됩니다.
이 무렵 가성비에 대해 논의하기 시작했습니다. Kovarex는 팔의 느낌이 매우 마음에 들었지만 시뮬레이션되는 모든 링크가 수십 개의 플랫폼이 있는 대규모 공장에 영향을 미치지 않기를 원했습니다. 이를 위해 이전 단계를 사용할 수 있었습니다. 갈고리가 예측 가능한 속도로 이동하도록 했으므로 매번 위치를 업데이트할 필요가 없습니다. 원하는 경로를 찾으면 그 거리를 저장합니다. 그런 다음 갈고리가 이 경로를 따라 얼마나 멀리 이동했는지 추적하는 내부 숫자를 하나씩 증가시킵니다. 플레이어의 화면에 팔이 보이는 경우에만 실제 중간 팔 포즈를 계산합니다.
블록 주변 이동
팔의 움직임이 해결되면 경로 찾기 문제로 넘어갔습니다. 초기 아이디어는 고전적인 A* 알고리즘을 가져와 인접한 모든 타일을 매핑하여 각 타일에서 수집기로 가는 최단 경로를 찾는 것이었습니다. 하지만 각 타일의 기록은 많은 용량을 차지했고, 그 결과 경로가 매우 들쭉날쭉해져 보기에 좋지 않았으며 추가 처리가 필요했습니다. 게다가 수집기는 종종 넓게 열린 공간에 배치되어 있습니다. 청크가 지나갈 때마다 타일 하나하나를 가로지르는 것은 매우 비효율적인 작업입니다.
이러한 관찰에 비추어 저는 내비게이션 메쉬를 구현하기로 결정했습니다. 내비게이션 메쉬는 큰 직사각형으로 열린 영역을 덮습니다. 그런 다음 광선을 투사하여 해당 직사각형의 중요한 모서리 사이의 모든 직접 연결을 찾습니다. 플레이어가 플랫폼 타일을 만들 때마다 내비게이션 메쉬를 새로 구성하고 유지하려면 약간의 연산 능력이 필요하지만, 그 대신 경로를 찾는 속도가 크게 빨라집니다. 더 좋은 점은 내비게이션 메쉬에서 찾은 경로가 실제로 가장 짧고 단순하다는 것입니다.
이전 타일 탐색 방식. 들쭉날쭉한 경로가 눈에 띕니다.
최종 내비게이션 메쉬 시스템입니다.
다각형 내비게이션 메쉬 경로를 더 보기 좋게 만들기 위해 날카로운 모서리를 부드럽게 처리하는 비균일 유리 B-스플라인(NURBS)을 사용하여 근사화합니다. NURBS의 좋은 특성은 가이드 포인트를 매우 안정적으로 감싼다는 것입니다. 따라서 3D 모델링 프로그램에서 매우 인기가 있습니다.
둥글게 처리하는 작업 외에도 모양을 개선하기 위해 사용하는 몇 가지 사소한 트릭이 있었습니다:
- 수집된 각 덩어리 사이에 최소한의 후퇴 거리가 있어야 합니다('진공 청소기'처럼 보이는 것을 방지하기 위해).
- 목표물이 일직선상에 있을 때 갈고리를 수평으로 감아 착지합니다.
- 양쪽 팔을 무작위로 살짝 흔들어서 한꺼번에 코너를 돌지 않도록 합니다.
- 팔의 밑부분으로 스윙을 리드하여 앞쪽이 끌려가는 것처럼 보이도록 합니다.
변수 예측
수집기 작업을 처음 시작할 무렵에 알려진 문제 중 하나는 플랫폼 속도였습니다. 고품질 추진기를 사용하면 플랫폼이 너무 빨리 움직여 포탑이 다가오는 소행성을 제때 쏘기에 충분할 정도로 빠르게 회전하지 못할 수 있습니다. 저는 이 문제가 수집기에도 큰 문제가 될 수 있다는 것을 알고 있었습니다.
수집기가 매 프레임마다 모든 덩어리를 지속적으로 테스트할 수는 없습니다. 선택의 폭을 좁혀야 했습니다. 이를 위해 새로운 덩어리가 스폰될 때마다 앞으로 라인을 캐스팅하고 그 과정에서 모든 수집기에 등록합니다.
제한 요소는 팔의 가용성이므로 이전 작업을 마칠 때마다 팔은 들어오는 소행성 덩어리를 확인합니다. 이 설계는 주어진 팔이 덩어리에 도달하는 데 걸리는 시간을 기준으로 덩어리 위치를 앞으로 투사하고 정시에 만날 수 있는 공간을 계산합니다. 또한 초고속으로 날아오는 덩어리도 미리 등록되기 때문에 더 이상 문제가 되지 않습니다. 팔은 위치로 미리 이동하여 덩어리가 수거 구역에 닿는 순간 가로챕니다.
수집기에 미리 연결하여 덩어리의 이동을 예측합니다(속도 향상).
결론
모든 주요 작업이 마무리되면 수집기가 마스터 브랜치에 들어갈 준비가 되기 전에 작은 세부 사항을 마무리하는 일만 남았습니다. 건물 수 제한, 블루프린트 지원, 복사 붙여넣기 등이 여기에 해당합니다. 네비게이션 메쉬와 NURBS 시스템은 모두 새로운 코드였기 때문에 테스트를 작성하고, 특이 케이스를 추적하고, 성능을 미세 조정하는 작업이 많았습니다.
전반적으로 플레이 테스트 결과, 소행성 수집기가 우주 플랫폼에 저희가 기대했던 독특한 외관과 게임플레이를 제공하는 데 매우 효과적이었다고 말할 수 있어 기쁩니다.
언제나 그렇듯이 평소 자주 이용하는 장소에서 여러분의 의견을 알려주세요.
로봇팔 하나로 맛있게 쓰네
휴리스틱하게 계산하는 아이디어가 쩌네 - dc App
와 진짜 개발 맛있게 한다
에렌델 그는 신인가
진짜 경이롭네 원래 게임개발 하면 이정도는 하나..?
정말 새삼 내가 하찮게 느껴지네
우리나라에선 이정도하면 탑급임
원래 게임개발쪽은 기하쪽 수학에 익숙해야 하긴 함
시작 지점이 우주선인가? 아니면 바닐라 로켓 이후에 우주로 이어지는 건가? 바닐라 로켓 이후라면 플탐이 어마어마 하다는 건데
바닐라 노란팩 보라팩을 다른행성가서 만든다 보면 됨 - dc App
파란팩하고 바로우주로날라감 로켓도 20배 싸지고
로켓 타이밍이 우탐모 마냥 엄청 땡겨짐
진짜 개멋있다. 나도 저런 개발 할 수 있을까. 크으.
와 근데 이정도 기술이면 몸값좀 높을텐데, 팩토리오 돈 잘 버나보네
이새끼들 게임에 "진심"인 놈들이구나... 할인 안하는거 인정한다
ups 터지는거 아닌가 몰라
그래서 언제나와ㅏㅏㅏㅏ
이때부터였네 개소름 ㄷㄷ