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


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.