개념적으로 게임에서 재생은 어떻게 작동합니까?


145

게임에서 재생이 어떻게 구현되는지 궁금합니다.

처음에는 게임에서 수행 된 모든 플레이어 / ai 액션의 명령 목록 만있을 것이라고 생각했고, 게임을 '재생'하고 엔진이 평소대로 렌더링되도록했습니다. 그러나, 나는 FPS / RTS 게임에서의 리플레이를 살펴 보았으며,주의 깊게 검사했을 때 파티클과 그래픽 / 가청 글리치와 같은 것들도 일관됩니다 (그 글리치들은 일반적 으로 일관됩니다).

어떻게 이런 일이 발생합니까? 고정 카메라 앵글 게임에서는 전체 장면의 모든 프레임을 스트림에 기록 한 다음 스트림을 다시 재생하지만 카메라를 일시 중지하고 이동할 수있는 게임에는 충분하지 않습니다. 주위에. 장면의 모든 위치를 모든 시점에 저장해야합니다 (아니요?). 따라서 파티클과 같은 것에는 많은 데이터가 필요합니다. 이는 게임하는 동안 게임 성능을 크게 끌어내는 것 같습니다.


10
오리지널 스타 크래프트 리플레이는 사실 일관성이 없었습니다. 같은 게임을 두 번 시청하면 다소 다른 결과를 볼 수 있습니다.
Andres

1
@Andres : 흥미 롭습니다. 특히 RTS 장르의 경우 Company Of Heroes를 생각하고있었습니다.
Steven Evers 2016 년

4
SnOrfus가 요구하는 바를 명확히하기 위해 : 일부 게임 (Uncharted 2, Halo 3, 심지어 Battlefield 2)을 통해 게임 전체를 기록 할 수 있습니다. 게임이 끝나면 지정된 속도로 게임을 플레이하고 액션이 진행되는 동안 레벨을 비행하여 맵의 어느 위치에서나 볼 수 있습니다. 따라서 비디오 버퍼와 관련이없는 모든 플레이어 / 객체의 움직임을 기록하는 것으로 가정합니다.
Sean

1
@Sean O'Hollaren : 네, 맞습니다.
Steven Evers

1
그런 다음 리플레이가 거의 기본 인 자동차 경주 게임도 추가하겠습니다. 모델의 위치가 기록 된 다음 엔진을 통해 모든 것이 실행됩니다.
d -_- b

답변:


61

처음 생각이 맞았다 고 생각합니다. 재생을 만들려면 난수 생성기의 초기 시드와 함께 사용자로부터받은 모든 입력 (받은 프레임 번호와 함께)을 저장합니다. 게임을 재생하려면 저장된 시드를 사용하여 PRNG를 재설정하고 게임 엔진에 동일한 입력 시퀀스 (프레임 번호와 동기화)를 공급합니다. 많은 게임이 프레임 사이의 시간에 따라 게임 상태를 업데이트하므로 각 프레임의 길이를 저장해야 할 수도 있습니다.


재생은 라이브 게임과 다른 프레임 속도로 실행될 수 있기 때문에 프레임 번호는 좋은 참조가 아닐 수 있습니다.
벤 S

5
@Ben : 프레임 번호는 여전히 동일하므로 프레임 속도는 차이가 없습니다. 이것이 정답입니다.
BlueRaja-대니 Pflughoeft

14
그래픽 프레임과 엔진 '프레임'(또는 반복)이 반드시 동일하지는 않습니다. 많은 오래된 게임에서 엔진은 하나의 마스터 루프에서 그래픽과 동일한 속도로 업데이트되었습니다. 최신 엔진을 사용하면 그래픽이 GPU가 허용하는 한도 내에서 빠르게 업데이트 될 수 있으며, 엔진 다이내믹스가 게임의 역학 (물리적 인 물리 엔진)의 일관된 해상도를 유지하는 데 필요한 수준으로 움직입니다.
Dan Bryant

3
@ iamgopal : 의사 난수 생성기의 상태를 알고 있다면 그 문제는 이미 해결되었습니다. 다른 방법은 난수를 다른 형태의 입력으로 취급하고 키 누르기 등과 함께 이들을 저장하는 것일 수 있습니다.
Kylotan

1
이 방법을 사용하려면 게임 엔진이 결정적이며 고정 된 시간 간격으로 작동해야합니다. 나는 모든 블리자드의 RTS 게임이 이런 식으로 구축되었다고 생각합니다. 비 결정적 게임에는 장기적으로 일관성을 유지하기 위해 추가 동기화 데이터가 포함됩니다.
John Leidegren

28

스타 크래프트와 스타 크래프트 : 브루드 워에는 리플레이 기능이있었습니다. 경기가 완료된 후 나중에 볼 수 있도록 리플레이를 저장하도록 선택할 수 있습니다. 재생하는 동안지도를 스크롤하고 단위와 건물을 클릭 할 수 있지만 동작을 변경할 수는 없습니다.

원래 게임에서 플레이 한 경기의 리플레이를 본 기억이 있지만 Brood War에서는 리플레이를보고있었습니다. 익숙하지 않은 사람들을 위해 Brood War에는 모든 원래 유닛과 건물뿐만 아니라 다양한 새 건물이 포함되어 있습니다. 원래 게임에서 플레이어는 컴퓨터가 쉽게 대응할 수없는 유닛을 만들어 컴퓨터를 물리 쳤습니다. Brood War에서 리플레이를했을 때 컴퓨터는 다른 유닛에 접근 할 수 있었으며,이 유닛은 플레이어를 물리 치고 생성하는 데 사용되었습니다. 따라서 동일한 재생 파일로 인해 Starcraft의 버전에 따라 다른 승자가 발생했습니다.

나는 항상 그 개념이 매혹적인 것을 발견했다. 재생 기능은 플레이어의 모든 입력을 기록하여 작동하는 것처럼 보였으며 컴퓨터는 매번 동일한 방식으로 자극에 반응한다고 가정했습니다. 플레이어 입력이 오리지널 스타 크래프트 리 플레이어에 공급되었을 때, 게임은 원래 경기에서와 똑같이 진행되었습니다. Brood War replayer에 동일한 정확한 입력이 공급되면 컴퓨터는 다르게 반응하고 더 강한 유닛을 만들어 게임에서 승리했습니다.

재생 엔진을 작성하는 경우 명심해야 할 사항입니다.


6
+1 : 매우 흥미 롭습니다. 나는 그것에 대해 들어 본 적이 없습니다. 그들이 어떻게 개발했는지에 대한 좋은 통찰력을 제공합니다.
Steven Evers 2016 년

18

두 가지 주요 방법이 있습니다.

  1. 말한대로 이벤트 저장 (플레이어 / AI 액션 등)
  2. 저장 상태 (전체 게임 상태, 객체의 fe 위치, 연속 순간).

당신이하고 싶은 일에 달려 있습니다. 일반적으로 훨씬 적은 메모리를 사용하므로 이벤트 저장이 더 좋습니다. 반면에 다른 속도와 다른 시작 지점에서 재생할 수있는 재생을 제공하려면 상태를 저장하는 것이 좋습니다. 상태를 저장하는 경우 모든 이벤트 후에 또는 초당 12 회 또는 25 회만 fe를 저장할지 여부를 결정할 수 있습니다. 이렇게하면 재생 크기가 줄어들고 되감기 / 빨리 감기가 더 쉬워 질 수 있습니다.

"상태"는 그래픽 상태를 의미하지 않습니다. 단위 위치, 자원 상태 등과 같은 것. 그래픽, 파티클 시스템 등과 같은 것은 일반적으로 결정 론적이며 "애니메이션 X, 시간 Y : Z"로 저장 될 수 있습니다.

때로는 리플레이가 부정 행위 방지 체계로 사용되기도합니다. 그렇다면 이벤트를 저장하는 것이 가장 좋습니다.


10

기술적으로 엔진을 결정 론적으로 작성해야합니다. 게임에서 캐릭터가 상대방의 팔을 목표로하고 무기를 발사한다고 가정하면 모든 경우에 동일한 양의 피해가 상대방에게 적용되어야합니다.

폭탄이 X 위치에서 폭발한다고 가정하면, 그 폭발에 의해 생성 된 입자는 항상 동일한 시각적 결과를 가져야합니다. 임의성이 필요한 경우 임의의 숫자 세트를 작성하고 게임을 플레이 할 때 시드 값을 선택한 다음 해당 시드 값을 재생에 저장하십시오.

일반적으로 게임에서 임의성을 갖는 것은 나쁜 생각입니다. 멀티 플레이어와 같은 경우에도 플레이어는 폭발을 볼 수있는 절반을 가질 수 없지만 다른 플레이어는 단순한 임의의 값을 얻지 못했기 때문에 볼 수 없습니다.

모든 것을 결정 론적으로 만들면 괜찮을 것입니다.


1
AI는 어떻습니까? AI는 무작위가 아닌가?
Jesse Jashinsky

18
실제로 필요하지 않습니다. 모든 임의의 이벤트에 시드 의사 난수를 사용하고 시드를 재생 파일에 저장하십시오. 이렇게하면 재생 중에 동일한 "무작위"숫자가 생성됩니다.
벤 S

13
-1 "임의성"컴퓨터에서 작동하는 방법의 명확한 오해
대니 Pflughoeft - BlueRaja

10
음 .... 아니 .. "진정한"무작위성 같은 것은 없다는 것을 완벽하게 알고 있습니다. 그러나 대부분의 사람들은 임의의 시드를 시스템 시간과 같은 것으로 설정 하여이 문제를 해결하려고합니다. 그러나 내가 말하는 것은 그러한 일을해서는 안된다는 것입니다. 그가 시스템 API 또는 사전 정의 된 난수 표를 사용하는지 상관하지 않습니다. 내가 처음 말한 것은 정확했습니다. 그의 엔진의 모든 기능은 입력을 기반으로 동일한 결과를 생성해야합니다. 시간은 결코 요인이되어서는 안됩니다.
Timothy Baldridge

2
입자가 의미있는 방식으로 게임 메커니즘과 상호 작용하지 않으면 RNG가 다른지 여부는 중요하지 않습니다. 이는 시뮬레이션이 모든 프레임을 동기화해야하는 시간이 약간 적기 때문에 네트워크 동기화 시뮬레이션의 경우에 도움이됩니다 (대부분의 RTS 게임 및 기타 많은 장르의 게임에서와 같이). 개별적으로 업데이트).
RCIX

10

초기 상태 와 타임 스탬프가 있는 일련의 동작이 주어지면 기록 된 동작이 재생되도록 가정되므로 시퀀스를 진행하면됩니다.

임의의 이벤트가 정확히 동일하게 발생 하도록하려면 시드 된 의사 난수를 사용하고 시드 를 재생 파일에 저장 하십시오.

동일한 알고리즘을 사용하여 시드에서 난수를 생성하는 한 게임 상태의 전체 스냅 샷 없이도 라이브 게임에서 발생한 것처럼 모든 이벤트를 다시 만들 수 있습니다.

이를 위해서는 순차적으로 리플레이를 시청 해야 하지만 게임 리플레이에서는 일반적으로 정상입니다 (Starcraft 2 참조). 타임 라인에 임의 액세스를 허용하려는 경우 설정된 간격 (예 : 1 분)으로 전체 상태 스냅 샷 을 생성하여 설정된 세분성으로 타임 라인을 뛰어 넘을 수 있습니다.


일정 시간 (5 초 또는 10 초)마다 다시 시드하면 재생 스트림에 기록하기 쉽고 충분히 앞뒤로 점프 할 수 있습니다 (기본적으로 PRNG "키 프레임"으로).
웨지

7

NVidia PhysX (게임에서 자주 사용되는 물리 시뮬레이션 엔진)는 시간이 지남에 따라 실제 장면의 전체 상태를 기록 할 수 있습니다. 여기에는 게임 엔진의 구동 입력이 통합되어있어 다른 사람들이 제안한대로 임의의 숫자 시드를 추적 할 필요가 없습니다. 이 장면 덤프를 가져 오면 외부 도구 (NVIdia 제공)에서 재생할 수 있으며 실제 모델의 문제를 추적하는 데 매우 유용합니다. 그러나 동일한 물리 스트림을 사용하여 그래픽 엔진을 구동 할 수도 있습니다. 그러면 그래픽을 구동하는 물리 만 기록되므로 일반적인 카메라 제어가 가능합니다. 많은 게임에서 여기에는 파티클 효과가 포함됩니다 (PhysX에는 매우 정교한 파티클 시스템이 포함되어 있습니다). 사운드에 관해서는 (사운드 스트림으로) 그대로 녹음 된 것 같습니다.


4

당신의 독창적 인 아이디어는 옳고, 매우 복잡한 효과에 대해서는 독점적으로 기억되지 않습니다. 예를 들어, 워크래프트 3 재생 시스템은 임의의 효과 등의 경우 애니메이션 상태 또는 파티클 효과를 저장하지 않습니다. 또한 대부분의 시스템에서 MOST는 시작점에서 결정적인 방식으로 계산할 수 있습니다. 랜덤 변수 (예를 들어 랜덤 오프셋을 제공하는 파티클 폭발)를 사용하는 경우, 이펙트 시간과 랜덤 시드 만 있으면됩니다. 그런 다음 실제로 어떤 결과가 나올지 알지 않고도 효과를 다시 생성 할 수 있습니다. 결정적인 코드 경로를 거치는 것을 알기

순전히 개념적으로 생각하여 이벤트 타임 라인을 재생하려면 사용자 작업 만 있으면됩니다. 랜덤 변수의 경우를 제외하고 프로그램은 정확히 같은 방식으로 반응합니다. 이 시나리오에서는 무작위성을 무시하거나 (효과가 정확히 동일하게 보이는지 또는 무작위로 재생성 할 수 있는지에 상관없이) 시드 값을 저장하고 무작위성을 위조 할 수 있습니다.


3

내 두 펜스를 던져

원하는 것에 따라 재생을 통해 수행 할 수 있습니다

  1. 비디오 버퍼 녹화 및 나중에 재생
  2. 매 프레임마다 객체 상태를 캡처하고 나중에 재생

대부분의 경우 사람들은 대화 형 재생을 원하므로 2. 가야합니다. 그런 다음 제약 조건에 따라이 프로세스를 최적화하는 여러 가지 방법이 있습니다.

  • 모든 입력이 일관되고 예상되는 출력을 생성하도록 시스템이 결정 론적 시뮬레이션 *인지 확인
  • 난수가 필요한 경우 난수를 나중에 정확하게 재현 할 수 있는지 확인하십시오 [의사 난수 생성기 PRNG로 시드 확인 또는 미리 준비된 난수 세트 사용]
  • 게임 요소를 "기계적"요소와 "미적"요소로 나눕니다. 기계적인 요소는 결과에 영향을 미치며 (예 : 컬럼이 넘어져서 막히는 경로) 미적인 요소는 시스템의 의사 결정 프로세스 (예 : 스파크와 같은 시각적 입자 효과)에 영향을 미치지 않으며 표시되지 않습니다.

정말 흥미로운 주제입니다. Xbox Wreckless 오리지널 타이틀 하나 에 좋은 재생 기능이 있다는 것을 기억 합니다. 불행히도, 두 번 이상 재생이 망칠 수 있습니다.)

오 예, 어떻게 누구나 Blinx Time Sweeper를 잊을 수 있었습니까 ! 실제 게임 메카닉 에 통합 훌륭한 대화 형 리플레이 !


* = 시간 스테핑에 관한 의견이있는 것 같습니다. 이 기능을 캡처하기 위해 "시뮬레이션"을 사용하고 있습니다. 핵심에서 엔진은 개별 시간 프레임을 생성 할 수 있어야합니다. 재생 프레임이 원본보다 처리하는 데 시간이 오래 걸리거나 짧아도 시스템은 동일한 시간 델타가 지났다는 것을 인식 해야합니다 . 즉, 각 기록 된 입력으로 프레임 시간 단계를 기록하고이 델타를 엔진 시계에 공급합니다.


2

아마도 각 플레이어가 보낸 명령 스택을 간단히 저장할 수 있습니다. 따라서 폭탄이 특정 시점과 시간에 폭발하거나 특정 차량이 파괴되는 것을 저장하는 대신 각 플레이어가 보낸 키 누름을 저장하면됩니다. 그런 다음 리플레이에서 해당 프레스로 발생했을 때 게임을 시뮬레이션합니다. 나는 그것이 더 적은 공간을 차지할 가능성이 있다고 생각하지만, 나는 그런 리플레이 시스템에서 일한 적이 없다.

그래도 흥미로운 질문입니다. 프로 게임에서 어떻게되는지 관심이 있습니다.


2

댄 브라이언트

또한, 임의의 시드를 기록하는 것은 되감기 지원에 충분하지 않습니다. 무작위 진행은 임의성에 의존하는 모든 논리에서 특별한 지원 없이는 가역적 인 절차가 아니기 때문입니다. 이벤트 스트림의 일부로 무작위 조작의 결과를 기록하는 것이 더 유연합니다.

정확히 내가 처음에 게임이 항상 똑같이 재생되도록 어떻게 만들 었는지 알아낼 때 처음에 생각했던 것입니다. 운명과 함께 나는 촬영이 얼마나 무작위로 진행되는지 생각했다. 사용 된 임의의 숫자를 저장하면 솔루션 일 수 있음을 알았습니다. 그것은 크라이시스 기술에 관한 PDF 문서를 만나기 전이었습니다. 일부 텍스처 노이즈와 잔디 또는 나무 배치는 고정 가역적 시드와 함께 의사 난 수화를 사용하여 볼 때마다 노이즈, 나무 및 잔디의 배치 변경을 보지 못했습니다!

수백만 그루의 나무와 잔디 축을 보관하는 동시에 피하십시오. 분명히 의사 난수 시퀀스는 논리가 고정되어있는 것처럼 언제든지 통계적으로 임의의 숫자 시퀀스를 만들기 위해 동일하게 재생할 수 있습니다.


이에 Dan의 관심을 끌고 자한다면 그의 공헌 아래에 의견을 추가하십시오. 그렇지 않으면 그는 그것을 보지 못할 것입니다.
절반 반

내가 단지 손님 인 이유 일 수도 있지만 부모님의 게시물에 "댓글 추가"기능을 볼 수 없었습니다. Dan은 Dan의 대답은 말할 것도없이 대답했습니다. 내 게시물이 아닌 게시물에 대해서도 수정 개선 기능이 있지만 어떻게 작동합니까?
Antonymous

아, 좋은 질문입니다! 여기 보인다 내 사과 - 당신은 질문 또는 답변이 자신이 아닌 다른에 대한 언급을 50 담당자 포인트를 필요. 50은 매우 쉽게 구할 수 있습니다. 단지 몇 가지 유용한 기여만으로도 달성 할 수 있습니다. 그렇습니다. 다른 사람의 질문과 답변을 편집 할 수 있지만 2000 년이 될 때까지 다른 사람이 편집 한 내용을 검토 합니다 . 여기에서 권한 차트를 참조 하십시오 .
초에 절반

1

일관된 리플레이 문제는 일관된 멀티 플레이어 게임과 동일합니다.

앞에서 언급했듯이 RTS 게임의 재생은 모든 입력을 기록하여 저장됩니다 (효과가 있습니다. 스크롤은 효과가 없습니다). 멀티 플레이어도 모든 입력을 전송합니다

추측뿐만 아니라 모든 입력을 기록합니다-Warcraft3 리플레이를 읽는 라이브러리가 있습니다.

입력에는이 답변의 타임 스탬프가 포함됩니다.


아니요. 일관된 MP 게임과 동일하지 않습니다. MP를 플레이 할 때 게임은 일반적으로 모든 사람이 동일한 버전의 게임을 가지고 있어야합니다. 이는 이전 버전의 게임과 함께 저장되었을 수 있으므로 저장된 세션의 경우는 아닙니다. 플레이어 중 하나가 AI 상대 인 경우 특히 중요합니다. 유닛이 기록 된 버전보다 최신 버전에서 단 하나의 어택 포인트를 가진 게임을 재생한다고 상상해보십시오. 이것은 완전히 다른 결과를 초래할 수 있습니다.
drakon

-1

나는 게임이 특정 증분에서 모든 상태 (모든 것)의 스냅 샷을 찍을 것이라고 믿는다. 그런 다음 리플레이가 발생하면 간단한 선형 보간법을 사용하여 "구멍"을 채울 수 있습니다. 적어도 그것이 내가 할 것이라고 생각하는 방법입니다.

입력을 기록하는 것이 신뢰할 수 없거나 동일한 출력을 보장하지 않는 것이 맞습니다. 게임은 모든 객체의 상태 (또는 적어도 중요한 것)를 반드시 추적해야합니다.


2
아니요, 동일한 입력을 공급하면 처음과 정확히 동일한 결과가 나타납니다. 입력이 원래 수신되었던 동일한 프레임 사이에 입력을 공급하면서 타이밍이 정확해야합니다. 전체 게임 상태를 주기적으로 저장하면 엄청난 양의 메모리가 필요하고 일관성이없는 결과도 생성 될 수 있습니다.
피터 Ruderman

@Peter, "동일한 입력을 공급하면 정확히 같은 결과가 나옵니다": no. 많은 게임에는 임의의 요소가 있으며 재생이 실행될 때마다 다를 수 있습니다. 입력 이상의 것을 추적해야합니다.
houbysoft 2016 년

사실입니다. 또한 PRNG의 씨앗을 저장해야합니다 (이 질문에 대한 나의 답변 참조).
피터 Ruderman

1
나는 그것이 성능과 메모리를 소비한다는 것을 알고 있지만, 입력이나 무작위 생성기까지 작은 것을 놓치면 ... 또는 정말로 아무것도, 재생이 끔찍한 접선에서 시작됩니다!
Bob Fincheimer 2018 년

@BlueRaja, Bob의 메모리 스냅 샷 아이디어는 반드시 그렇게 많이 가져올 필요는 없지만, 좋은 엔진은 모든 반복에 대해 모든 메모리를 인코딩하는 대신 상태 '델타'를 기록 할 수 있습니다. 엔진 수준에서 지원하기가 더 쉬울 것입니다. 또한, 임의의 시드를 기록하는 것은 되감기 지원에 충분하지 않습니다. 무작위 진행은 임의성에 의존하는 모든 논리에서 특별한 지원 없이는 가역적 인 절차가 아니기 때문입니다. 이벤트 스트림의 일부로 임의 조작의 결과를 기록하는 것이 더 유연합니다.
Dan Bryant
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.