[2019] 언리얼 엔진을 통해 살펴보는 리플렉션과 가비지 컬렉션NHN FORWARD※다운로드하시면 더 선명한 자료를 보실 수 있습니다.
언리얼 엔진 프로그래밍을 시작하면, 편리하지만 한편으로는 골치아픈 UObject 시스템을 만나게 됩니다.
이 발표에서는 C++ 프로그래머를 대상으로 UObject 시스템과 그 핵심 기능인 리플렉션, 가비지 컬렉션을 소개하고 그 동작 원리를 함께 들여다봅니다.
목차
1. 일반적인 리플렉션의 개념
2. 언리얼엔진의 리플렉션
3. 일반적인 가비지컬렉션의 개념
4. 언리얼엔진의 가비지 컬렉션
대상
- C++ 개발자
- 언리얼 C++ 프로그래밍에 관심 있는 분
■관련 동영상: https://youtu.be/VpEe9DbcZIs
NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들영욱 오게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들
http://ndcreplay.nexon.com/NDC2017/sessions/NDC2017_0079.html 이곳에서 영상과 슬라이드를 함께 보실 수 있습니다.
NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들영욱 오게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들
http://ndcreplay.nexon.com/NDC2017/sessions/NDC2017_0079.html 이곳에서 영상과 슬라이드를 함께 보실 수 있습니다.
9. - 디자인 패턴의 일종(객체 풀[Object Pool])
- 짧게 사용하고 사라진 뒤에 다시 사용하는 오브젝트의 경우 매번 다시
생성/해제를 반복하게 되면 메모리 부하가 심해집니다.
- 객체를 매번 할당, 해제하지 않고 고정 크기 풀에 들어 있는 객체를 재
사용함으로써 메모리 사용 성능을 개선합니다.
- 메모리 단편화를 방지합니다.
Object Pooling02
9
10. - 화면에 보이지 않게만 하고(Deactive) 메모리를 해제하지 않은 채로 필
요할 때마다 다시 사용하는 기법
- 메모리 할당을 더 간단하게 할 수 있고, 동적 메모리 할당 오버헤드와
가비지 컬렉션(GC)을 줄일 수 있습니다.
- 게임이란 도중에 렉이 걸리는 것보단, 로딩이 오래 걸리는 것이 유저 경
험에 있어서 더욱 이롭습니다.
Object Pooling01
10
11. 1. 오브젝트 생성 시 요구되는 높은 비용을 피하기 위해.
2. 빠른 객체의 초기화 속도
3. 적은 오브젝트의 수로도 많은 오브젝트를 표현할 수 있는점.
4. GC로 인한 프레임 드랍 회피.
Object Pooling 사용하는 이유02
11
12. 1. 객체를 빈번하게 생성/삭제하는 경우
2. 객체를 힙에 생성하기가 느리거나, 메모리 단편화가 우려되는 경우
3. 오브젝트 생성과 삭제함에 있어 병목현상이 발견되는 경우
ex) 게임을 표현함에 있어 많은 오브젝트가 필요한 경우
4. 데이터베이스/네트워크 연결처럼 접근 비용이 비싸면서 재사용 가능
한 자원을 객체가 캡슐화 할 때
Object Pooling 사용하면 좋은 예02
12
13. - 메모리 낭비 가능성
- 사용 가능 객체 개수가 정해져 있을 경우
- 객체를 위한 메모리 크기가 고정되어 있습니다.
1. 메모리 풀에 들어갈 수 있는 객체가 다양할 경우, 가장 큰
자료형에 맞춰야 합니다.
2. 그러므로 객체 크기 별로 풀을 나누는게 좋습니다.
- GC와의 충돌에 주의해야 합니다.
Object Pooling 주의할 점02
13
14. - 사용한 오브젝트를 풀에 반환 할 때 꼭 해당 객체를 초기화 해줘야
합니다.
- 사용 용도에 따라 오브젝트 풀을 어떻게 사용할 것인지에 대한
전략을 잘 세워야 합니다.
Object Pooling 주의할 점02
14
15. - 다른 목적으로 사용할 가용 힙 메모리의 양이 줄어든다. 따라서 현재 막
생성한 풀 외에도 메모리를 계속 할당한다면, 가비지 컬렉션이 더욱 자주
실행될 수 있습니다.
- 가비지 컬렉션에 걸리는 시간은 살아있는 오브젝트의 수에 비례하여
증가하기 때문에 매번 더 느려질 수 있습니다.
- 너무 큰 풀을 할당하거나 풀에 있는 오브젝트가 한동안 필요가 없는 상
황에서 풀을 활성화하여 유지한다면, 성능에 지장이 생기게 됩니다.
Object Pooling 단점02
15
16. - 즉, 오브젝트 풀 오버헤드(오브젝트 풀을 사용하지 않았을 때 생기는 메
모리 부하)인 경우에만 사용해야 이득을 볼 수 있다.
- 지속적인 프로파일링을 통해 이득인지 실인지 잘 따져봐야 할 것입니
다.
Object Pooling 단점02
16
19. 오브젝트 풀링 실습03
19
ObjectWithinPool
Actor
오브젝트 풀에 담을
클래스
활성/비활성화 기능
담당
SpawnObjects
Actor
실제 생성되 레벨에
배치될 오브젝트
이번 실습에서는 플
레이할 캐릭터와 같
은 오브젝트를 배치
할 예정입니다.
ObjectPool
ActorComponent
오브젝트 풀을 담당
할 컴포넌트
액터를 미리 생성해
놓고, 액터를 반환
해줄 기능을 담당
ObjectWithinPool에
서 사용
20. - 풀에 담을 오브젝트를 컨트롤할 액터
클래스를 생성합니다.
- 활성/비활성이 가능하도록 멤버 변수
및 함수 생성 합니다.
- 일정 시간이 지나면 오브젝트를 자동으
로 비활성화 해주도록 액터의
SetLifeSpan을 오버라이드합니다.
실습03
20
22. - ObjectWithinPool 액터에 오브젝트 풀링 기능을 담당할 ActorComponent클래스
를 생성합니다.
- 정의할 기능으로는
1. 풀에서 오브젝트를 꺼내오는 기능
2. 오브젝트 풀에 담을 클래스 정의
3. 풀 사이즈만큼 오브젝트를 저장해놓을 Tarray를 정의.
실습03
22
25. - 실제 생성될 오브젝트를 정의합니다.
- BoxComponent를 RootComponent로 사용하기
위해 정의했습니다.
- 오브젝트 풀에서 오브젝트를 가져오기 위해
ObjectPool 객체를 선언하였습니다.
- 생명주기를 엔진에서 컨트롤 할 수 있도록
LifeSpan, SpawnCooldown을 UPROPERTY로, 그
리고 스폰 주기를 체크할 Timer를 선언했습니다.
- 생성할 때 사용할 함수 Spawn()을 선언해주었습
니다.
실습03
6
28. 실습03
28
- 캐릭터와 똑같은 모습
을 보여주기 위해
SkeletalMesh 컴포넌트
를 추가해서 캐릭터를
표현하고, 애니메이션
블루프린트를 추가해
Idle모션을 추가해주었
습니다.
- 정면을 바라볼 수 있
도록 Rotation Z축을 -90
도로 변경해주었습니다.
29. 실습03
29
- 마지막으로 만들어놨던 SpawnObject 블루프
린트를 월드에 배치해줍니다.
- C++에서 ObjectPool ActorComponent를 생성
해줬기 때문에 디테일 패널에 추가가 되있는 것
을 볼 수 있습니다.
- 좀 더 빠른 재생성을 보여드리기 위해
LifeSpan과 Spawn Cooldown의 값을 일부 조절
했습니다.
32. - 오브젝트 풀링의 구현 방법은 게임마다, 또는 상황마다 상이하므로 때
에 맞춰 구현하시면 됩니다.
- 핵심은 이미 있는, 또는 미리 만들어 놓은 오브젝트를 재사용함으로써
오브젝트 생성과 삭제의 오버헤드를 피한다는 것입니다.
- 다시 한번 강조 드리지만 무조건적인 오브젝트 풀링 방법의 채용은 좋
은 방법은 아닙니다.
- 언제나 지속적인 프로파일링을 통해 필요한 요소에 최적의 풀링 개수
를 선택해서 적용하는 것이 가장 좋은 방법입니다.
마무리04
32