절차 생성, 게임 업데이트 및 나비 효과 하위 시스템은 자체

참고 : 며칠 전에 Stack Overflow에서이를 요청했지만 뷰가 거의없고 응답이 없었습니다. 대신 gamdev.stackexchange를 요청해야한다고 생각했습니다.

이는 이전에 생성 된 컨텐츠를 손상시키지 않고 여러 릴리스 후 업데이트를 통해 절차 생성 시스템을 유지 보수하는 데 대한 일반적인 질문 / 조언입니다.

게임용 절차 콘텐츠를 만들 때 “버터 플라이 효과”문제를 피하기위한 정보와 기술을 찾으려고합니다. 시드 난수 생성기를 사용할 때 반복 가능한 난수 시퀀스를 사용하여 재현 가능한 세계를 만들 수 있습니다. 일부 게임은 생성 된 세계를 한 번 생성 된 디스크에 간단히 저장하지만 절차 생성의 강력한 기능 중 하나는 숫자 시퀀스의 재현성에 의존하여 동일한 방식으로 영역을 여러 번 다시 생성 할 수 있다는 사실입니다. 고집. 특정 상황의 제약 때문에 지속성을 최소화해야하며 가능한 한 순수하게 시드 된 농도에 의존해야합니다.

이 접근법의 가장 큰 위험은 절차 적 생성 시스템의 작은 변화조차도 전 세계를 변화시키는 나비 효과를 일으킬 수 있다는 것입니다. 이것은 플레이어가 탐험하는 세계를 파괴하지 않고 게임을 업데이트하는 것이 매우 까다로워집니다.

이 문제를 피하기 위해 사용한 주요 기술은 여러 단계로 절차 생성을 설계하는 것입니다. 각 단계에는 자체 시드 난수 생성기가 있습니다. 즉, 각 하위 시스템은 자체 포함되어 있으며, 어떤 것이 고장 나더라도 세계의 모든 것에 영향을 미치지 않습니다. 그러나 이것은 게임의 고립 된 부분에 있더라도 “손상”에 대한 많은 잠재력을 가지고있는 것처럼 보입니다.

이 문제를 처리하는 또 다른 방법은 코드 내에서 완전한 버전의 생성기를 유지하고 주어진 세계 인스턴스에 적합한 생성기를 계속 사용하는 것입니다. 이것은 나에게 유지 보수의 악몽처럼 보이고, 누군가 실제로 이것을하면 궁금합니다.

따라서 제 질문은 특히 출시 후 게임 업데이트와 관련하여 나비 효과 의이 문제를 처리하기위한 일반적인 조언, 기술 및 디자인 패턴에 대한 요청입니다. (아쉽게도 그것은 광범위한 질문이 아닙니다.)

나는 언어에 무관심한 질문이지만 현재 Unity3D / C #에서 일하고 있습니다.

최신 정보:

답장을 보내 주셔서 감사합니다.

정적 데이터가 가장 안전하고 안전한 접근 방식 인 것 같습니다. 또한 정적 데이터를 많이 저장하는 것이 옵션이 아닌 경우 생성 된 세계에서 긴 캠페인을 수행하려면 사용 된 생성기의 엄격한 버전 관리가 필요합니다. 필자의 경우 제한의 이유는 모바일 기반 클라우드 저장 / 동기화가 필요하기 때문입니다. 내 해결책은 필수 사항에 대한 소량의 컴팩트 데이터를 저장하는 방법을 찾는 것입니다.

스톰윈드의 “케이지 (Cages)”개념은 사물에 대해 특히 유용한 사고 방식이라고 생각합니다. 케이지는 기본적으로 재 시드 지점으로, 작은 변화, 즉 나비 케이지의 실행 영향을 방지합니다.



답변

나는 당신이 여기에 기초를 덮었다 고 생각합니다.

  • 여러 생성기를 사용하거나 간격으로 다시 시드 (예 : 공간 해시 사용)하여 유출로 인한 유출을 제한합니다. 이것은 아마도 화장품 내용에 효과적이지만, 지적한 것처럼 여전히 한 섹션 내에 파손이 발생할 수 있습니다.

  • 저장 파일에 사용 된 생성기 버전을 추적하고 적절하게 응답합니다. “적절한”의 의미는 …

    • 게임 실행 파일에 모든 이전 버전의 생성기 이력을 유지하고 저장과 일치하는 것을 사용하십시오. 플레이어가 오래된 저장을 계속 사용하면 버그를 패치하기가 더 어려워집니다.
    • 플레이어에게이 저장 파일이 이전 버전의 파일임을 경고하고 해당 버전에 별도의 실행 파일로 액세스 할 수있는 링크를 제공하십시오. 몇 시간에서 며칠 동안 지속되는 캠페인이있는 게임에 적합하며 몇 주 이상 플레이 할 것으로 예상되는 캠페인에는 좋지 않습니다.
    • n실행 파일 에는 마지막 생성기 버전 만 유지하십시오 . 저장 파일이 최신 버전 중 하나를 사용하는 경우 저장 파일을 최신 버전으로 업데이트하십시오. 이는 적절한 생성기를 사용하여 오래된 상태를 리터럴 (또는 동일한 생성기의 새로운 생성기 출력의 델타로 압축 해제)로 압축 해제합니다. 여기서부터 새로운 상태는 최신 발전기에서 나옵니다. 오랫동안 게임을하지 않는 플레이어는 남겨질 수 있습니다. 최악의 경우 전체 게임 상태를 리터럴 형태로 저장하게되는데,이 경우에도 마찬가지입니다.
  • 생성 로직을 자주 변경하고 이전 버전과의 호환성을 유지하지 않으려면 생성기 결정에 의존하지 마십시오. 전체 상태를 저장 파일에 저장하십시오. (예 : “궤도에서 나옵니다. 확실한 유일한 방법”)


답변

그러한 버터 플라이 효과의 주요 원인은 숫자 생성이 아니라 단일 숫자 생성기에서 결정 성을 유지하기에 충분히 쉬울 것입니다. 클라이언트 코드에서 이러한 숫자를 사용 입니다. 코드 변경은 상황을 안정적으로 유지하는 데있어 실질적인 문제입니다.

코드 : 단위 테스트 어딘가에 약간의 변경이 의도하지 않은 곳에 표시되지 않도록하는 가장 좋은 방법은 모든 생성 측면에 대한 철저한 단위 테스트를 빌드에 포함시키는 것입니다. 이것은 하나의 변경이 많은 다른 것들에 영향을 줄 수있는 소형 코드의 경우에 해당됩니다. 영향을받는 단일 빌드에서 볼 수 있도록 모두 테스트해야합니다.

숫자 : 주기적 시퀀스 / 슬롯 모든 것을 처리하는 하나의 숫자 생성기가 있다고 가정 해 봅시다. 의미를 부여하지 않고 PRNG처럼 번호를 순서대로 뱉어냅니다. 두 번의 런에 대해 동일한 시드가 주어지면 동일한 시퀀스를 얻습니다. 이제 몇 가지 생각을하고 정기적으로 임의의 값을 제공해야 할 게임의 30 가지 측면이있을 것이라고 결정합니다. 여기서 우리는 30 슬롯의 사이클링 시퀀스를 할당합니다. 예를 들어 시퀀스의 첫 번째 숫자는 모두 거친 지형 레이아웃이고, 두 번째 숫자는 모두 지형 섭동입니다. … 매 10 번째 숫자마다 AI 상태에 약간의 오류가 추가되어 사실적입니다. 그래서 당신의 기간 은 30입니다.

10 이후에는 게임 디자인이 진행됨에 따라 다른 측면에 사용할 수있는 20 개의 슬롯이 무료입니다. 여기서 비용은 슬롯 이 현재 사용 중이 아니더라도 ( 즉, 기간을 완료하여) 1-10의 다음 순서로 돌아가려면 슬롯 11-30에 대해 숫자를 생성해야합니다 . 사용 가능한 슬롯 수에 따라 약간의 CPU 비용이 발생하지만 CPU 비용이 발생합니다. 다른 단점은 확실 최종 디자인이 매우 개발 과정의 시작에 사용할 슬롯의 수에 수용 … 그리고 더 많은 당신은 시작에 지정 될 수 있다는 것을, 더 많은 슬롯을 “비어” 당신은 잠재적으로 각각을 통해 일을 작동하게해야합니다.

이것의 영향은 다음과 같습니다.

  • 하나의 발전기가 모든 것을 위해 숫자를 생성합니다.
  • 숫자를 생성해야하는 측면의 수를 변경해도 결정론에 영향을 미치지 않습니다 (기간이 모든 측면을 수용 할 수있을 정도로 클 경우)

물론, 게임을 대중에게 이용할 수없는 기간이 오래 지속될 것입니다. 즉, 알파로 말하면, 당신은 플레이어에게 영향을주지 않고 30 ~ 20 개 측면을 줄일 수 있습니다. 당신은 할당 한 방법으로 처음에 너무 많은 슬롯을. 이것은 물론 일부 CPU주기를 절약 할 수 있습니다. 그러나 좋은 해시 함수 (자신이 직접 작성할 수 있음)는 어쨌든 번개처럼 빨라야합니다. 따라서 추가 슬롯을 실행하는 데 많은 비용이 들지 않아야합니다.


답변

PCG로 지속성을 유지 하려면 PCG 코드 자체를 data로 취급하는 것이 좋습니다 . 일반 컨텐츠, 생성 된 컨텐츠를 사용하여 개정간에 데이터를 유지하는 것과 마찬가지로 개정간에 데이터를 유지하려면 생성기를 유지해야합니다.

물론 가장 널리 사용되는 방법은 앞에서 설명한 것처럼 생성 된 데이터를 정적 데이터로 변환하는 것입니다.

PCG 게임에서 지속성이 드물기 때문에 많은 발전기 버전을 유지하는 게임의 예를 모르겠습니다. 왜냐하면 permadeath가 종종 PCG와 함께하는 이유입니다. 그러나 동일한 게임 내에 동일한 유형의 여러 PCG에 대한 예가 많이 있습니다. 예를 들어, Unangband 에는 던전 실을위한 별도의 발전기가 많이 있으며, 새로운 것을 추가 할 때 기존의 발전기는 여전히 동일하게 작동합니다. 유지 관리 가능 여부는 구현에 달려 있습니다. 유지 보수를 유지하는 한 가지 방법은 스크립트를 사용하여 생성기를 구현하고 나머지 게임 코드와 분리하여 생성기를 유지하는 것입니다.


답변

나는 약 3 백만 평방 킬로미터의 면적을 유지하고 기타 물건의 무작위 배치 외에도 약 1 백만 개의 건물과 기타 물건을 보관합니다. 야외 시뮬레이션 c. 저장된 데이터는 약 4GB입니다. 저장 공간이있어 운이 좋지만 무제한은 아닙니다.

무작위는 무작위이며 통제되지 않습니다. 그러나 우리는 그것을 조금 감쌀 수 있습니다 :

  • 시작 끝점을 제어합니다 (다른 게시물, 시드 번호 및 생성 된 수 참조).
  • 숫자 공간을 제한하십시오 (예 : 0에서 100 사이의 정수만 생성하십시오.
  • 값을 추가하여 숫자 공간을 오프셋합니다 (예 : 100 + [0에서 100 사이의 생성 된 숫자]는 100에서 200 사이의 난수를 생성합니다)
  • 크기 조정 (예 : 0.1 곱하기)
  • 그리고 주위에 다양한 케이지를 적용하십시오. 이것은 세대의 일부를 깎아 내고 있습니다. 예 : 2 차원 공간에서 생성하는 경우 숫자 쌍 위에 사각형을 놓고 외부를 스크랩 할 수 있습니다. 또는 원 또는 다각형. 3D 공간에서 구와 같은 다른 모양 (예 : 시각적으로 생각하지만 실제 시각화 또는 위치 지정과 반드시 ​​관련이있는 것은 아님) 만 허용 할 수 있습니다.

그게 다야. 우리는 또한 불행히도 데이터를 소비합니다.

핀란드어로 Hajota ja hallitse라는 말이 있습니다. 나누기와 정복 으로 번역합니다 .

나는 작은 세부 사항에 대한 정확한 정의라는 생각을 빨리 버렸다. 랜덤은 자유를 원하므로 자유를 얻습니다. 나비가 날아 가자-그 안에 새장. 대신에 나는 우리를 정의 할 수있는 풍부한 방법에 집중했습니다. 파란색 또는 진한 파란색 (지루한 고용주가 한 번 말한 것)이라면 어떤 자동차인지는 중요하지 않습니다. “파란색 또는 진한 파란색”은 여기에서 색상 차원에 따라 (매우 작은) 우리입니다.

숫자 공간을 제어하고 관리하기 위해 관리 할 수있는 것은 무엇입니까?

  • 부울 그리드는 (비트가 작습니다!)
  • 코너 포인트는
  • 나무 구조 그대로 (= “케이지 홀딩 케이지”에 따름)

유지 관리 측면 및 버전 상호 호환성 측면 … 우리는
: if version = n 다음
: elseif version = m then …
그래, 코드베이스가 커집니다 :-).

익숙한 것들. 당신의 올바른 길은 나눌 수 있는 풍부한 방법을 정의하는 것입니다 하고 그것에 대한 일부 데이터를 희생 입니다. 그런 다음 가능하면 (로컬) 무작위 배정의 자유를 주어야합니다.

DMGregory가 제안한 재미있는 “nuke it fom 궤도”와 완전히 호환되지 않지만 작고 정확한 핵무기를 사용할 수 있습니까? 🙂