끝없는 주자에서 실제로 움직이는 것은 무엇입니까?


107

예를 들어 유명한 Flappy Bird 게임 또는 실제로 정렬되는 것은 플레이어 (이 경우 새 또는 원하는 카메라)가 앞으로 이동하거나 전 세계가 뒤로 이동하는 것입니다 (조류는 Y 위치 만 변경하고 일정한 X 위치)?


1
이 질문과 그 답변에서 많은 주제를 벗어난 의견을 삭제했습니다. 우리는 또한 여러 차례의 합리적인 토론을 대화로 옮겨서 어떤 경우에는 반복적으로 대화했습니다. 그럼에도 불구하고 몇몇 사용자는 의견이 장기 토론을위한 것이 아니라는 사실을 무시할 필요성을 느꼈습니다. 따라서이 질문은 일시적으로 잠겨 있습니다.
Josh

답변:


146

필립의 대답에 약간 동의하지 않습니다 . 또는 적어도 그가 그것을 제시 한 방법으로. 플레이어 주변으로 세상을 움직이는 것이 더 좋은 아이디어라는 인상을줍니다. 정확히 반대 일 때. 그래서 여기 내 자신의 대답이 있습니다 ...


두 옵션 모두 작동 할 수 있지만 일반적으로 전 세계 플레이어가 아닌 플레이어 주위로 세계를 이동하여 "물리를 뒤집는"것은 나쁜 생각입니다.


성능 손실 / 폐기물 :

세상에는 보통 많은 물건이있을 것입니다. 대부분은 아니지만 정적 또는 수면. 플레이어는 하나 또는 비교적 적은 수의 객체를 갖습니다. 플레이어 주변에서 전 세계를 움직이는 것은 플레이어를 제외한 모든 장면을 움직이는 것을 의미합니다. 정적 객체, 수면 동적 객체, 활성 동적 객체, 광원, 사운드 소스 등 모두 움직여야합니다.

그것은 실제로 움직이는 것 (플레이어, 그리고 몇 가지 더 많은 것)만을 움직이는 것보다 (비슷하게) 상당히 비쌉니다.


유지 관리 및 확장 성 :

플레이어 주위로 세상을 움직이면 세상 (그리고 그 안의 모든 것)이 일이 가장 활발하게 일어나는 지점이됩니다. 시스템의 모든 버그 또는 변경은 잠재적으로 모든 것이 변경됨을 의미합니다. 이것은 일을하는 좋은 방법이 아닙니다. 버그 / 변경 사항을 가능한 한 격리하여 변경하지 않은 곳에서 예기치 않은 동작이 발생하지 않도록합니다.

이 접근법에는 다른 많은 문제들도 있습니다. 예를 들어 엔진 내에서 작동하는 방식에 대한 많은 가정을 어 기고 있습니다. RigidBody예를 들어 플레이어 이외의 다른 용도로는 동적을 사용할 수 없습니다 . RigidBody키네마 틱으로 설정 되어 있지 않은 객체는 위치 / 회전 / 스케일 (플레이어를 제외한 씬의 모든 객체에 대해 모든 프레임을 수행 할 때)을 설정할 때 예기치 않게 동작합니다.


따라서 대답은 플레이어를 이동시키는 것입니다!

... 음 아니오 . Philipp의 답변에서 언급했듯이 무한 러너 유형의 게임 (또는 큰 매끄러운 탐색 가능 영역이있는 게임)에서 원점에서 너무 멀리 떨어지면 결국 눈에 띄는 FPPE ( 부동 소수점 정밀도 오류 )가 발생합니다. 숫자 유형을 오버플로하여 게임이 중단되거나 기본적으로 게임 세계의 연기 균열이 발생합니다 ... 스테로이드에서! 😵 (이 시점에서 FPPE는 게임을 이미 "정상"균열로 만들 것입니다)


실제 솔루션 :

둘 다하지 마십시오. 월드를 정적으로 유지하고 플레이어를 그 주위로 움직여야합니다. 그러나 플레이어가 장면 의 루트 (position ) 에서 너무 멀어지기 시작 하면 플레이어 세계 모두 "루트" 합니다 . [0, 0, 0]

사물의 상대 위치 (전 세계 플레이어)를 단일 프레임 업데이트로 유지하면 (실제) 플레이어는 눈치 채지 못할 것입니다!

이를 위해 두 가지 기본 옵션이 있습니다.

  1. 플레이어를 장면의 루트로 옮기고 월드 청크를 플레이어와 관련된 새로운 위치로 옮깁니다.
  2. 세상을 격자처럼 생각하십시오. 플레이어가있는 그리드 부분을 루트로 옮기고 플레이어를 그리드의 해당 부분을 기준으로 새로운 위치로 이동시킵니다.

이 프로세스의 실제 예는 다음과 같습니다.


그러나, 너무 멀어요?

Unity의 소스 코드를 살펴보면 1e-5( 0.00001)를 내부 Vector2와 내부 Vector3(객체의 위치, [자유로운 회전 및 스케일을 담당하는 데이터 유형] 두 개의 부동 소수점 값을 고려하는 기준으로 사용합니다 . 부동 소수점 정밀도 손실은 두 가지 방법으로 0에서 멀어지기 때문에 장면 루트 / 원점에서 1e+5( 100000) 단위 아래의 모든 항목이 작업하기에 안전하다고 가정하는 것이 안전합니다.

그러나! 이후...

  1. 시스템이 이러한 재 루팅 프로세스를 자동으로 처리하도록하는 것이 더 적절합니다.
  2. 게임이 무엇이든간에 세계의 연속적인 "섹션"의 너비가 100000 단위 (미터 [?]) 일 필요는 없습니다.

... 그러면 100000 단위보다 훨씬 더 빨리 / 더 자주 다시 뿌리는 것이 좋습니다. 예를 들어 내가 제공 한 예제 비디오는 1000 단위마다 그렇게하는 것 같습니다.


2
의견은 긴 토론을위한 것이 아닙니다. 이 대화는 채팅 으로 이동 되었습니다 . 여기에 더 많은 의견을 게시하는 대신 해당 채팅을 사용하십시오.
알렉상드르 Vaillancourt

> 실제로 움직이는 것만 움직이는 것보다 훨씬 비싸다 . 렌더링 할 때, 당신은 어쨌든 것 신원 고정 카메라를 가진 모든 개체에 카메라 행렬과 행렬의 곱셈을해야 할 것 이러한 방식으로 비싼.
Matsemann

게임 개발이 단일 개발이되는 순간 ...
LJ ᛃ

@ Matsemann-당신이 채팅을했다면, 이것은 새로운 요점이 아니라는 것을 알았을 것입니다. 이미 설명했듯이 NOT-EQUALS 장면을 렌더링하십시오. 그것들은 다르고 거의 완전히 독립적 인 주제와 파이프 라인입니다. 객체가 장면에 배치되는 방식으로 참조 프레임 반전을 수행하면 렌더링이 아니라 양쪽 끝 이 더 무거워집니다 . --- 또한, 주장한 바와 같이 성능이 균등하게 거래 되더라도 반전에 관한 다른 모든 문제는 여전히 해결되지 않은 상태로 남아 있으며,이 방법 은 다시 뿌리를 내리는 것보다 여전히 나쁩니다.
XenoRo

@LJ ᛃ 유니티에 대한 질문은 구체적으로 (D. Everhard의 [IMHO defacing] 편집 이전의 OP 태그 참조), 이에 대한 답변을 반영하여 만들어 졌습니다. --- 그러나 여기에 가장 좋은 부분이 있습니다 : Unity, Unreal, CryEngine, Source 등 ... 가장 인기 있고 가장 인기있는 엔진은 이런 식으로 작동하므로 이유가 있습니다. 일반적으로 완벽하게 유효 하지만 만들어지는 요점은 여전히 정확도의 정점입니다 . 일반적으로 물리의 참조 프레임을 반전 시키면 특히 동적 객체에서 문제가 발생할 수 있습니다.
XenoRo

89

두 옵션 모두 작동합니다.

그러나 끝없는 주자가 진정한 끝이 아니길 원한다면, 플레이어를 움직이지 않고 세상을 움직여야합니다. 그렇지 않으면 결국 X 위치를 저장하는 데 사용하는 변수의 한계에 도달하게됩니다. 정수는 결국 오버플로되고 부동 소수점 변수는 점점 정확도가 떨어 지므로 잠시 후 게임 플레이가 고장납니다. 그러나 한 세션에서 재생할 수있는 시간 범위 내에 아무도 이러한 문제가 발생하지 않을 정도로 충분히 큰 유형을 사용하면이 문제를 피할 수 있습니다 (플레이어가 초당 1000 픽셀을 이동하면 49 일 후에 32 비트 정수가 오버플로 됨).

개념적으로 당신에게 더 직관적 인 느낌을 가지십시오.


의견은 긴 토론을위한 것이 아닙니다. 이 대화는 채팅 으로 이동 되었습니다 .
Josh

1
나는 그것이 아무것도 해결되지 않는다고 생각합니다. 플레이어 (및 카메라) 위치를 유지하는 대신 세계의 스크롤 위치를 유지하십시오. 어떻게 다른가요?
Agent_L

1
@Agent_L 일반적으로 월드는 조각으로 생성되며 각 조각은 X / Y 위치를 갖습니다. 조각이 플레이어의 뒤를 벗어나면 (예 : 오프 스크린) 삭제되고 일정량 만 미리 생성되므로 항상 상대적으로 작은 범위 내에 있습니다. 무한으로 무작위로 생성 된 러너 임에도 불구하고 ~ 1000보다 작거나 0보다 작습니다. 왜냐하면 각 청크에서 플레이어의 위치와 시퀀스에서 각 청크의 인덱스를 추적했습니다.
Nic Hartley

나는 "가변 오버플로"개념을 구입하지 않습니다. 플레이어가 움직이지 않으면 "배경"은 플레이어가 움직일 때 오프셋되는 것과 같은 양만큼 음수 오프셋됩니다. 두 경우 모두 정확히 같은 문제가 발생하고 (반대 방향) 오버플로 한계에서 특별한 처리가 필요합니다.
쓰셨

2
초당 1000 픽셀에서 64 비트 정수를 넘어가려면 5 억 5 천 5 백만 년이 걸릴 것입니다. 16 비트 정수와 같은 작은 유형을 사용하는 경우에만 문제가됩니다.
Lyndon White

38

XenoRo의 답변바탕으로 설명하는 재 루트 방법 대신 다음을 수행 할 수 있습니다.

무한 맵 생성 부분의 원형 버퍼를 생성합니다.이 맵은 모듈러스 산술로 업데이트 된 위치로 캐릭터가 이동합니다 (따라서 원형 버퍼를 돌면됩니다). 캐릭터가 덩어리를 떠나 자마자 버퍼의 일부를 교체하십시오. 플레이어 업데이트 방정식은 다음과 같습니다.

player.position = (player.position + player.velocity) % worldBuffer.width;

여기 내가 말하는 것에 대한 그림의 예가 있습니다.

여기에 이미지 설명을 입력하십시오

다음은 마지막에 줄 바꿈이 수행되는 예입니다.

여기에 이미지 설명을 입력하십시오

이 방법을 사용하면 정밀한 오류가 발생하지는 않지만 3D에서 매우 멀리 떨어진 시야 거리 에서이 작업을 수행하려는 경우 매우 큰 버퍼를 만들어야 할 수도 있습니다 (여전히 자신을 미리 수 있어야 함) ). 플래 피 버드의 경우 청크 크기는 단일 화면에서 단일 장면을 유지하는 데 필요한만큼만 크며 버퍼는 매우 작을 수 있습니다.

모든 prng 를 사용하여 반복 결과를 얻을 수 있으며 PRNG 생성의 최대 비 반복 시퀀스 수는 일반적으로 pow (2, 내부적으로 사용되는 비트 수)의 길이보다 으며 메르겐 트위스터 는 그렇지 않습니다. 2.5k의 내부 상태를 사용하기 때문에 많은 문제가 발생하지만 작은 변형을 사용하는 경우 반복 (또는 악화) 전에 2 ^ 127-1 최대 반복이 있지만 천문학적으로 많은 수 입니다. PRNG가 시드에 대해 우수한 애벌랜치 믹싱 기능 을 통해 (암시 적으로 더 많은 상태를 추가 할 때) 반복적으로 주기가 짧아도 반복주기 문제를 해결할 수 있습니다 .


의견은 긴 토론을위한 것이 아닙니다. 이 대화는 채팅 으로 이동 되었습니다 .
Josh

15

이미 요청하고 받아 들인 것처럼, 그것은 실제로 게임의 범위와 스타일에 달려 있지만 언급되지 않았으므로 FlappyBird는 전 세계의 플레이어가 아니라 화면을 가로 질러 장애물을 움직입니다.

스폰 너는 Vector2.left방향 에서 고정 된 속도로 화면 밖으로 오브젝트를 인스턴스화합니다 .


3
FlappyBird는 매우 간단한 게임 이기 때문에 작동합니다 . 내 대답에서 언급했듯이, 동일한 기술은 여전히 가능 하지만 지하철 서퍼와 같이 더 복잡한 (세계 객체 / 세부 정보가 더 많은) 항목에서 매우 문제가 될 수 있습니다 .
XenoRo

15
동의하며 귀하의 답변은 매우 철저합니다. 나는 새가 실제로 퍼지는 방법을 언급하는 사람을 보지 못했기 때문에 그것을 추가 할 것이라고 생각했다.
Stephan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.