https://www.factorio.com/blog/post/fff-441


Friday Facts #441 - Space logistics improvements | FactorioHello, Nice to see you all again so soon.www.factorio.com



안녕하세요. 이렇게 빨리 다시 뵙게 되어 반갑습니다.



혼합 로켓 - Genhis


우주 플랫폼을 처음으로 설정하고 있다고 상상해 보세요. 우주 플랫폼을 짓기 시작하면, 꽉 찬 로켓 하나가 통째로 발사됩니다. 벨트나 조립기계, 용광로가 필요할 때도 마찬가지로 한 종류의 아이템이 꽉 찬 스택으로 발사되죠. 작은 플랫폼 하나를 짓는 데 10~20개의 자동 로켓을 요청할 수 있으며, 결과적으로 인벤토리에는 쓰지 않은 아이템이 잔뜩 남게 됩니다. 이 방식의 장점은 나중에 플랫폼을 재건축하거나 공장을 추가하기로 결정했을 때 아이템을 더 기다릴 필요가 없다는 것입니다. 이것이 저희가 구상한 우주 플랫폼 건설 방식이었습니다. 점진적인 발전을 이뤄나가는 것이죠.


하지만 모든 플레이어가 이런 방식으로 플레이하는 것은 아니며, 일부는 좀 더 미리 계획하는 것을 좋아합니다. 이러한 플레이어들은 꽉 찬 아이템 스택을 한 번에 보내는 것을 로켓 낭비로 여겼으며, 특히 게임 초반에는 더욱 그렇습니다. 저희는 공식 포럼, 레딧, 그리고 커뮤니티 디스코드에서 오가는 이런 논의들을 지켜보고 있었습니다.


한 로켓에 여러 종류의 아이템을 섞는 것은 너무 복잡해 보였고, 저희가 명확한 해답을 가지고 있지 않은 수많은 예외 상황들이 있었기 때문에 2.0 개발 중에는 이를 시도하지 않았습니다. 하지만 이는 저(Genhis) 역시 제 플레이에서 너무나 아쉬웠던 부분이었고, 그래서 저는 저희의 Lua API를 남용하여 '개념 증명(proof-of-concept)'용 모드를 만들기 시작할 정도였습니다. 작동은 했지만 정식으로 배포할 만큼 다듬어지지는 않았고, 제 동료 중 누구도 그것을 보지 못했습니다. 그러던 중 내부 2.1 위시리스트에 이 기능이 독립적인 안건으로 등장했고, 제가 구현하겠다고 자원했습니다.


예외 상황을 처리하고, 저희가 취할 수 있는 선택지들을 고민하며, 무엇을 달성하고자 하는지 논의하는 데 꽤 많은 시간이 걸렸고 타협이 없었던것은 아닙니다. 결국에는 좋은 지점에 도달했다고 생각하므로, 저희의 결과물을 소개해 드리겠습니다.




(플랫폼을 '전체 건설'할때의 모습) / (플랫폼을 건설하기 위해 여러 물건이 혼합되어 적재된 모습)


혼합 물류를 지원하는 데 있어 가장 중요한 부분은 이를 완전 자동화하는 것이었습니다. 즉, 여러분이 우주 플랫폼에서 무언가를 요청하고 로켓 격납고에 자동 요청 기능이 켜져 있다면, 시스템 로직이 알아서 적절한 아이템 묶음을 골라 로봇들이 격납고로 배달하게 만드는 것입니다. 동시에 저희는 성능을 염두에 두어야 했기 때문에 가장 완벽하고 최적화된 해결책을 찾기보다 충분히 좋은 해결책을 찾는 데 초점을 맞췄습니다.


요청은 순차적으로 처리되며, 요청 개수가 가장 적은 것부터 시작합니다. 이것들은 보통 일회성 물품이거나 중요한 아이템을 나타내므로, 플랫폼이 일반적으로 운송하는 대량 화물(예: 불카누스의 방해석이나 행성 과학 팩)보다 먼저 배달되기를 원하기 때문입니다.


로켓을 꽉 채우기에 남은 미충족 요청이 너무 적을 때 문제가 까다로워집니다. 로켓을 반쯤 빈 상태로 보내는 것은 낭비지만, 2.0을 만들 당시에는 이를 어떻게 깔끔하게 해결할지 몰랐습니다. 2.1에서는 요청이 가장 많은 아이템을 골라 초과 배송하기로 결정했습니다. 왜냐하면 플레이어가 그 아이템을 더 필요로 할 확률이 높기 때문입니다. 플레이어가 아이템을 더 요청할 때까지 로켓 발사를 미루는 것은 직관적이지 않으며, 모든 요청이 충족될 때까지라는 조건과 제대로 맞물리지도 않을 것입니다.




단계별로 로직이 작동하는 과정


일부 아이템을 초과 배송하더라도, 시스템의 정렬 제약 조건 때문에 알고리즘이 로켓을 채울 완벽한 조합을 찾지 못할 수도 있습니다. 이런 일은 주로 물류 네트워크에 물품 공급이 충분하지 않을 때 발생합니다. 이 로직은 부족한 아이템이 언젠가는 생산될 것이라 기대하며 발사를 기다리려 합니다. 플레이 테스트 중 몇몇 동료들이 이 상황에 혼란스러워했기 때문에, 저는 물류 흐름을 끊지 않기 위해 기존의 '단일 아이템으로 꽉 찬 로켓' 방식으로 되돌아가는 예외 처리를 선택했습니다.


또한 이와 관련해 다양한 조정 작업을 거쳤으므로 이런 예외 상황이 발생하는 일은 매우 드물 것이며, 플레이어의 피드백에 따라 추후 더 수정해 나갈 수 있습니다.



플랫폼 건설 데드락


또 다른 어려운 문제는 우주 플랫폼의 데드락을 다루는 것이었습니다. 2.0 출시 후 몇 주 뒤 포럼에 버그 리포트가 올라왔습니다. 플레이어가 거대한 플랫폼 청사진을 붙여넣었는데, 플랫폼 허브의 인벤토리 공간이 모든 요청을 수용하기에 충분하지 않았던 것이죠. 충분한 양의 플랫폼 타일과 화물 저장고가 건설되기도 전에, 다른 자잘한 아이템들이 허브를 먼저 꽉 채워버렸습니다. 당시 임시방편으로는 일부 아이템을 다시 행성으로 내려보내고 화물 저장고가 이번에는 제대로 들어갈 수 있도록 조치해야만 했습니다.


물론 이를 근본적으로 수정해야 했고, Rseding(개발자)이 코드를 변경하여 건설 불가능한 아이템을 아예 건설 요청에 넣지 않도록 만들었습니다. 이 수정은 로켓이 한 가지 아이템을 꽉 채운 단일 스택을 보낼 때는 괜찮았지만, 새로운 혼합 화물 시스템에서는 매우 비효율적인 결과를 초래했습니다. 그렇다고 이 버그를 다시 발생하도록 놔둘 수는 없었기 때문에 다른

해결책을 찾아야 했습니다.


해당 포럼 스레드에서는 우주 플랫폼의 우선순위를 높이자는 제안이 있었고, 어차피 새로운 묶음 로직을 위해 아이템 요청들이 이미 정렬되고 있었기 때문에 이는 실현 가능해졌습니다. 그래서 저는 아이템 프로토타입에 '요청 우선순위 API'를 추가하고, 이를 플랫폼 기반과 화물 저장고에 활성화했습니다. 화물 저장고는 더 많은 입력 해치를 추가하고 인벤토리 크기를 늘려 대형 플랫폼의 건설 속도를 높이기 위해 최우선 순위가 부여되었습니다. 하지만 이는 (극히 드문 경우이긴 하나) 여전히 플랫폼을 교착 상태로 만들 수 있음을 의미합니다. 저희는 이것이 수용 가능한 타협점이라 생각했습니다. 이러한 변경으로 인해, 플랫폼에 충분한 보급품이 있더라도 모든 고스트 상태가 건설 요청에 다시 추가되며, 아직 건설되지 않은 개체의 아이템 요청도 포함됩니다.




이 재작업 과정에서 저는 시간을 내어 최소 화물 묶음 수 지정과 관련된 오래된 버그도 수정했습니다. 이제 이 기능이 예전만큼 꼭 필요하지는 않겠지만, 사용한다면 기대하는 방식에 훨씬 더 가깝게 작동할 것입니다. 로켓은 가능한 한 많은 아이템을 요청하며, 요청된 양이나 물류 네트워크에 있는 양 중 더 적은 쪽으로 한도가 제한됩니다. 최소 화물량이 채워지고 더 이상 아이템을 가져오기 위해 이동 중인 로봇이 없을 때, 즉시 로켓 발사를 시도할 것입니다. 심지어 '우주 시대'에서 모드가 활성화한 경우, 아이템을 궤도로 자동 발사하는 등의 모딩 관련 사례도 수정했는데, 이는 다음 주제로 이어집니다.



로켓의 모딩 지원 확장


어차피 로켓 물류 로직을 다시 작성하고 있었기 때문에, 이 주제에 관한 모딩 인터페이스 요청도 깊이 고려해보고 싶었습니다. 꽤 많은 모더들이 로켓의 탑재 중량 이 게임 전체의 글로벌 유틸리티 상수로 고정되어 있다는 점에 불만을 표했지만, 시스템을 대대적으로 뜯어고쳐야 했기에 그들의 요청은 "구현하지 않음"으로 거절되어 있었습니다. 지금이 이 문제를 다시 살펴볼 완벽한 타이밍이었습니다.


탑재 중량을 모드로 수정할 수 있게 만드는 것이 구현을 얼마나 복잡하게 만드는지 놀라울 정도였고, 저는 Rseding(개발자)가 이 요청을 거절했던 것이 옳았다고 믿게 되었습니다. 이 어려움이 혼합 로켓 시스템 때문에 가중된 것인지 아닌지는 확신할 수 없지만, 자동 로켓 배달에 또 다른 화물 최적화 변수가 추가되는 것이니 쉽지 않은 게 당연합니다. 그럼에도 불구하고 저는 기필코 이것을 구현하기로 결심했습니다.


최적의 스택 량을 계산하는 것은 기하급수적으로 더 어려워집니다. 왜냐하면 이제 아이템을 로켓에 최적으로 채워 넣는 것뿐만 아니라, 초과 배송되는 아이템을 최대한 줄이면서도 알맞은 크기의 로켓을 선택해야 하기 때문입니다. 저는 코드가 충분히 단순하게 유지되기를 바라며 최적의 솔루션을 향해 작업을 시작했지만, 한 가지 문제를 해결하자마자 또 다른 예외 상황을 발견했습니다. 더 복잡한 접근 방식이 성능에 미칠 악영향이 걱정되었기 때문에, 결국 대부분을 폐기하고 가장 단순한 방식을 선택했습니다. 새로운 로직은 이제 요청된 모든 아이템이 들어갈 수 있는 가장 작은 크기의 가용한 로켓을 선택합니다. 여러 개의 작은 로켓으로 화물을 쪼개는 것이 더 훌륭한 접근일 수도 있었겠지만요. 이것은 합리적인 타협이며, 나중에 누군가가 더 똑똑한 방법을 고안해 낸다면 그때 다시 조정할 수 있습니다.


이 기능의 또 다른 장애물이었던 아이템 툴팁에 명시된 로켓 용량에 대해서는 유틸리티 상수의 기본 용량을 참조하도록 유지하기로 결정했습니다. 이를 아이템 무게 자체로 표기하여 플레이어가 머릿속으로 로켓 용량을 계산하게 만드는 것은 사용자 지정 로켓 격납고가 많은 모드에는 더 좋았겠지만, '우주 시대' 본편에는 그다지 어울리지 않았습니다. 이 방식을 통해 '우주 시대'는 영향을 받지 않으며, 모더들은 자신들의 커스텀 탑재 중량을 이 기본값의 배수(multiplier)로 취급하여 사용할 수 있습니다.



탑재 중량이 증가된 모드의 로켓 격납고 툴팁 모습


마지막으로 자동 배달 로직이 혼합 로켓과 잘 어울리도록, 로켓 격납고의 인벤토리 크기가 동적으로 변하게 만들었습니다. 물리적으로나 원격 상호작용을 통해 새로운 아이템이 추가되거나 제거될 때, 인벤토리 슬롯은 자동으로 늘어나거나 줄어듭니다. 기존 모드가 완전히 사라진 것은 아닙니다. 모더들은 "무게 제한이 있고 슬롯이 무제한인 인벤토리"와 "무게 제한이 없고 슬롯이 제한된 인벤토리" 중 하나를 선택할 수 있습니다. 이 선택은 launch_to_space_platforms 프로토타입 매개변수와 연결되어 있습니다. 왜냐하면 자동 로켓 배달은 동적 크기의 인벤토리에서만 작동할 수 있기 때문입니다.



우주 플랫폼 개선 - Klonan


우주 플랫폼은 '우주 시대' 게임 플레이 물류의 중추적인 역할을 합니다. 지금도 잘 작동하고는 있지만, 저희는 2.1 개발 과정에서 몇 가지 개선 사항을 적용했습니다.



모든 행성에서 받기


궤도 요청은 아이템을 수입해 올 특정 행성을 지정할 수 있습니다. 플랫폼이 행성 간에 아이템을 실제로 이동시키려면(예: 불카누스에서 텅스텐을 집어와 나우비스에 내려놓기) 이것이 필수적입니다. 만약 물건을 가져올 행성에 필터가 없다면, 게임은 이 아이템을 도대체 어디에 내려놓는 것이 이치에 맞는지 알 방법이 없게 됩니다.


하지만 사실 기본적으로 모든 위치에서 아이템을 가져오고 싶거나, 최소한 아이템을 아무 행성에도 내려놓지 않게 막고 싶은 경우들이 존재한다는 것이 밝혀졌습니다. 가장 대표적인 예가 플랫폼 자체가 직접 소모하는 아이템들(핵연료 전지, 수리 팩 등)입니다.


물류 섹션을 여러 개 만들어서(각각 다른 위치에서 수입하도록 설정하여) 이를 구현하는 것도 어느 정도 가능하지만, 그건 너무 번거롭습니다. 대신, 커뮤니티에서 자주 제안했던 방식인 칸 비워두기를 구현했습니다. 이제 이 빈칸은 모든 행성에서 받음을 의미합니다.





쓰레기와 함께 출발 금지


이와 관련된 문제로, 특정 행성에서 쓰레기를 버리도록 필터를 설정한 경우(예: 나우비스에 다 쓴 우라늄 연료 전지를 버리기), 플랫폼이 쓰레기 슬롯에 아이템을 그대로 남겨둔 채 출발해 버릴 가능성이 있었습니다. 이로 인해 일부 상황에서 원치 않는 문제가 발생하곤 했는데, 사실상 아이템이 아무 행성에나 무작위로 버려지는 셈이 되었죠.


그래서 플랫폼의 로직을 수정했습니다. 이제 플랫폼은 현재 위치를 떠나기 전에 쓰레기 슬롯을 모두 비울 때까지 기다립니다 (버릴 수 있는 지표면이 해당 위치에 존재한다면 말이죠).




물론 이 기능은 수동으로 쓰레기통에 넣은 모든 아이템에도 적용됩니다. 따라서 건설 로봇을 기다리거나 하는 와중에 우주선이 마음대로 훌쩍 떠나버리는 일은 없을 것입니다.


또한 스크린샷에서 폐기 슬롯 패널 옆에 새롭게 추가된 다이오드를 눈치채실 수 있습니다. 마우스를 올려보면 "아이템 낙하 쿨다운 대기 중"이나 "모든 지상 스테이션이 바쁨"과 같은 낙하 로직의 상세 상태를 보여줍니다.



플랫폼 간 전송


아까 전 스크린샷에서 약간 의심스러운 부분을 발견하셨을지도 모릅니다. "왜 이 플랫폼은 얼음/탄소/황을 수입하고 있지? 엄청나게 비효율적이고 요청과도 다르지 않나?"


맞습니다! 우리가 2.0 버전을 플레이하고 있었다면 당신의 말이 전적으로 옳습니다.

하지만 2.1부터는 플랫폼이 다른 우주 플랫폼과 아이템을 송수신할 수 있는 기능이 추가됩니다!




요청 설정 시, 해당 필터가 어디로부터 아이템 배달을 요청할지 지정할 수 있습니다:


  - Planet (행성) - 해당 행성의 로켓 격납고에서 배달을 요청합니다.

  - Platforms (플랫폼) - 해당 행성의 궤도를 돌고 있는 다른 우주 플랫폼에서 배달을 요청합니다.

  - All (모두) - 행성과 우주 플랫폼 양쪽 모두에서 배달을 요청합니다.


예상치 못한 아이템 전송을 막고 이 새로운 기능의 발견을 돕기 위해, 각 플랫폼에는 다른 플랫폼에 아이템을 제공할지 여부를 지정하는 체크박스가 추가되었습니다.




물론 이 기능은 다음과 같은 완전히 새로운 가능성의 길을 열어줍니다:


  - 더 빠른 수송선 회전을 위해 궤도에 '버퍼 플랫폼'을 구성

  - 얼음/탄소/철광석 등의 초기 자원을 다른 플랫폼에서 공급해줌으로써 대형 플랫폼을 더 빠르게 시동/건설

  - 표면에서 쏘는 로켓 발사 비용을 아끼기 위해 궤도 상에서 우주 자재(우주 플랫폼 기반 등) 조립하기

  - 그리고 그 밖에도 무수히 많은 것들...



허브 요청 설정


회로 네트워크를 통한 진정한 자동화가 없다면 팩토리오의 온전한 기능이라 할 수 없죠. 이전에 저희가 회로 요청 기능을 추가하지 않았던 이유 중 하나는, 신호를 받았을 때 어느 행성에서 수입할지를 명시할 방법이 없었기 때문이며, 이를 시스템으로 구현하기에 꽤 어색해 보였기 때문입니다.


하지만 이제 우리에겐 '모든 위치에서 수입' 기능이 생겼습니다. 그래서 저희는 "회로 요청은 모든 위치에서 수입한다" 라고 정의함으로써 디자인을 깔끔하고 직관적으로 유지할 수 있게 되었습니다. 또한 회로를 통한 요청은 '모든' 출처(행성 및 플랫폼 모두)로부터 아이템을 요청합니다.



회로 네트워크 신호의 약간 마법 같은 '자기 차감' 로직 덕분에, '내용물 읽기'와 '요청 설정'을 동시에 사용하는 것도 가능합니다.



레이더 - 우주 모드


이 모든 요소들이 하나로 연결되려면, 플랫폼과 행성 간에 신호를 주고받을 방법이 필요합니다. 이 기능이 기존의 레이더 회로 연결의 확장 형태로 들어가는 것은 너무나도 자연스러운 수순입니다:




이제 채널(신호 ID)을 지정할 수 있으며, 동일한 우주 채널로 설정된 모든 레이더는 위치에 상관없이 서로 신호를 송수신하게 됩니다. 플랫폼 위에서는 채널을 현재 위치를 기준으로 필터링하여 부족한 행성의 자원이나 사용 가능한 화물량을 파악할 수 있고, 우주 함대를 제어하고 지휘하기 위해 여러분이 원하는 어떤 논리든 자유롭게 구현할 수 있습니다.


역) ????진심?????????


이 모든 기능이 결합되어 2.1 버전의 우주 물류는 훨씬 더 강력해집니다. 아, 그리고 한 가지 더 있습니다...



새로운 로켓 격납고 애니메이션


2.1 업데이트의 일환으로 저희는 그래픽을 마지막으로 다듬는 작업을 진행 중입니다. 이 멋진 결과물을 감상하실 준비를 하세요. 앞으로 더 많은 것들이 준비되어 있습니다.


Zsolti가 그래픽을, Ian이 사운드를 담당


이제 격납고 내부가 제작 중일 때 시각적으로 훨씬 명확해졌으며, 우측 상단에 로봇들이 아이템을 넣고 뺄 수 있는 작고 귀여운 해치를 추가했습니다.


늘 그렇듯, 여러분의 다양한 생각이라는 화물을 평소 이용하시는 공간(포럼, 레딧 등)에 섞어서 보내주세요!