절차적 스캐터링은 재현 가능할 때만 신뢰할 수 있다: 같은 입력이 모든 머신과 모든 빌드에서 항상 같은 숲을 생성해야 한다. 그것은 시드를 이해하는 것(무작위성을 반복 가능하게 만드는 방법), 살아있는 절차적 시스템이 소스 관리 하에서 왜 위험한지, 그리고 스캐터를 네이티브 엔진 인스턴스로 베이킹하는 것이 왜 merge 불가능한 블랙박스를 diff 가능, review 가능, 버전 관리 가능한 에셋으로 바꾸는지를 의미한다. 이 글은 결정론, 시드, 그리고 팀의 초목이 모두의 발밑에서 조용히 변하는 것을 어떻게 막을지 다룬다.
이것은 무작위로 보이지만, 팀에게는 반복 가능한 무작위여야 한다: 당신의 머신, 팀원의 머신, 빌드 서버에서 같은. 결정론이 예쁜 스캐터를 실제로 shipping하고 유지할 수 있는 무언가로 바꾸는 것이다.
결정론이 왜 중요한가
스캐터가 열릴 때마다 또는 빌드될 때마다 다르게 재생성된다면, 당신의 레벨은 조용히 변한다: 충돌이 움직이고, 숨겨진 오브젝트가 나타나고, 플레이테스트가 재현 불가능해 진다. 결정론적 스캐터는 같은 입력에서 항상 정확히 같은 결과를 생성한다.
반복 불가능한 무작위성은 레벨에서 버그 공장이다. 다른 머신에서 씬을 열거나 다음 주에 다시 빌드하는 것이 모든 바위와 덤불이 착지하는 곳을 다시 섞는다면, 비어 있던 자리가 이제 막혔고, 조정한 시야선이 깨졌으며, 테스트 중인 레벨이 shipping한 레벨이 아니기 때문에 플레이테스트 결과를 신뢰할 수 없다. 결정론(같은 입력, 같은 출력, 항상)이 절차적 스캐터를 안전하게 만드는 것이다. 그것은 "컴퓨터가 몇 개의 식물을 배치했다"와 "레벨이 내가 의지할 수 있는 정의되고 안정적인 상태를 가지고 있다"의 차이다.
시드: 무작위성을 반복 가능하게 만들기
시드는 무작위 시퀀스의 시작 숫자다. 같은 시드 → 매번 같은 "무작위" 배치. 시드를 노출하고 저장하면 당신의 스캐터는 재현 가능하다; 그것을 진정한 무작위성에 맡기면 매 실행마다 다른 레벨이다.
컴퓨터는 진정한 무작위성을 하지 않는다: 결정론적 시퀀스를 실행하며, 그것들은 무작위로 보이고, 각 시퀀스는 시드라고 불리는 시작 숫자에 의해 정의된다. 같은 시드를 먹이면 같은 시퀀스, 따라서 같은 배치를, 매번 얻는다. 이것이 재현 가능한 스캐터링의 열쇠다: 도구가 시드를 노출하고, 당신은 그것을 씬과 함께 저장하고, 숲은 이제 (시드 + 매개변수 + 표면)의 순수 함수다. 마음에 드는 다른 배치를 탐색하기 위해 시드를 변경한 다음 잠근다. 대신 진정 으로 시드 없는 무작위 소스에서 끌어오는 어떤 것(시계, 열 때마다의 새로운 굴림)은 로드할 때마다 다른 레벨을 생성하며, 이는 프로덕션에 사용할 수 없다.
버전 관리 문제
"시스템 + 매개변수"로 저장된 살아있는 절차적 스캐터는 소스 관리에 블랙박스다: diff할 수 없고, review할 수 없으며, 두 사람이 편집하면 merge 불가능한 충돌이 생긴다. 팀은 Git이나 Perforce가 실제로 추적할 수 있는 형태의 스캐터가 필요하다.
여기서 스캐터가 팀의 현실과 만난다. 당신의 숲이 "이러한 설정을 가진 스캐터 시스템"으로만 존재한다면, 소스 관리는 그것이 무엇을 생산했는지 볼 수 없다: 오직 일부 매개변수가 변경되었다는 것만. 풀 리퀘스트에서 배치 변경을 review할 수 없고, 무엇이 움직였는지 말할 수 없으며, 두 아티스트가 같은 스캐터를 만지면, 어떤 도구도 의미 있게 해결할 수 없는 merge 충돌을 얻는다. 살아있는 생성기 내에만 사는 스캐터된 레벨은 팀이 안전하게 협력하기 위해 의지하는 바로 그 시스템에 보이지 않으며, 그래서 "모든 것이 절차적이다"가 조용히 "아무도 숲을 안전하게 편집할 수 없다"가 될 수 있다.
이들 각각은 위치, 회전, 스케일을 가진 인스턴스다. 스캐터가 네이티브 인스턴스로 베이킹 될 때, 그것들은 실제, 검사 가능한 데이터가 된다: 숲은 공식이기를 그만두고 줄 단위로 review할 수 있는 것이 된다.
베이킹이 diff 가능하게 만든다
스캐터를 네이티브 엔진 인스턴스로 베이킹하라: 구체적인 변환을 가진 실제 배치된 오브젝트로. 이제 그것은 일반적인 씬 데이터다: diff 가능, review 가능, merge 가능, 그리고 재생성되지 않고 저장되었기 때문에 모든 머신에서 동일하다.
결정론과 버전 관리 모두의 해결은 같은 움직임이다: 베이크. 살아있는 생성기를 shipping 하는 대신, 스캐터를 단순한 네이티브 엔진 인스턴스로 베이킹한다: 씬에 저장된 구체적인 위치, 회전, 스케일을 가진 실제 배치된 메시로. 이는 모든 문제를 한 번에 무너뜨린다. 정의상 결정론적이다 (재굴림이 아닌 저장된 데이터다). diff 가능하다 (소스 관리가 변경된 구체적인 변환을 본다). review 가능하다 (리드가 풀 리퀘스트에서 정확히 무엇이 움직였는지 볼 수 있다). 그리고 런타임에 엔진에 특별한 비용이 들지 않는다, 왜냐하면 단지 인스턴스화된 메시이기 때문이다. 규칙으로 밀도를 페인트하고 그다음에 네이티브 인스턴스로 베이킹하는 워크플로우(정확히 Numivo가 작동하는 방식)는 절차적 스캐터의 저작 속도와 수동 배치 콘텐츠의 안정성을 블랙박스 취약성 없이 제공한다.
팀의 초목을 안정적으로 유지하기
시드를 잠그고, 커밋하기 전에 베이킹하고, 베이킹된 결과를 진실의 원천으로 취급하라. 의도적으로 다시 스캐터하라 (시드를 올리고, diff를 review하라), 결코 우연히가 아니라. 그래서 숲은 누군가 그렇게 의도할 때만 변한다.
팀을 위한 실용적인 규율은 짧다. 스캐터가 재현 가능하도록 시드를 잠그라. 소스 관리에 있는 것이 모두가 공유하는 구체적인 결과이며 머신마다 재굴림하는 레시피가 아니도록, 커밋하기 전에 베이킹하라. 베이킹된 인스턴스를 진실의 원천으로 취급하라: review하고 shipping하는 것이 그것이다. 그리고 숲을 변경하고 싶을 때는 의도적으로 하라: 매개변수나 시드를 조정하고, 다시 베이킹하고, 다른 변경처럼 diff를 review하라. 목표는 인간이 그래야 한다고 결정할 때만 변하고 모든 변경이 가시적이고 review 가능한 숲이다(레벨의 다른 부분에 지킬 것과 같은 기준). 속도를 위한 절차적, 안정성을 위한 베이킹: 그것이 모든 요령이다.
훔칠 가치가 있는 현장 숫자
- 결정론 규칙: 같은 입력 → 같은 출력, 항상, 아니면 당신의 레벨은 드리프트한다
- 시드는 무작위성을 반복 가능하게 만든다: 노출하고, 저장하고, 잠그라
- 살아있는 절차적 스캐터는 Git/Perforce에게 블랙박스다: diff 불가, merge 불가
- 네이티브 인스턴스로 베이킹 → diff 가능, review 가능, merge 가능, 어디서나 동일
- 팀 습관: 시드 잠그기 → 베이킹 → 커밋; 의도적으로 다시 스캐터, 결코 우연히가 아니라
미니 FAQ
스캐터를 절차적으로 유지하고 결코 베이킹하지 않을 수는 없나? 솔로 빠른 프로젝트에는, 아마도. 팀이나 유지할 것에는, 아니다: diffing, review, 안전한 merging을 잃고, 조용한 드리프트를 위험에 노출시킨다. 베이킹이 절차적 스캐터를 프로덕션 안전하게 만드는 것이다.
정확히 무엇을 소스 관리 하에 두어야 하는가, 설정인가 결과인가? 베이킹된 결과가 진실의 원천이다; 의도적으로 재생성할 수 있도록 설정/시드도 유지하라. 설정만 커밋하는 것은 소스 관리가 레벨에서 실제로 무엇이 변했는지 볼 수 없다는 것을 의미한다.
두 아티스트가 같은 숲을 편집했다, 어떻게 merge하는가? 베이킹된 인스턴스로는, 그것은 일반적인 씬 데이터이고 당신의 일반 merge 도구가 적용된다. 살아있는 생성기로는, 종종 해결 불가능하다: 이것이 커밋 전 베이킹과 주어진 스캐터의 소유자를 조정하는 것의 핵심 논거다.
베이킹이 나중에 조정하는 능력을 앗아가는가? 아니다. 시드와 매개변수를 유지하고, 다시 베이킹은 배치를 변경하고 싶을 때마다 의도적인 단계다. 재스캐터가 저절로 일어나는 것이 아니라 의도적이고 review된 행동인 한, 반복과 안정성을 얻는다.
절차적 스캐터는 재현 가능할 때만 그 자리를 얻는다. 시드를 잠그고, 네이티브 인스턴스로 베이킹하고, 그 베이킹된 결과를 레벨의 진실로 취급하라: 그러면 당신의 숲은 전체 팀이 그 위에 구축할 수 있는 것이 된다: 저작이 빠르고, shipping이 안정적이며, 누군가 그렇게 의도할 때만 안전하게 변경할 수 있다.

