휴면을 사용하여 단일 스레드에서 렌더링 / 그리기 코드에서 논리 / 업데이트 분리


9

게임 오브젝트의 속도는 FPS에 의해 방해받지 말고 대신 시간을 기준으로해야한다는 것을 읽었습니다. 드로잉 속도를 제한하지 않고 성능을 최대화하고 시간에 따라 일정한 로직 업데이트 속도를 제공하기 위해 업데이트 / 드로잉 코드를 분리하려면 어떻게해야합니까?

내 현재 의사 코드는 다음과 같습니다

loop
{
    draw();
    if (ticksElapsed() > 100)
    {
        update();
        ticks+= ticksElapsed();
    }        
}

문제는 드로잉 코드가 update () 속도의 성능을 방해한다는 것입니다. 그리고 수면이 발생하면 그리기 / 논리 기능을 모두 제거하기 때문에 100 % CPU를 소비합니다.

또한 SDL을 사용하고 있으며 vsync 옵션이없는 것 같습니다. 또한 고정 및 가변 시간 스테핑이라는 용어에 대해 들었지만 sleep ()으로 어떻게 수행 할 수 있는지 잘 모르겠습니다.


1
ticksElapsed () <100 인 경우 while 루프의 끝에 잠자기 (0)를두기 만하면 대기하기 위해 100 % CPU 전력을 낭비 할 필요가 없습니다. 다른 스레드가없는 경우 OS는 즉시 스레드로 돌아갑니다. 달리고 싶다. 그러나 더 이상 100 % CPU 전력을 낭비하지 않습니다.
Maik Semder

그러나 이러한 1 스레드 설정을위한 최상의 솔루션은 vsync를 사용하는 것입니다. vsync를 사용할 수없는 경우 대상 프레임 속도에 도달 할 때까지 루프에서 sleep (0)을 호출 한 다음 업데이트 및 그리기
Maik Semder

답변:


3

코드 스 니펫에서는 그림과 업데이트가 15ms (60fps) 미만이면 바쁜 대기로 고정 시간 단계 모드에서 게임을 실행하려고하는 것처럼 보입니다. 이것은 가능하며 수면 시간을 정확히 알지 못하기 때문에 수면 통화를 사용 하여이 작업을 수행 할 수 없다고 생각했습니다. 바쁜 대기 루프가 좋은 솔루션입니다.

그러나 업데이트 및 드로잉이 15ms를 초과하는 경우 게임 드로잉 및 업데이트 속도가 느려집니다. 이제 두 가지 작업을 수행 할 수 있습니다.이 상태를 감지하고 프레임을 삭제 (도면 건너 뛰기 및 다시 동기화 될 때까지 바로 업데이트로 이동)하지만 컴퓨터가 느리게 진행되는 경우 컴퓨터가 느려지지 않습니다.

다른 해결책은 업데이트 논리를 고정 시간 독립적으로 만드는 것입니다. 이를 위해 별도의 스레드가 필요하지 않습니다. 물건이 얼마나 빨리 움직여야하는지 다시 지정하면됩니다. 틱당 5 픽셀 대신 초당 50 픽셀을 사용해야합니다. 이를 위해서는 고정밀 타이머가 필요하며 모든 업데이트 논리는 타이머에 액세스하여 마지막 업데이트 이후 얼마나 많은 시간이 지 났는지 확인할 수 있어야합니다.

기본적으로 당신은 :

void UpdatePlayer()
 player.x += 10;

void UpdatePlayer(float elapsedSeconds) //the total seconds elapsed since last update
 player.x += walkspeed * elapsedSeconds;

내 엔진은 항상 100 %를 소비하며 실제로 할 수있는 일은 없습니까?
Oskenso Kashi

1
스케줄러가 얻을 수있는만큼 많은 사이클을 소비하지만 게임을하는 동안 다른 많은 것을 할 수 없기 때문에 실제로 문제가되지는 않습니다. :).
Roy T.

@Oskenso 그러나, 당신이 다음 주 스레드 당신이 정말로 잠을 고려해야한다, 다른 사람은 동안 루프에서 연산 능력을 많이 낭비만큼 할 수있을뿐만 실행하지 않습니다보다 1 개 스레드보다 사용하는 경우 문제입니다
Maik Semder

@Maik Semder : 수면 (x)에 대한 해결책이 정확하지 않습니까? 휴면 간격이 지나면 스레드를 실행할 수 있습니다. 그러나 준비된 스레드가 즉시 실행되는 것은 아닙니다. 그것은 스케줄러에 달려 있습니다. 두 개의 스레드를 사용하는 경우 다른 훌륭한 해결책이 있습니다. altdevblogaday.com/2011/07/03/threading-and-your-game-loop
Roy T.

1
@Roy sleep (0)이 해결책입니다. 실행하려는 다른 스레드가없는 경우 ( Sleep WinAPI ) 즉시 리턴 하고 다른 스레드에 실행할 기회를 제공합니다. 다른 스레드가 메인 스레드에 대가로 실행 기회를 제공하지 않으면 스레딩 문제가 발생하지만 처음에 sleep을 호출하지 않고 다른 모든 항목을 차단하면 스레드가 더 악화되고 해결책이 거의 없습니다. 핵심은 sleep (0)을 호출하고 목표 고정 프레임 속도에 도달 할 때까지 경과 시간을 테스트하는 것이므로 대기하는 동안 100 % CPU를 낭비하지 않습니다.
Maik Semder
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.