게임에서 죽은 물체를 효과적으로 제거 하는가?


10

for 루프 또는 foreach 루프를 사용하여 업데이트하거나 그려야 할 때 모든 객체를 반복합니다. 그러나 객체가 죽으면 컬렉션에서 다시 제거하고 싶습니다.

죽은 개체 목록에 개체를 추가하여이 작업을 수행 한 다음 모든 것이 그려지고 업데이트되면이 목록의 모든 항목을 검토하여 목록의 개체를 원래 소스에서도 제거합니다.

더 좋은 방법이 있습니까?



2
제목에 "garbage"라는 단어를 사용하고 .NET 가비지 콜렉터를 언급 한 지금까지의 답변에도 불구하고 이것은 실제로 가비지 콜렉션과 관련이 없습니다.
Andrew Russell

.NET 가비지 수집기와의 혼동을 막기 위해 실제로 "쓰레기"라는 단어를 "죽음"으로 바꾸는 자유를 얻었습니다.
Nevermind

아, 알아요 가비지 수집 기사는 죽은 개체로 수행하는 작업을 수행 할 수 있으므로 여전히 관련이 있습니다. 예를 들어 죽은 잔해? 모든 것을 연결 해제하고 기본값으로 재설정 한 다음 파편 버킷에 다시 놓으십시오.
doppelgreener

답변:


11

우선 : 용어. "가비지 목록"이라고 말하면 사람들은 가비지 수집기에 대해 이야기하고 있다고 생각할 것입니다. 이것을 "데드리스트"라고하자.

당신이 아마 발견했듯이, 질문은, 당신이 그것을 반복하는 동안 컬렉션에서 아이템을 제거 할 수 없습니다. 컬렉션이 List<>아이템을 제거하는 가장 간단한 방법 인 경우 :

for(int i = list.Count-1; i >= 0; --i)
{
    if(list[i].IsDead)
        list.RemoveAt(i);
}

거꾸로 반복한다는 점에 유의하십시오 . 앞으로 반복하면서 항목을 제거 할 수 있지만 더 복잡하고가 필요합니다 goto. 로 할 수 없습니다 foreach.

업데이트 루프와 별도로 제거를 수행 할 수 있습니다. 또는 업데이트 루프에 병합 할 수 있습니다. 항상 RemoveAt루프 끝에서를 수행하십시오 . 루프의 해당 지점 이후에는 list[i]유효한 것으로 간주 할 수 없습니다 (다음 반복에서 다시 유효하게 됨).

또한 각 객체에는 고유 한 IsDead플래그가 있습니다 (처분 패턴을 사용하는 경우이를 만들 수 있음 IsDisposed). 실제로 "데드 목록"을 유지할 필요는 없습니다.

제거를 위해 목록을 검색하지 않아도되므로 성능을 위해 각 항목에 플래그를 사용하는 것이 좋습니다. 또한 디자인에 바람직합니다. 즉, 각 객체가 죽은 지 쉽게 확인할 수 있음을 의미하므로 실수로 객체에 대한 메소드를 호출하지 않습니다 (이러한 객체가 일회용 패턴을 구현하는 ObjectDisposedException경우이 경우에 발생할 수 있음).

가 아닌 컬렉션이있는 경우 List<>해당 컬렉션에서 죽은 항목을 제거하면 여전히 죽은 목록이 생성 될 수 있습니다 (반복 중 제거가 불가능할 수 있음). 제 생각에는 IsDead개체가 죽을 때 목록을 유지하려고하는 대신 플래그를 찾는 컬렉션을 반복하여 사용하기 전에 죽은 목록을 만드는 것이 더 좋습니다 .

사용 불능 목록으로 완료되면 Clear()나중에 다시 사용할 수 있도록 보관 해야 합니다.


그렇다면 일회용 패턴이 더 '효과적인'것으로 간주됩니까?
Jonathan Connell

@Jonathan : 귀하의 질문을 이해하지 못합니다. IsDead패턴은 기능적으로 동일 IsDisposed. 의미 적으로 사용 IsDead한다는 것은 나중에 죽은 항목이 제거 될 이러한 객체의 그리기 / 업데이트 목록을 유지하고 있음을 의미합니다. 폐기 패턴이이를 의미하지는 않습니다. 또한 처리 패턴 해당 개체가 관리 하지 않는 리소스를 보유하고 있음을 의미합니다 (일반적으로 게임 플레이 개체에는 적합하지 않음).
Andrew Russell

역순으로 foreach로 할 수 있습니다.
shinzou

0

99.9 %의 시간 동안 가비지 수집기 (GC)는 번거 로움없이 모든 것을 처리합니다. 해당 객체를 삭제하거나 null로 설정하면 작동하게하십시오. 정리에는 대기 시간이 여러 가지 요소 (예 : 할당 된 메모리 블록 수)에 따라 달라 지지만 걱정할 필요는 없지만 일반적으로 그것에 대해 알 필요는 없습니다. 그것은 단지 작동하도록 설계되었습니다. 이것이 C가 아닌 C #을 사용하는 이유 중 하나입니다.

일반적으로 GC 성능은 병목 현상이 발생한다는 것을 프로파일 링을 통해 알지 않는 한 지나치게 걱정하지 마십시오. 일반적으로 매우 까다로운 게임에서만 발생합니다. 이 경우 GC.Collect () 및 다양한 함정을 살펴보면 언제 사용해야하는지 알 수 있습니다. 인터넷 검색 "force gc xna"를 제안합니다. 많은 자료가 있습니다.


따라서 매번 Update () 호출에 사용중인 목록이 있으면 요소가 "null"인 요소의 모든 요소가 자동으로 정리되고 제거됩니까?
Mathias Lykkegaard Lorenzen

@Mathias No. 귀하의 질문에 대한 내 의견을 참조하십시오. 가비지 수집기는 컬렉션과 해당 내용을 포함하여 여전히 액세스 할 수있는 항목을 수정하지 않습니다.
Andrew Russell

1
문제는 없습니다 어떤 단어 "쓰레기"의 불행한 선택을 제외하고, GC 함께 할 수 있습니다.
Nevermind
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.