2012-09-12 2 views
3

ICollidable 인터페이스를 구현하는 엔티티 목록이 있습니다. 이 인터페이스는 엔티티 간의 충돌을 해결하는 데 사용됩니다. 내 실체 따라서 다음과 같습니다리스트 <T> .AddRange가 잠시 지연되고 있습니다.

  • 플레이어, 난을 삭제하고
  • 발사체
  • 항목
  • 타일 각 게임 업데이트 (약 60t/S)에

게임 상태에 따라 현재 엔티티를 추가하고 추가합니다. 이 작업은 다음을 통해 수행합니다.

collidableEntities.Clear(); 
collidableEntities.AddRange(players); 
collidableEntities.AddRange(enemies); 
collidableEntities.AddRange(projectiles); 
collidableEntities.AddRange(items); 
collidableEntities.AddRange(camera.VisibleTiles); 

보이는 타일을 목록에 추가 할 때까지 모든 것이 올바르게 작동합니다. 게임 루프를 실행하는 데 1 ~ 2 초가 걸리므로 시각적 인 문제가 발생하여 그리기가 지연되어 렌더링에서 지터를 볼 수 있습니다. 말 그대로 타일을 추가하는 선을 제거/추가 할 수 있고 지터가 발생하고 발생하지 않는 것을 볼 수 있으므로 그 선으로 좁혔습니다.

내 질문은 무엇입니까? VisibleTiles의 목록은 약 450-500 타일이므로 실제 많은 데이터가 아닙니다. 각 타일에는 무엇이 렌더링되고 어디에 있는지를 결정하는 Texture2D (이미지)와 Vector2 (위치)가 있습니다. 나는 계속 찾고있을 것이지만, 머리 위로부터 나는 처음 1-2 초의 딸꾹질이 왜 있었는지 이해할 수는 없지만 그곳에는 부드럽다.

모든 조언을 주시면 감사하겠습니다.

업데이트

I 요소의 근사 량을 초기 용량을 증가시키는 시도하지만, 차이는 관찰되지 않았다.

업데이트 요청으로

, 여기 camera.VisibleTiles

코드입니다
public List<Tile> 
{ 
    get { return this.visibleTiles; } 
} 
당신은 미리 정의 된 크기 목록을 초기화하기 위해 overloaded constructor for List<T>을 사용할 수 있습니다
+2

'camera.VisibleTiles'의 코드에 액세스 할 수 있습니까? 객체 참조를주는 것 이상의 일을하고 있습니까? –

+0

그래, 그냥 목록 에 대한 참조를 반환하는 속성입니다. –

+2

@Brian이 제안한 바에 따라 camera.VisibleTiles를 호출하지만이 코드를 목록에 추가하지 않는 코드로 바꾸십시오. 그것은'AddRange' 호출인지 느린'VisibleTiles' 호출인지를 결정합니다. – Rotem

답변

5

이와 같은 성능 문제가 발생할 때마다 가능한 원인이 무엇인지 추측하지 않아도됩니다. 올바른 대답은 프로필 응용 프로그램입니다. 사용할 수있는 여러 옵션이 있습니다. StackOverflow에서 제안을 찾을 수있을 것입니다.

그러나 오늘은 운이 좋았 기 때문에 방금 전 당신에게 준 조언을 무시하고 추측 할 것입니다. 나는 미래에 그러한 문제를 진단하는 데 도움이되기를 희망하는 나의 추론을 설명 할 것이다.

만 게임 플레이의 시작 부분에 및 이 목록 자체, 또는 충돌 로직의 기능에 내재 아무것도 아니라고 믿고 날 리드 일단 당신이 을 설명하는에서만 문제가 발생한다는 사실. 물론 이것은 목록에있는 객체의 수가 기본적으로이 기간 동안 일정하다고 가정합니다. 이 인 경우이 둘 중 하나에 의해 야기 되었기 때문에 모든 프레임일 것으로 예상됩니다.

따라서 가비지 컬렉터이 의심됩니다. 게임을 시작할 때 GC가 발생하는 것을 볼 수 있습니다. 즉, 거대한 자산을 모두 메모리에로드 한 직후입니다. 이론적으로는 모서리를 통해 컬렉션으로 푸시 할 수 있기 때문에 코드의 무작위 지점에서 발생하는 것으로 보입니다.

내 생각 엔 게임을로드 할 때 생성하는 애셋이 많은 양의 콜렉션 압력을 생성하고 있지만 그럼에도 콜렉션을 실행하기에는 충분하지 않습니다. 게임 플레이 중에 개체를 할당하면 (이 경우 목록의 크기를 조정 한 결과로) 수집 압력이 GC가 최종적으로 활성화하기로 결정한 지점까지 증가하여 관찰하는 지터가 발생합니다. GC가 실행되고 모든 적절한 객체가 올바른 세대로 이관되면 지터가 중단됩니다.

내가 말했듯이 이것은 교육받은 사람 일지라도 단지 추측 일뿐입니다. 그러나 테스트는 간단합니다. 렌더 루프를 입력하기 전에 GC.Collect(2)에 대한 호출을 추가하십시오. 내가 맞으면 지터가 사라져야합니다.

보다 철저히하고 싶습니다. Microsoft는 메모리 문제 디버깅에 유용한 도구 인 CLR Profiler을 제공합니다. 이 도구는 콜렉션이 발생하는시기와 그 이유를 정확하게 보여줍니다. XNA 개발에 매우 ​​유용합니다.

+0

+1. GC 동작에 대한 좋은 추론. –

+0

올바른 방향으로 생각하고 있기 때문에 대답으로 표시됩니다. –

0

:

var collidableEntities = new List<object>(500); 
+0

나는 그것을 시도했지만 성공하지 못했다. –

+0

항목이 한 번에 하나씩 루프에 추가되면이 작업이 훨씬 더 커질 수 있습니다. 'AddRange'는 추가 될 모든 모든 항목에 충분한 용량이 있음을 보장하기 위해 (시도하여) 가능한 버퍼 크기 조정의 수를 줄입니다. 또한, 500은 그렇게 크지 않습니다. 문제를보기 시작하려면 보통 수만 명이 있어야합니다. – Servy

1

각 세대의 GC 조정 크기로 인해 1-2 초가 걸릴 수 있습니다. 해당 perf 카운터를보고 1 초 만에 Gen1/2 컬렉션이 많은지 확인하십시오 (GC를 최소화하면 게임의 유용한 목표입니다).

추가 임의의 추측 : 어떤 이유로 든 모든 개체는 struct입니다. 그리고 매우 큽니다. 따라서 복사하는 데 오랜 시간이 걸립니다.

노트 (첫번째 초 후에 부드럽게 설명 할 것이다) :

  • 을 대신 하나의 목록에있는 항목 모두 복사를 방지 할 수 생성 반복자를 고려 병합의.
  • 프로필러 가져 오기
  • 처리 과정에 대한 실적 카운터를 살펴보십시오. 흥미로운 카테고리는 메모리, GC, CPU, 핸들러입니다.