확장팩 FFF 모음 정리 링크



에란델이 fff에 나온다 = 번역할 문장이 존나 많아진다....

큰거없음


적 스포 안당하려고 지난주 FFF거른사람 이번것도 거르셈

그리고 거미 진짜 혐오하는 사람은 볼때 주의하셈 좀 징그러움



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


FFF #425 - 다리 뒤에 숨은 이야기

게시자 StrangePan, Earendel

2024-08-23



안녕하세요,

펜타포드를 위해 길을 터주세요!


지난 주(FFF-424) 팩토리오에 완전히 새로운 두 가지 적, 스톰퍼와 스트레이퍼가 등장한다고 발표했었죠. 이번 주에는 이 사랑스러운 몬스터에 생명을 불어넣은 몇 가지 기능, 시스템, 최적화에 대한 비하인드 스토리를 소개해드리겠습니다. 또한 지난 주 FFF를 준비하기 위해 사용한 기술에 대해서도 이야기할 예정입니다. 다뤄야 할 내용이 많으니 바로 들어가 보겠습니다.





최적화부터 시작하기 - StrangePan


처음부터 우리는 펜타포드가 스파이더트론 다리를 구동하는 코드를 재사용하기를 원했지만 스파이더트론에 성능적인 문제가 있다는 사실도 알고 있었습니다. 이 문제를 해결하지 못하면 펜타포드를 팩토리오에 추가하는 것이 오히려 UPS에 해가 될 수 있었습니다. 일반적으로 개발보다 최적화를 먼저 하는건 좋지 않은 생각이지만, 펜타포드에 생명을 불어넣기 위해서는 먼저 스파이더트론을 최적화해야 했기 때문에 선택의 여지가 거의 없었습니다.




작업 중복 제거


스파이더트론의 가장 명백한 성능 문제는 장애물을 통과할 때 발생했습니다. 1.1에서는 스파이더트론 분대에게 넓은 강을 건너라고 명령하면 속도가 눈에 띄게 느려지는 것을 확인할 수 있습니다. 일부 세이브 파일에서는 겨우 10마리 정도의 스파이더트론 만으로도 UPS에 영향을 미칠 수 있었습니다.


제가 발견한 첫 번째 원인은 각 다리를 배치할 빈 공간을 검색하는 알고리즘이었습니다. 1.1에서 알고리즘은 바깥쪽으로 나선형으로 스캔하여 최대 16x16 타일의 영역에서 타일의 1/5마다 해당 위치의 타일(예: 물) 또는 개체와의 충돌 여부를 확인합니다. 빈 공간이 없는 최악의 경우, 이 알고리즘은 약 6400회의 충돌 검사를 수행합니다((8 [타일 반경] × 2 ÷ 0.2 [검사 간 간격])²).



스파이더트론의 다리가 충돌 여부를 확인하는 모든 위치. 이 예시에서는 1600번의 검사를 보여주지만, 이는 최악의 경우도 아닙니다.

또한 스파이더트론의 모든 다리가 매 틱마다 이 검사를 수행한다는 사실은 설명되지 않았습니다.



이 문제를 해결하기 위한 비결은 스캔 정밀도가 매우 세밀하다는 것을 깨닫는 것이었습니다(0.2타일). 타일은 이 크기의 5배이고 대부분의 엔티티는 이 크기의 10배 이상입니다. 따라서 알고리즘은 종종 동일한 타일이나 엔티티를 반복해서 확인합니다. 대신 알고리즘이 충돌을 발견하면 즉시 충돌한 바닥의 가장자리를 지나서 안쪽으로 진행해야 합니다. 모든 충돌 가능한 바닥의 바운딩 박스를 기억한다면 전체 행과 열을 스캔하는 것을 건너뛸 수도 있습니다.





스파이더트론의 다리는 이제 훨씬 적은 수의 위치를 검사합니다. 이 예시에서는 약 70회의 충돌 검사를 하는 걸 보여줍니다.

또한 나선형에 비해 더 나은 결과를 생성하는 새로운 스캔 패턴에 주목하세요.



이 변경만으로도 스파이더트론의 성능이 크게 향상되었지만, 아직 작업이 끝나지 않았습니다. 펜타포드가 실현되려면 더 많은 컴퓨팅 사이클을 확보해야 했습니다.





공유된 지식이 곧 힘


두 번째 성능 저하의 원인은 그룹의 모든 스파이더트론 다리가 거의 동일한 영역에서 동일한 빈 공간 탐색을 수행한다는 점입니다. 각 다리가 충돌 확인 횟수를 줄이더라도 근처에 있는 여러 다리가 이 작업을 중복해서 수행했습니다. 그러면 자연스럽게 거미 다리가 함께 작동하여 더 적은 수의 검색을 수행할 수 있을까 하는 의문이 생깁니다.


이 문제를 해결하는 비결은 알고리즘이 첫 번째 빈 공간이 발견될 때까지 중앙에서 바깥쪽으로 스캔한다는 사실을 깨닫는 것이었습니다. 즉, 검색 원점에서 몇 타일 떨어진 빈 위치를 찾으면 안쪽 사각형이 완전히 차단된다는 것을 알 수 있습니다. 이 안쪽 사각형을 '검색 제외 영역'으로 표시하고 목록에 넣으면 향후 다리 빈 자리 검색에서 해당 목록을 확인하고 해당 영역에 속하는 충돌 검사를 건너뛸 수 있습니다.



한 영역에서 빈 공간을 검색하면 해당 영역은 나머지 틱 동안 '검색 제외 영역'으로 기록됩니다. 다른 스파이더트론 다리는 빈 공간을 검색할 때 이 영역의 검사를 건너뛰게 됩니다.



솔직히 저는 이 기능이 성능면에 영향을 크게 미칠 거라는 기대가 거의 없었습니다. 구현이 매우 단순하고 제외 영역은 추가된 틱에 대해서만 유효하기 때문입니다. 하지만 놀랍게도 이 작은 해킹으로 시간이 엄청나게 단축되었습니다! 몇 가지 조정과 기타 최적화를 거쳐 이제 펜타포드를 구현할 수 있게 되었고 확장팩에 추가할 수 있게 되었습니다.







새로운 걷기 알고리즘


마지막으로 살펴볼 성능 저하의 원인은 어떤 스파이더트론 다리를 움직일지 선택하는 알고리즘과 관련이 있습니다. 빈 공간 탐색 알고리즘을 개선했음에도 불구하고 여전히 눈에 띄는 비효율성이 있었습니다. 이미 움직이고 있거나 움직이는 이웃을 기다리고 있는 모든 다리가 스파이더트론이 걷고 있는 동안 매 틱마다 빈 공간을 탐색하고 있었죠. 각 다리는 얼마나 멀리 이동해야 하는지에 따라 점수를 부여받았고, 가장 높은 점수를 받은 다리 하나만 움직이도록 선택되었습니다. 해당 다리가 이미 움직이느라 바쁘면 결과는 그냥 버려졌습니다.


물론 이로 인해 낭비되는 검색이 많았지만 스파이더트론이 항상 목적지를 향해 나아갈 수 있도록 해야 했습니다. 이 점수 시스템이 없으면 큰 발걸음을 내딛어야 하는 다리가 옆의 다리 또는 양쪽 다리가 작은 발걸음을 반복하느라 바쁘기 때문에 종종 막히게 됩니다. 모든 다리가 동등하게 움직일 수 있는 기회를 보장하는 효율적인 방법이 필요했습니다.


이 문제에 대한 해결책은 펜타포드 개발 초기 몇 달 후에 나왔습니다. 다리가 다섯 개인 펜타포드가 추가되었을 때, 다리의 점수를 매기고 움직이는 기존 알고리즘은 더 이상 적합하지 않았습니다. Earendel은 이 외계 생명체에 독특하고 유기적인 보행 패턴을 부여하기 위해 다리가 움직이는 순서를 완벽하게 제어하기를 원했습니다. 이를 통해 스파이더트론의 보행 알고리즘을 점검하고 마지막 주요 최적화를 구현할 수 있었습니다.


다리가 다섯 개인 생물체는 어떻게 걸어야 할까요? 지구상에는 그 예가 많지 않지만, Earendel은 그래도 좋은 디자인을 생각해 냈습니다. 균형과 안정성을 유지하기 위해 펜타포드는 별 모양으로 발걸음을 옮깁니다.



1그룹의 모든 다리가 스텝을 마치면 2그룹의 다리가 스텝을 시작할 수 있습니다. 이후에는 3그룹, 4그룹, 5그룹 순으로 진행합니다.

하지만 일부 펜타포드는 거꾸로 세는 것을 선호합니다.



이를 구현하기 위해 펜타포드 또는 스파이더트론의 모든 다리에는 번호가 매겨진 '걷기 그룹'이 할당됩니다. 걸을 때 현재 걷기 그룹에서 하나 이상의 다리가 선택되어 움직입니다. 이렇게 선택된 다리는 명확한 목적지를 검색한 다음 그곳으로 이동하기 시작합니다. 더 이상 낭비되는 검색은 없습니다. 현재 걷기 그룹의 모든 다리가 보행을 완료하면(또는 적어도 오늘 여기서는 다루지 못할 특정 임계값을 지나면) 다음 걷기 그룹에 대해 프로세스가 반복됩니다. 이 새로운 시스템은 충돌 검사 횟수를 크게 줄이면서 디자이너가 스파이더트론과 펜타포드 걷기 애니메이션을 전례 없이 제어할 수 있게 해줍니다.


이 세 가지 대규모 최적화와 미처 다 하지 못한 몇 가지 소규모 최적화를 거친 스파이더트론은 이제 UPS의 부담을 훨씬 덜 수 있게 되었습니다. 스파이더트론의 이동성을 강조하기 위해 설계된 테스트 세이브 파일에서, 업데이트당 평균 53.56%(약 2.15배 빨라짐)의 밀리초 단축을 측정했습니다(). 따라서 팩토리오 2.0에서는 이제 플레이어가 더 많은 스파이더트론 군대를 지휘해도 UPS가 소멸되지 않습니다(결과는 달라질 수 있습니다).









새로운 적, 새로운 기능 - StrangePan


새로운 적과 함께 새로운 매커니즘도 등장합니다! 그리고 새로운 매커니즘에는 새로운 엔진 기능도 있습니다. 이제 펜타포드 디자인에 영향을 준 게임 디자인 결정과 이를 구현하기 위해 구축한 시스템 변경 사항에 대해 알아보겠습니다.



장애물을 뛰어넘는 경로 찾기


저희는 글레바 행성의 공장을 벽으로 둘러싸는 것이 게임플레이에 방해가 될 것이라는 사실을 일찍부터 알고 있었습니다. 그래서 저희는 허술한 벽에 신경 쓰지 않는 적을 설계했습니다. 대신 플레이어는 강력한 화력과 새로운 로켓 포탑으로 펜타포드 공격을 방어해야 합니다.


이를 위해서는 틈새를 지원하고 장애물을 무시한 경로를 생성하는 길찾기 시스템이 필요했습니다. 다행히도 기존 바이터 경로 찾기 시스템(FFF-317)에 몇 가지 새로운 기능을 추가하여 확장할 수 있었습니다.


청크 단위 수준 경로 탐색을 수행할 때 청크의 경계에 닿는 이동 가능한 타일만 기록하는 것만으로는 더 이상 충분하지 않습니다. 또한 청크의 둘레를 따라 이동할 수 없는 타일은 가장 가까운 이동 가능한 타일(최대 2개의 서로 다른 구성 요소)까지의 거리를 기록해야 합니다. 나중에 이 정보를 사용하여 청크 사이에 여러 컴포넌트를 연결합니다.


두 타일 사이의 거리는 델타-X 또는 델타-Y 중 더 큰 값으로 계산됩니다.




청크 내의 이동 가능한 타일은 거리가 최대 허용 간격보다 작은 경우 함께 그룹화됩니다. 각 청크의 테두리를 따라 있는 타일은 청크 내에서 가장 가까운 이동 가능한 타일까지의 거리를 기억합니다.

(참고: 이 스크린샷에는 둘 이상의 컴포넌트 범위 내에 있는 모서리 타일의 예시는 표시되지 않았습니다.) .



다음으로, 기본(타일 수준) 경로 찾기를 수행할 때 모든 노드는 횡단이 가능한지 여부를 기억하고 항상 마지막으로 알려진 횡단이 가능한 노드를 가리켜야 합니다. 이를 통해 알고리즘은 횡단이 불가능한 영역(물, 벽 및 기타 개체)을 더 깊이 스캔하여 바이터가 횡단할 수 없는 경로를 찾을 수 있습니다.




노드는 횡단할 수 없는 지형에서 일정 거리를 검색하며, 항상 마지막으로 알려진 횡단 가능한 타일을 가리킵니다. 일반적인 경로 탐색은 이 그림보다 훨씬 더 많은 노드를 검색합니다.



현재 기본 게임에서는 불연속 경로 탐색을 지원하지 않지만, 팩토리오 2.0의 모딩 API를 통해 불연속 경로 탐색을 사용할 수 있게 됩니다.






공중에 떠다니는 포자


이제 벽으로 펜타포드를 막을 수 없으니 플레이어에게는 또 다른 문제가 생겼습니다. 펜타포드가 어느 방향에서든 공장의 모든 부분을 공격할 수 있다는 것입니다! 엔지니어가 할 수 있는 일은 더 많은 포탑과 무기로 공장을 포위하는 것 말고는 무엇일까요? 이는 플레이어가 원하는 전략이 아니었기 때문에 저희는 이 전략을 불필요하게 만들어야 했습니다. 이를 위해 글레바에서 공해가 작동하는 방식을 변경했습니다.


적 유닛(바이터와 펜타포드 모두)은 일반적으로 오염도에 따라 공격 대상을 선택합니다. 공격 파티가 구성되면 국지적으로 오염도가 가장 높은 가장 가까운 청크를 향해 이동하여 해당 청크에서 오염을 방출하는 개체를 공격합니다.


공해는 다른 행성과 달리 글레바에서는 다르게 작동합니다. 나우비스에서 오염을 많이 배출하는 일부 기계는 글레바에서 오염을 배출하지 않는 반면, 글레바에서 오염을 많이 배출하는 기계는 나우비스에서 오염을 배출하지 않습니다. 바이터의 동작 원리를 변경하지 않고 펜타포드가 공장의 특정 부분에 우선순위를 두도록 하려면 어떻게 해야 하나요?


팩토리오 2.0에는 오염 물질 유형이 도입되었습니다. 모드를 통해 다양한 유형의 오염 물질을 추가할 수 있습니다. 기계, 식물, 스포너, 타일은 각각 다른 양의 오염 물질을 방출하거나 흡수하도록 구성할 수 있습니다. 그러나 게임 성능상의 이유로 표면당 하나의 오염 물질 유형만 활성화할 수 있습니다. "공해"는 오염이 활성화된 신규 및 기존 표면의 기본 오염 물질 유형입니다. 팩토리오: 우주 시대 DLC에서는 포자가 글레바의 공해를 대체합니다. 각 오염 물질 유형은 고유한 이름, 흡수 및 방출 속도, 표에 나타나는 색상 등을 가질 수 있습니다.


이 새로운 도구로 무장하여 펜타포드가 공장의 대부분은 기능적으로 무시하면서 몇 개의 특정 건물에 공격력을 집중하도록 글레바를 조정할 수 있었습니다. 어음, 여러분이 도발하지 않는다면 말입니다.







재설계된 다리


마지막으로 펜타포드 다리에도 재작업이 필요했습니다. 유기적인 생명체이기 때문에 각 다리가 펴지거나 구부러지는 정도를 최소화하고 대신 무릎과 엉덩이의 구부러짐을 강조하고 싶었습니다. 이렇게 하면 몬스터의 모양과 느낌이 더 사실적이고 로봇처럼 느껴지지 않습니다.


심지어 다리는 몸체에 대한 방향에 따라 스프라이트가 업데이트되도록 만들었습니다. 팩토리오의 시점과 이상한 각도 때문에 이 작업을 제대로 하기가 어려웠지만, Fearghall과 Earendel은 놀라운 작업을 해냈습니다. 최종적으로 완성된 모습은 조명 각도를 일관되게 유지하고 플레이어의 시점을 항상 고려함으로써 이 생물들이 더욱 사실적으로 느껴지도록 만들었습니다.



스톰퍼와 스트레이퍼는 다리를 뻗기 전에 엉덩이와 무릎을 구부립니다. 방향에 따라 스프라이트가 바뀝니다.



스파이더트론과 펜타포드는 많은 코드를 공유하기 때문에 이제 스파이더트론도 약간 새로운 모습을 갖게 되었습니다. 다리가 덜 뻣뻣하고, 더 구부러지고, 솔직히 조금 더 소름 끼치기도 합니다. 여전히 로봇이 분명하기 때문에 상징적인 모습은 그대로 유지하면서 약간의 변화를 주었다고 생각합니다.




왼쪽: 1.1의 스파이더트론 걷기 애니메이션. 

오른쪽: 2.0의 스파이더트론 걷기 애니메이션.










비하인드 스토리 - Earendel


이번 주 FFF를 위해 무엇을 할까 고민하다가 지난번 FFF를 만들 때 제가 농담을 던졌어요. 사람들이 그 아이디어를 정말 좋아하는 것 같아서 여기까지 왔습니다.


팬들은 비하인드 스토리를 보는 것을 좋아하니 당연한 일이죠. 영상이 어떻게 제작되는지 보여주는 것은 게임의 비밀을 공개하지 않고도 비하인드 스토리 콘텐츠를 보여줄 수 있는 좋은 방법입니다.


대부분의 FFF는 (이번 영상처럼) 이게 나오는 해당 주에 제작됩니다. 보통 저는 일주일 전에 미리 작업을 끝내려고 하는데, 그렇게 하면 스트레스가 덜하거든요. 하지만 적 FFF의 경우 제작 과정에서 모든 '미지의 요소'를 제거하기 위해 몇 주 전부터 작업을 시작했습니다.


무작위로 생성된 지형 중 일부를 '전투 경기장'으로 삼아 적을 배치하고 시나리오로 내보냈습니다(누구나 맵 에디터에서 할 수 있는 것과 같은 방식).


이전 동영상에서 캐릭터 달리기 및 탱크 컨트롤(회전, 가속 등)에 대한 플레이어 입력을 캡처하는 퍼포먼스 캡처 코드가 이미 있었습니다. 이 시스템을 확장하여 플레이어의 무기 입력(주로 어떤 무기를 선택했는지, 발사했는지 여부, 목표 위치 등)도 캡처했습니다.


캐릭터 장비는 다음과 같습니다. 무기 공격력 업그레이드는 8레벨까지 진행했습니다.





아레나에서 적과 싸우는 연기를 녹음한 다음 그 연기를 시나리오에 다시 적용하고 다시 실행했더니... 다르게 진행되었습니다.


플레이어의 입력은 모두 같았지만 적들은 같은 행동을 하지 않았죠. 일부는 다른 위치로 돌아다니며 다른 시간에 공격했습니다. 원래 캡처한 버전에서는 맵에 스트레이퍼가 한 마리 있었고 알 덩어리가 파괴되기 직전에 다른 스트레이퍼가 생성되었습니다. 스크립트로 제어하는 캐릭터가 있는 버전에서는 두 번째 스트레이퍼가 생성되는 대신 추가 리글러가 생성되었습니다. 스톰퍼는 어떤 이유에서인지 훨씬 일찍 전투에 참여했습니다. 캐릭터는 서로 다른 타이밍에 부딪히는 날아다니는 리글러로 인해 속도가 느려져 움직임이 궤도를 벗어났고 결국 나무에 부딪혀서 빠르게 밟혀 죽었습니다.


그래서 이상적인 시작은 아니었습니다. 시나리오를 다시 실행하면 적어도 캐릭터가 발로 밟히는 장면이 똑같이 나오기 때문에 적어도 매번 전체 결과를 다시 롤링하지는 않습니다. 저는 시나리오의 결과를 무작위로 만들거나 만들지 않는 원인이 정확히 무엇인지 알아내기 시작했습니다.


몇 가지 테스트 끝에 시나리오가 입력된 녹화와 같은 방식으로 재생되도록 하는 것은 불가능하다는 것을 깨달았습니다. 왜냐하면 녹화 코드와 애플리케이션 코드 자체만으로도 결과를 변경할 수 있고 이를 해결할 방법이 없기 때문입니다. 약간 성가시긴 하지만 어차피 경기장 주변 환경이 많이 바뀔 것이라는 것을 알았기 때문에 큰 문제는 아니었습니다. 새로운 시뮬레이션을 더 안정적으로 유지하기 위해 더 안정적인 다른 도구를 추가하는 것이 가장 합리적이라고 생각했습니다.


가장 큰 문제는 플레이어가 궤도를 벗어나는 것이었습니다. 날아오는 리글러에 부딪히면 움직임이 느려지기 때문에 이런 일이 쉽게 일어날 수 있었습니다. 날아오는 리글러를 피할 때는 아슬아슬한 순간이 많기 때문에 많은 변수가 생깁니다. 플레이어의 움직임에 변화가 생기면 적의 이동 방향에도 영향을 미치기 때문에 전투가 예상치 못한 방향으로 흘러갈 수 있습니다.






맵이 완성되면서 일부 새로운 지형 에셋이 추가되었지만, 이로 인해 적의 행동이 '리롤'되어 캐릭터의 속도가 느려지고 모든 것이 다르게 진행되어 캐릭터의 최종 경로가 매우 다르게 보입니다.

왼쪽: 원래 이동 경로. 

오른쪽: 키 입력은 동일하지만 속도가 다른 이동 경로.



이 문제를 해결하기 위해 저는 캐릭터가 의도한 경로에서 얼마나 멀리 떨어져 있는지 측정하고, 너무 멀리 벗어나면 이를 수정하기 위해 강제로 한 방향으로 달리도록 했습니다. 여전히 어떤 효과로 인해 속도가 느려지지만, 코너를 돌거나 회피 동작을 건너뛰고 다시 궤도로 돌아올 수 있습니다.


이런 식으로 플레이어의 움직임을 추적하면서 카메라 시스템을 교체할 수 있는 좋은 방법도 얻었습니다. 카메라가 풍경 위를 부드럽게 패닝하는 이전 영상과 달리 이 영상은 캐릭터의 불규칙한 움직임을 따라갑니다. 카메라 움직임을 위한 기존의 베지어 제어 포인트 시스템은 캐릭터의 움직임을 맞추기에는 악몽과도 같았고, 특히 재녹화가 필요한 경우 거의 확실하게 재녹화가 이루어졌습니다.


새로운 시스템은 퍼포먼스 캡처에서 기록된 캐릭터 위치를 가져와 릴랙스 필터를 몇 번 통과시켜 해당 경로를 부드럽게 처리하여 각 지점을 전후의 평균으로 만듭니다.



흰색 : 실제 캐릭터 움직임. 

파란색 : 카메라의 부드러운 경로.



이렇게 하면 카메라 움직임이 부드러워지지만 항상 캐릭터 중심으로 움직이기 때문에 액션을 잘 따라가지 못합니다. 그래서 가상의 지점이 목표한 적에게 이동하고 카메라가 부드러워진 경로와 보조 목표 지점 사이에 몇 %를 유지하도록 하는 보조 목표 시스템을 추가했습니다. 이 시스템은 적 자체가 아닌 가상의 점을 사용하므로 적이 죽고 새로운 목표가 선택되면 카메라가 갑자기 점프하지 않고 가상의 점이 제한된 속도로 새로운 목표물로 이동합니다. 추가 제어 계층을 통해 카메라가 두 번째 타겟으로 얼마나 강하게 당겨지는지 결정할 수 있습니다. 동영상이 시작될 때 두 번째 타겟은 알 덩어리이지만 영향력은 0으로 설정되어 있습니다.



모든 디버그 데이터 활성화

파란색 : 평탄화된 기본 카메라 경로

주황색 : 보조 타깃 경로

흰색 : 실제 카메라 결과

보라색 사각형 : 카메라 범위 경계



전투의 모든 동작이 음악에 맞춰 춤을 추듯 이루어지기 때문에 모든 위치와 타이밍이 평소보다 더 중요합니다. 알 덩어리는 비트가 시작되기 직전에 파괴됩니다. 스트레이퍼는 우울한 톤이 나오고 음악이 조금 더 불안정하게 들리기 시작하면 죽습니다. 그리고 스톰퍼도 특정 시간에 죽어야 합니다(자세한 내용은 나중에 설명합니다).


그 과정에서 무엇이 시나리오 결과를 바꾸고 적들이 어떻게 영향을 받는지 알게 되었습니다.


적들은 아무것도 바뀌지 않는 한 일관되게 행동합니다. 그래픽을 교체하는 것은 괜찮지만 물체의 위치는 변경할 수 없습니다. 적을 이동하거나, 나무를 추가하거나 제거하거나, 타일을 변경하거나, 캐릭터에 탄약을 추가하거나, 장식을 추가하는 등의 모든 작업은 결과를 망가뜨립니다. 이외에도 다양한 방식으로 깨질 수 있습니다.


스포너(알 덩어리)가 유닛을 생성하거나 생성하지 않을 수도 있고, 생성하더라도 다른 유형의 유닛이 생성될 수도 있습니다. 한 번은 무작위로 스톰퍼를 생성해서 스톰퍼가 2마리가 나온 적이 있습니다. 좋지 않은 일이었습니다. 이 시나리오는 동영상용 시나리오 세트가 포함된 모드의 일부이므로 이 문제를 해결하기 위해 스포너가 리글러만 스폰할 수 있도록 시나리오 모드를 업데이트했습니다.


펜타포드는 임의의 방향으로 돌아다닐 수 있기 때문에 전투가 시작되면 "어그로" 범위에서 벗어나 전투에 나타나지 않을 수도 있습니다.


카메라 시야에 들어오기 직전에 적을 정확한 위치로 순간이동시키려고 했지만, 다리가 긴 적을 순간이동시킬 수 없고 1프레임 만에 고무줄처럼 이전 위치로 되돌아간다는 것을 금방 알 수 있었습니다.


대신 카메라 뷰에 나타나기 직전에 LUA 스크립트를 통해 펜타포드를 올바른 위치에 스폰해야 했습니다. 이렇게 하면 위치가 더 일관되게 유지되었습니다. 하지만...


스크립트로 생성된 다리가 긴 펜타포드는 왼쪽 또는 오른쪽으로 공격할 확률이 50대 50으로, 즉 임의의 방향으로 공격할 확률이 높았습니다. 다른 것들과 마찬가지로, 방향은 변하지 않는 한 일관성이 있었습니다. 방향이 전투에 많은 영향을 미치기 때문에 가장 난감한 문제였습니다. 이에 대한 훌륭한 해결책은 없었지만, 다리가 3개인 적의 좌우 조합 결과는 8가지에 불과하지만 실제로 가장 중요한 방향은 첫 번째 스트레이퍼입니다. 다른 일관성 안전망을 사용하면 첫 번째 스트레이퍼가 제가 원하는 방향으로 다시 굴러갈 때까지 시작 위치를 미세하게 조정하여 일관된 방향을 갖도록 하는 것으로 충분했습니다.


시나리오 시뮬레이션 결과가 엉망이 되는 최악의 상황을 발견한 것은 훨씬 후에야였습니다: 스크린샷을 저장하기 위해 카메라 스크립트 코드를 미리보기 모드에서 렌더링 모드로 변경하는 것만으로도 시나리오 결과물이 망가질 수 있다는 사실을 알게 된 것이죠. 즉, 미리 보기에 표시된 대로 작동하지 않아서 미리 보는 데 들인 모든 시간이 무용지물이 된 것입니다. 처음 몇 번은 렌더링 결과가 눈에 띄게 달라지지 않았기 때문에 이 문제를 바로 알아차리지 못했지만, 어느 순간부터 큰 문제가 되었습니다. 다행히 렌더링을 항상 켜두되 캡처 크기를 1픽셀씩 1픽셀로 줄이면 파일은 여전히 저장되지만 크기가 너무 작아서 미리보기용으로 충분할 정도로 매우 빠르다는 것을 알게 되었습니다.


무기 입력 캡처에는 발사 시간, 발사 위치, 사용할 총이 기록됩니다. 리글러의 경우 조준 보조가 주변 적을 선택하므로 부정확해도 괜찮습니다. 하지만 로켓 대 스트레이퍼의 경우 위치가 너무 잘못되어 로켓이 보통 리글러를 조준하거나 전혀 발사되지 않는 경우가 많았고, 아주 가끔씩만 의도한 대상을 공격하는 경우가 있었습니다. 이 문제를 해결하기 위해 입력 데이터를 편집하여 모든 로켓 발사를 제거하고 대신 이벤트 시스템을 사용하여 스트레이퍼에게 직접 로켓을 발사하고, 스트레이퍼가 범위 내에 있는지 확인하기 위해 시간을 쉽게 변경할 수 있는 방식으로 로켓을 발사했습니다.


화염방사기에는 목표물 고정 기능이 없지만, 처음 사용했을 때는 리글러를 상대로 항상 잘 작동했습니다. 전투가 시작될 무렵이라 더 일관성이 있고, 어쨌든 모두 불타 죽거든요. 마지막으로 스톰퍼를 상대할 때 스톰퍼의 위치가 매우 불안정했습니다. 항상 캐릭터 근처 어딘가에 있었지만 각도는 어느 방향이든 될 수 있었습니다. 원래 위치를 기준으로 발사하면 불꽃이 무작위적인 방향으로 향하기 때문에 대부분의 경우 매우 부정확해 보였습니다. 일단 화염 댄스가 시작되면 좁은 영역에 머물면서 원을 그리며 화염을 퍼뜨리는 것이 더 합리적이기 때문에 일관성이 생겼습니다. 이 시퀀스의 시작 부분을 수정하기 위해 처음 2초 동안 화염방사기가 스톰퍼의 위치를 조준한 다음 다시 캡처된 입력으로 전환하도록 스크립트를 추가했습니다. 약간의 연기와 거울만 있으면 됩니다.


다음 문제는 마지막 스톰퍼가 죽는 타이밍입니다. 스톰퍼는 음악이 끝나기 전에 죽어야 하지만, 그 전에는 몇 초 동안 아무 일도 일어나지 않아야 합니다. 알 덩어리의 경우 정확한 타이밍에 쏘기만 하면 됩니다. 스트레이퍼는 로켓 타이밍에 따라 다르고 간혹 사거리를 벗어나는 경우가 있지만 몇 초 늦어지는건 괜찮습니다. 스톰퍼의 경우 사망 시간을 제어하기가 정말 어렵습니다. 퍼포먼스 캡처에서는 (약간의 연습을 통해) 타이밍을 정확히 맞출 수 있었지만, 실제 플레이에서는 항상 타이밍이 맞지 않습니다. 여분의 리글러가 방해가 되거나 화염방사기가 더 많이 빗나가기 때문에 보통 너무 늦습니다. 이 문제를 해결하는 마지막 방법은 생명력에 10배를 곱하고 스크립트를 사용하여 정확한 타이밍에 즉시 처치하는 것입니다. 어차피 생명력 막대는 숨겨져 있습니다. 그 시점에 가해지는 대략적인 피해량은 정확한 체력을 가지고 있다면 죽을 수 있는 정도이므로 잘못 보이지 않습니다. 사실 마지막에 화염방사기로 빙글빙글 돌기 위한 전략의 일부입니다. 피해를 입지 않으면서도 죽지 않도록 불이 어느 정도 피해를 입히도록 하는 것이죠.




https://cdn.factorio.com/assets/blog-sync/fff-425-combat-but-less-reliable.mp4

(역주 : 영상이 길어서 그냥 링크로 대체)


원래 전투 영상과 같은 장면이지만 적의 체력 표시줄을 표시했고 전투 시인성을 위해 낮으로 바꿔두었습니다.

스톰퍼의 사망 시간이 스크립트로 지정되어 있지 않아 이번에는 약간 너무 일찍 죽지만 재연출하면 너무 늦게 죽을 수도 있습니다.

이번에는 캐릭터가 살아남지만 항상 그런 것은 아닙니다.


마지막 문제는 캐릭터가 죽는 것입니다. 원작 공연에서는 끝까지 살아 남았지만 그 중 상당 부분은 회피와 관련이 있었습니다. 시나리오를 재생할 때 나무에 부딪히지 않더라도 캐릭터가 끝까지 살아남을 확률은 25%에 불과했는데, 이는 다른 곳에 있는 발을 피하고 때때로 피해로 직진하는 경우가 있었기 때문입니다. 이 문제는 갑옷이나 장비의 품질을 업그레이드하면 해결할 수 있었지만, 스크립트로 캐릭터의 체력을 유지하는 더 빠른 방법을 선택했습니다.


재미로 좀 더 큰 적을 만나면 어떻게 되는지 확인해 보겠습니다.



https://cdn.factorio.com/assets/blog-sync/fff-425-combat-but-medium.mp4

(역주 : 영상이 길어서 그냥 링크로 대체)


다시 같은 장면이지만 이번에는 적들이 더 진화했습니다. 조금 다르게 전개됩니다...









새로운 삶 만들기 - StrangePan


이 여정에 함께 해주셔서 감사합니다! 새로운 적을 만드는 데 무엇이 필요한지, 그리고 지난주 FFF와 같은 흥미로운 발표를 만들기 위해 어떤 노력이 필요한지 엿볼 수 있었기를 바랍니다.


저도 이제 다양한 적들이 등장하는 게임에 대해 더 큰 애정을 갖게 되었습니다. 기존 시스템을 기반으로 개발할 수 있다는 이점이 있었지만, 각 시스템의 기능, 한계, 단점, 버그를 파악한 다음 이를 어떻게 하면 잘 조합할 수 있을지 고민해야 했죠. 게임의 다른 부분이 깨지거나 불균형이 발생하지 않도록 각 변경 사항을 신중하게 테스트해야 했습니다. 그 과정에서 수많은 재작업, 정리, 버그 수정, 수많은 메모가 필요했습니다. 그럼에도 불구하고 이전 프로그래머들이 확장성, 성능 및 (때로는) 코드 상태를 염두에 두고 이러한 시스템을 구축한 것은 분명합니다.


어쨌든, 저는 이 소름 끼치는 기어다니는 모습은 평생 동안 충분히 본 것 같습니다. 글레바는 펜타포드에게 맡길게요. 그들이 가져도 돼요! 게다가 이제 불카누스 공장을 점검할 때가 됐어요. 거기서 많은 경고 알림을 받고 있는데, 주조소에 차질이 없기를 바랍니다...



항상 그렇듯이 안정적이고 반복적으로 일반적인 장소로 이동하여 지금과 같은 정확한 타이밍에 댓글을 달아주세요.