게임 개발 · 기술 동향미로의 개발노트
카테고리

Factorio · 시뮬레이션 최적화

Factorio의 벨트는 왜 아이템의 위치 대신 간격을 기억할까?

모아보기 · 작성 기준일 · 블로그 공개

아이템이 수백 개여도 서로의 간격이 그대로라면, 줄의 양 끝만 갱신할 수 있어요. 막혔을 때는 어떤 값이 바뀌는지 살펴봅니다.

빨간 선으로 운반 벨트의 연속 구간을 나눈 Factorio 개발진의 게임 화면
Factorio 개발 일지의 운반 벨트 구간 도식. 빨간 선은 연속 구간의 경계를 표시한다.

아이템 200개를 움직이는 데 숫자 200개가 필요할까요?

공장에 놓인 운반 벨트가 한 틱 전진합니다. 아이템마다 좌표를 가지고 있다면 200개를 전부 갱신해야 합니다. 하지만 같은 속도로 이동하고 서로 추월하지 않는다면, 이웃한 두 아이템 사이의 거리는 그대로입니다. Factorio 개발진은 0.15 최적화에서 연속된 벨트를 묶고, 줄 안의 아이템은 절대 좌표 대신 서로의 간격으로 저장했습니다. 줄 전체가 자유롭게 흐르는 동안에는 양끝의 여유만 바꾸면 됩니다.

벨트가 막히면 어디가 먼저 줄어들까요?

앞 아이템이 출구에서 멈춰도 뒤쪽 아이템은 그 앞에 공간이 남아 있는 동안 이동합니다. 이때 바뀌는 값은 출구 쪽에서 가장 가까운, 아직 남아 있는 간격입니다. 매 틱 뒤로 훑어 그 위치를 다시 찾으면 비용이 커집니다. 개발진은 그 간격의 위치를 기억했습니다. 외부에서 아이템을 끼워 넣는 경우를 제외하면, 이미 서로 맞닿은 아이템이 막힌 구간에서 저절로 벌어지지 않습니다. 덕분에 다음 간격을 찾아야 할 때 탐색 위치가 한쪽 방향으로만 움직입니다.

작은 모형으로 직접 비교하기

12칸짜리 줄에 아이템 네 개를 같은 방향으로 흘려보냅니다. 먼저 개별 좌표 배열을 만들고, 다음에는 아이템 간격과 양끝 여유를 저장합니다. 두 버전 모두 같은 위치에 아이템이 그려지는지 대조하면서 틱당 몇 개의 상태를 갱신했는지 세어 봅니다. 출구를 막고, 다시 열고, 중간에 아이템을 넣는 경우를 차례로 비교하면 간격 표현이 유리한 상황과 재계산이 필요한 상황이 드러납니다. 줄 사이 이동이나 합류가 잦으면 줄 내부의 갱신 비용을 줄여도 경계 처리 비용이 남습니다.

수치로 보면 무엇이 그대로일까요?

12칸짜리 모형에 아이템을 2, 5, 9 위치에 놓아 봐요. 이웃 아이템의 위치 차이는 3과 4입니다. 세 아이템이 모두 한 칸 움직여 3, 6, 10에 와도 두 차이는 그대로입니다. 개별 위치 표현에서는 세 값을 바꾸지만, 차이를 저장하면 기준 위치 하나만 바꿔 같은 결과를 얻을 수 있어요. 이 예는 아이템 사이의 빈 공간 길이를 그대로 옮긴 것이 아니라, 간격이 보존되는 이유를 보여주는 간단한 좌표 모형입니다.

출구를 막아 두고 선두가 더 이상 가지 못하면 뒷부분까지 즉시 정지시킬 이유는 없어요. 공간이 남은 쪽의 아이템은 앞으로 더 갈 수 있어요. 실험에서는 앞쪽 공간이 모두 닫힌 다음에야 그 뒤의 공간이 줄어드는지 매 틱의 위치를 기록해 확인합니다. 마지막에 총개수만 비교하면 한 틱 일찍 움직였거나 꽉 찼을 때 겹친 버그가 숨을 수 있어요. 두 표현을 비교할 때는 같은 틱의 위치 목록과 경계에서 빠져나간 아이템 순서까지 대조하는 편이 좋습니다.

표현을 바꿀 때 비용이 옮겨 가는 지점

기준 위치와 간격으로 저장하면 줄 전체를 한 번에 전진시키기 쉬운 대신, 가운데 아이템 하나의 절대 위치를 묻는 연산은 앞쪽 간격을 함께 읽어야 할 수 있어요. 렌더링을 위해 어차피 전체를 순회하는 상황과, 투입기가 줄 중간을 자주 조회하는 상황을 나눠 측정해야 합니다. 또한 앞뒤 구간을 합치거나 분리하는 일이 잦다면 경계의 간격을 다시 맞추는 비용도 비교에 포함합니다. 갱신 연산이 줄었다는 사실만으로 전체 프레임이 빨라졌다고 결론 내리기보다, 어떤 상태를 얼마나 자주 읽고 쓰는지부터 확인하면 다른 게임의 행렬이나 줄에도 이 아이디어를 적용할 근거가 생깁니다.

출처

같은 카테고리의 글

게임 기술 전체 보기 ↗