2011-09-07 6 views
6

현재 C# & XNA를 사용하여 타워 방어 게임을 만들고 있습니다. 게임은 잠시 동안 부드럽고 잘 돌아가지만 충분한 시간 동안 (충분한 적/타워/총알이 생성 된 후) 게임이 기하 급수적으로 느려지는 것처럼 보입니다. 모든 사례가 해결 되더라도 지연은 계속 유지됩니다.XNA 게임 지연 결정

처음에는 이것이 가비지 수집과 관련이 있을지도 모른다고 생각했지만 테스트하기 위해 객체를 수집 할 때 모든 객체가 수집 될 때 인쇄 할 소멸자를 작성했습니다. XNA에서 지연과 가능한 원인이있는 사람이 있다면 궁금합니다.

편집 : 이것은 PC 나 성능을 확인하기 위해 사용했던 두 가지가있다

+0

제안 : 더 나은 (전반적인) 질문 일 수 있습니다. "지연이 발생한 위치를 확인하려면 어떻게해야합니까? 이것은 많은 다른 것들에 의해 야기 될 수있는 것처럼 보입니다. 지연 문제의 근원을 파악하기 위해 코드를 많이보아야합니다. – jadarnel27

+0

간단히 살펴볼 코드가 너무 많습니다. 나는 이론적 인 해결책이나 가능한 원인에 대해 더 많은 것을 요구하고있다. 현재 네트워킹과 관련된 문제가 없어야합니다. – Johannes

+1

내가 제안하는 한 가지 점은 사용자가 큰 서브 루틴/영역을 입력하고 종료 할 때 (디버그 로그 파일이나 다른 것으로) 타임 스탬프를 인쇄하는 것입니다. 이 방법을 사용하면 그 시간을 잃어버린 곳을 볼 수 있고 문제에 대해 안쪽으로 작업 할 수 있습니다. – jadarnel27

답변

0

게임 루프 시간이 늘어 났습니까? 스톱워치를 Update 루프와 Draw 루프의 시작과 끝에 추가하십시오. 속도가 느려지는 것을 발견 할 때까지 stopwatch.Start() 및/또는 stopwatch.Stop())를 배제하십시오. 증가하지 않으면 다른 원인에 의해 발생합니다.

시도 코드에 다음 행을 추가합니다 (DrawInt64/32 정말 유용 당신이 쓰레기를 생성하지 않고 숫자를 그릴 수의 SpriteBatch하는 확장 가능한 여기

SpriteBatch.DrawInt64(Font, GC.GetTotalMemory(false)/1000 /* in kilobytes */, 
POSITION, Color.White, 0f); 

입니다

:. http://pastebin.com/pVw66mGy 또는 다만하여 drawString을 사용하고 .ToString()).

표시된 숫자가 줄어들 때마다 가비지 수집이 실행됩니다.

+0

가비지 수집이 발생하는지 확인하는 더 좋은 방법은 GC.CollectionCount()를 사용하는 것입니다. 이렇게하면 각각의 세대가 수집되는시기를 볼 수 있습니다. 0 세대 컬렉션은 큰 문제가 아닐 수 있습니다. 1 세대와 2 세대 컬렉션은 성능 측면에서 훨씬 더 큰 관심사입니다. –

1

가비지 수집이 성능에 영향을 줄 우려가있는 경우 가장 유용한 도구 중 하나는 CLR Profiler입니다. 이 유틸리티를 사용하면 프로그램에서 수행 한 힙 할당을 프로파일 링하여 정확히 어떤 메소드가 가비지를 생성하는지 식별 할 수 있습니다. 문자열을 연결하고, 사전을 열거 키, 클로저, 델리 게이션으로 인덱싱 할 수있는 뻔하지 않은 많은 것들을 힙에 할당 할 수 있다는 것을 기억하십시오. 초당 60+ 프레임으로 프레임 당 한 번 생성되는 작은 쓰레기조차도 올바른 상황에서

즉, 설명해 주신 내용이 나에게 불필요한 낭비라고 생각하지 않습니다. GC는 전체 수집 중에도 프레임이 몇 개만 삭제되도록 일반적으로 빠릅니다. 즉, 가끔씩 사소하고 짜증나는 저크가 느껴지지만 지속적으로 느려지지는 않습니다.

(경고 :이 유일한 XNA 플랫폼에 비해 매우 정교한 GC가있는 PC에 적용됩니다.)

당신은 방법을 완료하는 데 시간이 가장 오래 걸리는지 확인하는 코드에 프로파일 러를 연결하려고한다 ; 문제가 GC와 관련이 없다면 유익 할 것입니다. 이전에는 일부 최신 버전에 문제가 있었지만 EQATEC을 사용했습니다. 그 중 하나를 시도해 보거나 Google에서 대안을 둘러 볼 수 있습니다.

0

이벤트를 잊지 않는 것을 잊으시겠습니까? 아래 예제에서 4 개의 스프라이트를 목록에 추가하고 각 스프라이트는 게임의 이벤트를 연결합니다. 그런 다음 스프라이트를 제거하고 이벤트를 발생시킵니다.

이 상황에서 4 개의 스프라이트는 모두 여전히 활성 상태이며 Game에 계속 언급되어 있기 때문에 이벤트가 발생합니다.

게임 개체에 이벤트를 사용하는 경우 모두 실행중인 상태로 둘 수 있습니다.

class Game 
{ 
    public event EventHandler SomeEvent; 
    List<Sprite> sprites; 

    public Game() 
    { 
    sprites = new List<Sprite>(); 
    sprites.Add(new Sprite(this)); 
    sprites.Add(new Sprite(this)); 
    sprites.Add(new Sprite(this)); 
    sprites.Add(new Sprite(this)); 

    sprites.RemoveAt(0); 

    EventHandler temp = SomeEvent; 
    if (temp != null) 
    { 
     temp(this, EventArgs.Empty); 
    } 
    } 

    static void Main(string[] args) 
    { 
     Game newProgram = new Game(); 
    } 



    class Sprite 
    { 
     public Sprite(Game gameReference) 
     { 
      gameReference.SomeEvent += new EventHandler(gameReference_SomeEvent); 
     } 

     void gameReference_SomeEvent(object sender, EventArgs e) 
     { 
      Debug.WriteLine("Event"); 
     }  
    }