Top 38 유니티 오브젝트 풀링 24555 Votes This Answer

You are looking for information, articles, knowledge about the topic nail salons open on sunday near me 유니티 오브젝트 풀링 on Google, you do not find the information you need! Here are the best content compiled and compiled by the toplist.prairiehousefreeman.com team, along with other related topics such as: 유니티 오브젝트 풀링 오브젝트 풀링 단점, 유니티 2021 오브젝트 풀링, Unity 2d object pooling, Unity-object pool GitHub, 유니티 메모리풀링, Unity material pooling, 유니티 자식 오브젝트 생성, 유니티 오브젝트 생성


[유니티 강좌] 유용한 스킬 배우기 Skill 1 : 오브젝트 풀링
[유니티 강좌] 유용한 스킬 배우기 Skill 1 : 오브젝트 풀링


[Unity3D] Programming – 오브젝트 풀링 기법 구현하기 :: 베르의 프로그래밍 노트

  • Article author: wergia.tistory.com
  • Reviews from users: 40951 ⭐ Ratings
  • Top rated: 4.5 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about [Unity3D] Programming – 오브젝트 풀링 기법 구현하기 :: 베르의 프로그래밍 노트 오브젝트 풀링 기법은 특히 메모리가 부족하고 CPU의 성능이 낮은 디바이스의 사양이 낮았던 예전에 주로 사용되었던 기법이지만, 현재에 와서도 게임의 … …
  • Most searched keywords: Whether you are looking for [Unity3D] Programming – 오브젝트 풀링 기법 구현하기 :: 베르의 프로그래밍 노트 오브젝트 풀링 기법은 특히 메모리가 부족하고 CPU의 성능이 낮은 디바이스의 사양이 낮았던 예전에 주로 사용되었던 기법이지만, 현재에 와서도 게임의 … Programming – 오브젝트 풀링 기법 작성 기준 버전 :: 2019.2 프로그래밍에서 오브젝트를 생성하거나 파괴하는 작업은 꽤나 무거운 작업으로 분류된다. 오브젝트 생성은 메모리를 새로 할당하고 리소스를 로드하는..내가 하는 프로그래밍 공부
    그리고 그 외의 여러가지들
  • Table of Contents:
[Unity3D] Programming – 오브젝트 풀링 기법 구현하기

티스토리툴바

[Unity3D] Programming - 오브젝트 풀링 기법 구현하기 :: 베르의 프로그래밍 노트
[Unity3D] Programming – 오브젝트 풀링 기법 구현하기 :: 베르의 프로그래밍 노트

Read More

유니티 – 오브젝트 풀링(Object Pooling) | Rito15

  • Article author: rito15.github.io
  • Reviews from users: 5611 ⭐ Ratings
  • Top rated: 4.2 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 유니티 – 오브젝트 풀링(Object Pooling) | Rito15
    오브젝트 풀링의 개념은 간단하다. 게임오브젝트를 파괴하는 대신 비활성화하여 풀에 넣고,. 생성하는 대신 풀에서 꺼내어 활성화하면 된다. 따라서 … …
  • Most searched keywords: Whether you are looking for 유니티 – 오브젝트 풀링(Object Pooling) | Rito15
    오브젝트 풀링의 개념은 간단하다. 게임오브젝트를 파괴하는 대신 비활성화하여 풀에 넣고,. 생성하는 대신 풀에서 꺼내어 활성화하면 된다. 따라서 … 1. 목표 오브젝트 풀링 기법 이해하기
  • Table of Contents:
[1] 오브젝트 풀링

[2] 다중 풀링

[3] 샘플 오브젝트

[4] Key 선택

[5] GC 문제 해결을 위한 2가지 방법

[1] Key 타입

[2] PoolObjectData 클래스

[3] PoolObject 클래스

[4] ObjectPoolManager 클래스

ObjectPoolManager 클래스

[1] Register API 제공

[2] 풀 한도 이상의 오브젝트 점진적 파괴

[3] 관계 없는 게임오브젝트에 대한 Despawn 처리

[4] 지정된 시간 후 Despawn 기능

Don’t Destroy On Load

유니티 - 오브젝트 풀링(Object Pooling) | Rito15
유니티 – 오브젝트 풀링(Object Pooling) | Rito15

Read More

오브젝트 풀링(Object Pooling)이란?

  • Article author: whiny.tistory.com
  • Reviews from users: 3222 ⭐ Ratings
  • Top rated: 4.8 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 오브젝트 풀링(Object Pooling)이란? 할당과 해제는 CPU가 담당하고, CPU에 부담이 오브젝트가 많아질수록 더해지게 됩니다. 게다가 유니티에서 메모리 해제를 하며 가비지 컬렉터가 발생 … …
  • Most searched keywords: Whether you are looking for 오브젝트 풀링(Object Pooling)이란? 할당과 해제는 CPU가 담당하고, CPU에 부담이 오브젝트가 많아질수록 더해지게 됩니다. 게다가 유니티에서 메모리 해제를 하며 가비지 컬렉터가 발생 … 이번 포스팅에서는 다양한 최적화 기법들 중에서 오브젝트 풀링(Object Pooling)에 관해서 알아보겠습니다. 간단하게 오브젝트 풀링을 설명하자면, 오브젝트의 Pool 즉 웅덩이를 만들어두고, 그 웅덩이 안에서 필..복습하며 정리하고 있습니다.
  • Table of Contents:

오브젝트 풀링(Object Pooling)이란

티스토리툴바

오브젝트 풀링(Object Pooling)이란?
오브젝트 풀링(Object Pooling)이란?

Read More

Object Pooling 유니티에서 이용하기

  • Article author: luv-n-interest.tistory.com
  • Reviews from users: 24689 ⭐ Ratings
  • Top rated: 3.3 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about Object Pooling 유니티에서 이용하기 [Game Developer, 게임개발자/디자인패턴] – Object Pool, 오브젝트 풀, 객체 풀 [디자인패턴](최적화) 더군다나 Unity.. …
  • Most searched keywords: Whether you are looking for Object Pooling 유니티에서 이용하기 [Game Developer, 게임개발자/디자인패턴] – Object Pool, 오브젝트 풀, 객체 풀 [디자인패턴](최적화) 더군다나 Unity.. Object Pooling은 많이 들어봤고 디자인 패턴 중에 가장 이해하기 쉬운 것이라고 생각한다. [Game Developer, 게임개발자/디자인패턴] – Object Pool, 오브젝트 풀, 객체 풀 [디자인패턴](최적화) 더군다나 Unity..기술: C++, C#, Unity, Unreal, DX ++ devops k8s
    관심분야: 새로운 컨텐츠를 구현하는게 제일 재밌는 것 이라고 생각하고 있으며 이미 있는 것에 대해 최적화 또는 리팩토링하는데에 관심이 있습니다(엔진 튜닝 또는 커스터마이징) 하지만 개발은 항상 힘이 듭니다. 그래서 포기하고 싶을 때도 많지만 내일 또다시 시도해봅니다.
    요즘엔 새로운 것에 눈을 떴습니다.
  • Table of Contents:

Object Pooling 유니티에서 이용하기

티스토리툴바

Object Pooling 유니티에서 이용하기
Object Pooling 유니티에서 이용하기

Read More

Introduction to Object Pooling – Unity Learn

  • Article author: learn.unity.com
  • Reviews from users: 21565 ⭐ Ratings
  • Top rated: 4.3 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about Introduction to Object Pooling – Unity Learn Object Pooling is a great way to optimize your projects and lower the burden that is placed on the CPU when having to raply create and … …
  • Most searched keywords: Whether you are looking for Introduction to Object Pooling – Unity Learn Object Pooling is a great way to optimize your projects and lower the burden that is placed on the CPU when having to raply create and … ,Scripts,C++,Scripting,Code,Pooling,C#,Object PoolingObject Pooling is a great way to optimize your projects and lower the burden that is placed on the CPU when having to rapidly create and destroy GameObjects. It is a good practice and design pattern to keep in mind to help relieve the processing power of the CPU to handle more important tasks and not become inundated by repetitive create and destroy calls. In this tutorial, you will learn to use Object Pooling to optimize your projects.
  • Table of Contents:
Introduction to Object Pooling - Unity Learn
Introduction to Object Pooling – Unity Learn

Read More

[Unity] Object Pooling (오브젝트 풀링)

  • Article author: a6ly.dev
  • Reviews from users: 21560 ⭐ Ratings
  • Top rated: 5.0 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about [Unity] Object Pooling (오브젝트 풀링) 오브젝트 풀링의 사용 이유 : 오브젝트의 생성과 파괴는 부하가 크고, 오브젝트의 파괴는 GC(Garbage Collector : 가비지 컬렉터)를 발생시켜 성능을 … …
  • Most searched keywords: Whether you are looking for [Unity] Object Pooling (오브젝트 풀링) 오브젝트 풀링의 사용 이유 : 오브젝트의 생성과 파괴는 부하가 크고, 오브젝트의 파괴는 GC(Garbage Collector : 가비지 컬렉터)를 발생시켜 성능을 … 오브젝트 풀링의 사용 이유 : 오브젝트의 생성과 파괴는 부하가 크고, 오브젝트의 파괴는 GC(Garbage Collector : 가비지 컬렉터)를 발생시켜 성능을 저하시킨다. 따라서 게임을 할 때 생성, 파괴가 반복되는 오브..
  • Table of Contents:
[Unity] Object Pooling (오브젝트 풀링)
[Unity] Object Pooling (오브젝트 풀링)

Read More

유니티 – 오브젝트 풀링(Object pooling)

  • Article author: geojun.tistory.com
  • Reviews from users: 40426 ⭐ Ratings
  • Top rated: 4.3 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 유니티 – 오브젝트 풀링(Object pooling) 오브젝트 풀링은 유니티에서 자주 사용되는 오브젝트를 생성과 파괴가 아닌 리스트(List)나 큐(Queue) 등에 저장해 두고 불러와 사용하고 사용 후엔 … …
  • Most searched keywords: Whether you are looking for 유니티 – 오브젝트 풀링(Object pooling) 오브젝트 풀링은 유니티에서 자주 사용되는 오브젝트를 생성과 파괴가 아닌 리스트(List)나 큐(Queue) 등에 저장해 두고 불러와 사용하고 사용 후엔 … 오브젝트 풀링은 유니티에서 자주 사용되는 오브젝트를 생성과 파괴가 아닌 리스트(List)나 큐(Queue) 등에 저장해 두고 불러와 사용하고 사용 후엔 다시 반납하는 역할을 합니다. 유니티에서 ObjectPool이란 이..
  • Table of Contents:

태그

‘Unity’ Related Articles

공지사항

최근 포스트

태그

검색

전체 방문자

티스토리툴바

유니티 - 오브젝트 풀링(Object pooling)
유니티 – 오브젝트 풀링(Object pooling)

Read More

유니티 오브젝트 풀링(Unity object pooling)

  • Article author: doho-tech.tistory.com
  • Reviews from users: 21802 ⭐ Ratings
  • Top rated: 3.0 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about 유니티 오브젝트 풀링(Unity object pooling) 유니티 오브젝트 풀링(Unity object pooling). Doho_K 2021. 6. 3. 15:26. 오늘은 오브젝트 풀링을 쉬운 방법으로 만들어 보겠습니다. …
  • Most searched keywords: Whether you are looking for 유니티 오브젝트 풀링(Unity object pooling) 유니티 오브젝트 풀링(Unity object pooling). Doho_K 2021. 6. 3. 15:26. 오늘은 오브젝트 풀링을 쉬운 방법으로 만들어 보겠습니다. 오늘은 오브젝트 풀링을 쉬운 방법으로 만들어 보겠습니다. 총알같이 자주 생성되고 제거되는 오브젝트들은 생성하고 제거를 계속 반복하기에는 메모리에 부담이 됩니다. 렉이 잘 걸릴수 있다는 거죠. 이를 방지하..유니티 초보 개발자입니다.
    공부하면서 드는 생각과 참고하면 좋은 자료를 업로드합니다
  • Table of Contents:
유니티 오브젝트 풀링(Unity object pooling)
유니티 오브젝트 풀링(Unity object pooling)

Read More

[Unity] 211103(47일) – 오브젝트 풀링(object pooling)

  • Article author: narasee.tistory.com
  • Reviews from users: 18897 ⭐ Ratings
  • Top rated: 4.7 ⭐
  • Lowest rated: 1 ⭐
  • Summary of article content: Articles about [Unity] 211103(47일) – 오브젝트 풀링(object pooling) [Unity] 211103(47일) – 오브젝트 풀링(object pooling) … 오브젝트 풀링은 메모리 할당과 해제에 들어가는 메모리 파편화를 방지하기 위해 미리 … …
  • Most searched keywords: Whether you are looking for [Unity] 211103(47일) – 오브젝트 풀링(object pooling) [Unity] 211103(47일) – 오브젝트 풀링(object pooling) … 오브젝트 풀링은 메모리 할당과 해제에 들어가는 메모리 파편화를 방지하기 위해 미리 … 211103 211104 211110 211203 오브젝트 풀링(Object Pooling) 풀링 대상에는 OnEnable 오브젝트 풀링은 메모리 할당과 해제에 들어가는 메모리 파편화를 방지하기 위해 미리 오브젝트들을 생성해놓고 활성화, 비활..
  • Table of Contents:

나라씨

[Unity] 211103(47일) – 오브젝트 풀링(object pooling) 본문

티스토리툴바

[Unity] 211103(47일) - 오브젝트 풀링(object pooling)
[Unity] 211103(47일) – 오브젝트 풀링(object pooling)

Read More


See more articles in the same category here: Top 159 tips update new.

[Unity3D] Programming – 오브젝트 풀링 기법 구현하기

Programming

오브젝트 풀링 기법

작성 기준 버전 :: 2019.2

프로그래밍에서 오브젝트를 생성하거나 파괴하는 작업은 꽤나 무거운 작업으로 분류된다. 오브젝트 생성은 메모리를 새로 할당하고 리소스를 로드하는 등의 초기화하는 과정으로, 오브젝트 파괴는 파괴 이후에 발생하는 가비지 컬렉팅으로 인한 프레임 드랍이 발생할 수 있다.

이러한 문제를 해결하기 위해서 사용되는 기법이 바로 오브젝트 풀링(Object pooling)이다.

오브젝트 풀링의 개념

오브젝트 풀링의 개념은 아주 간단하다.

먼저 풀링을 할 오브젝트를 담을 오브젝트 풀을 구성한다.

그 다음 풀링할 오브젝트를 생성해서 오브젝트 풀에서 그 오브젝트들을 관리하게 만든다.

외부에서 해당 오브젝트가 필요하면 오브젝트 풀에서 꺼내간다.

오브젝트 풀에서 꺼낸 오브젝트의 사용이 끝나면 오브젝트를 풀에 돌려준다.

오브젝트 풀에서 오브젝트를 가져오려고 할 때, 모든 오브젝트가 이미 사용중이라면 새로운 오브젝트를 생성해서 꺼내준다.

이것이 바로 오브젝트 풀의 개념이다. 게임에 필요한 오브젝트를 미리 생성해서 필요할 때마다 꺼내쓰고 사용이 끝나면 오브젝트 풀에 돌려주는 것이다. 이렇게 함으로써, 오브젝트가 필요할 때마다 생성하고 다 쓰면 파괴하는 것이 아니라, 게임이 시작될 때, 필요한 만큼의 오브젝트만 생성하고, 모자라면 추가로 생성하고, 게임이 끝나면 파괴하는 방식으로 오브젝트의 생성/파괴 횟수를 줄일 수 있게 된다.

오브젝트 풀링 기법은 특히 메모리가 부족하고 CPU의 성능이 낮은 디바이스의 사양이 낮았던 예전에 주로 사용되었던 기법이지만, 현재에 와서도 게임의 최적화를 위해서 많이 사용되며, 모바일 게임이 많이 제작되면서 PC에 비해서 모자란 디바이스 성능으로 인해서 재조명 받는 기법이다.

보통 자주 생성되었다가 파괴되어야 하는 총알이나, 캐릭터가 뛸 때 발생하는 먼지 이펙트 같은 곳에 많이 사용되는 기법이다.

유니티 엔진에서의 구현

기본 세팅

기본적인 세팅은 다음과 같다.

씬 한 가운데 캐릭터의 역할을 할 초록색 박스를 배치했다.

public class Shooter : MonoBehaviour { [SerializeField] private GameObject bulletPrefab; private Camera mainCam; void Start() { mainCam = Camera.main; } void Update() { if(Input.GetMouseButton(0)) { RaycastHit hitResult; if(Physics.Raycast(mainCam.ScreenPointToRay(Input.mousePosition), out hitResult)) { var bullet = Instantiate(bulletPrefab).GetComponent(); var direction = new Vector3(hitResult.point.x, transform.position.y, hitResult.point.z) – transform.position; bullet.transform.position = direction.normalized; bullet.Shoot(direction.normalized); } } } }

그리고 박스 게임 오브젝트에는 마우스 클릭 방향으로 총알 게임 오브젝트를 생성해서 발사하는 Shooter 컴포넌트가 부착되어 있다.

public class Bullet : MonoBehaviour { private Vector3 direction; public void Shoot(Vector3 direction) { this.direction = direction; Destroy(gameObject, 5f); } void Update() { transform.Translate(direction); } }

그리고 지정된 방향으로 5초 간 날아가다 자동으로 소멸하는 총알 프리팹 역시 만들어두었다.

이것을 테스트 해보면 마우스를 클릭하면 엄청난 양의 총알 오브젝트가 새로 생성되고 시간이 지나면 모두 파괴되는 것을 볼 수 있다.

이 상황을 프로파일러를 통해서 확인해보면 총알을 생성하는 Instantiate와 파괴하는 Destroy가 어느 정도 성능을 잡아먹고 있는 것을 확인할 수 있다.

오브젝트 풀 구현

public class ObjectPool : MonoBehaviour { public static ObjectPool Instance; [SerializeField] private GameObject poolingObjectPrefab; Queue poolingObjectQueue = new Queue(); private void Awake() { Instance = this; Initialize(10); } private void Initialize(int initCount) { for(int i = 0; i < initCount; i++) { poolingObjectQueue.Enqueue(CreateNewObject()); } } private Bullet CreateNewObject() { var newObj = Instantiate(poolingObjectPrefab).GetComponent(); newObj.gameObject.SetActive(false); newObj.transform.SetParent(transform); return newObj; } public static Bullet GetObject() { if(Instance.poolingObjectQueue.Count > 0) { var obj = Instance.poolingObjectQueue.Dequeue(); obj.transform.SetParent(null); obj.gameObject.SetActive(true); return obj; } else { var newObj = Instance.CreateNewObject(); newObj.gameObject.SetActive(true); newObj.transform.SetParent(null); return newObj; } } public static void ReturnObject(Bullet obj) { obj.gameObject.SetActive(false); obj.transform.SetParent(Instance.transform); Instance.poolingObjectQueue.Enqueue(obj); } }

오브젝트 풀링 기법을 구현하는 기초적인 코드의 전체는 위의 코드와 같다.

public static ObjectPool Instance; private void Awake() { Instance = this; Initialize(10); }

이 코드를 하나씩 살펴보자. 우선 오브젝트 풀의 경우 오브젝트를 생성하는 어떤 코드에서든 접근이 가능해야하는 경우가 많기 때문에 싱글톤 패턴으로 구현되는 경우가 많다.

[SerializeField] private GameObject poolingObjectPrefab;

그리고 생성해야할 오브젝트의 프리팹을 가지고 있다. 프리팹을 가지고 있어야 하는 이유는 처음 생성해둔 오브젝트를 모두 꺼내주고 나서, 꺼내준 오브젝트를 미처 돌려받기 전에, 오브젝트를 요청받았을 때, 새로운 오브젝트를 생성해서 꺼내주기 위한 것이다.

Queue poolingObjectQueue = new Queue();

큐(Queue)를 이용해서 생성된 총알 오브젝트를 순서대로 관리한다. 만약 오브젝트 풀에서 오브젝트를 꺼내주는 순서와 돌려받는 순서를 제대로 관리하지 못하면, 하나의 오브젝트를 여러 곳에 빌려주는 등의 문제가 발생할 수 있다.

private void Awake() { Instance = this; Initialize(10); }

게임 오브젝트가 생성되면 제일 먼저 실행되는 Awake() 함수에서는 싱글톤 패턴에서 사용되는 오브젝트 풀 인스턴스에 자신을 할당하는 일과 오브젝트 풀을 초기화하는 Initialize() 함수를 호출한다.

private void Initialize(int initCount) { for(int i = 0; i < initCount; i++) { poolingObjectQueue.Enqueue(CreateNewObject()); } } Initialze() 함수에서는 매개변수로 받은 초기화 갯수 값에 따라서 CreateNewObject() 함수에서 만들어진 새로운 총알 오브젝트를 pooling Object Queue에 넣어준다. 이렇게 게임이 시작하기 전에 사용될 게임 오브젝트를 미리 적절한 갯수를 만들어 줌으로써 게임 플레이 도중에 발생할 과부하를 게임 준비 과정인 로딩으로 돌릴 수 있다. 모두 잘 알겠지만, 플레이어는 아주 조금 더 긴 로딩은 당장 용납하지만, 플레이 도중에 발생하는 렉은 용납하지 못한다. private Bullet CreateNewObject() { var newObj = Instantiate(poolingObjectPrefab).GetComponent(); newObj.gameObject.SetActive(false); newObj.transform.SetParent(transform); return newObj; }

CreateNewObject() 함수는 poolingObjectPrefab으로부터 새 게임 오브젝트를 만든 뒤 비활성화해서 반환하는 역할을 한다. 이렇게 곧바로 비활성화하는 이유는 아직 오브젝트 풀이 꺼내주지 않은 오브젝트는 비활성화된 것으로써 플레이어의 눈에 띄지 않아야하기 때문이다.

public static Bullet GetObject() { if(Instance.poolingObjectQueue.Count > 0) { var obj = Instance.poolingObjectQueue.Dequeue(); obj.transform.SetParent(null); obj.gameObject.SetActive(true); return obj; } else { var newObj = Instance.CreateNewObject(); newObj.gameObject.SetActive(true); newObj.transform.SetParent(null); return newObj; } }

GetObject() 함수는 오브젝트 풀이 가지고 있는 게임 오브젝트를 요청한 자에게 꺼내주는 역할을 한다. 단, 모든 오브젝트를 꺼내서 빌려줘서 poolingObjectQueue에 빌려줄 오브젝트가 없는 상태라면 CreateNewObject() 함수를 호출해서 새로운 오브젝트를 생성해서 빌려준다.

public static void ReturnObject(Bullet obj) { obj.gameObject.SetActive(false); obj.transform.SetParent(Instance.transform); Instance.poolingObjectQueue.Enqueue(obj); }

ReturnObject() 함수는 빌려준 오브젝트를 돌려받는 함수이다. 돌려받은 오브젝트를 비활성화한 뒤 정리하는 일을 처리한다.

무엇이든지 빌려줬으면 돌려받아야 한다. 이 원칙은 프로그래밍에서도 매우 중요한 원칙으로 사용한 오브젝트를 제대로 돌려받지 않으면 GetObject() 함수를 호출할 때, 계속해서 새로운 오브젝트를 생성하고 사라지지 않은 오브젝트들이 씬에 쌓이게 된다. 이것이 바로 메모리 누수이다.

코드 작성이 끝나면 씬에 새 게임 오브젝트를 배치하고 오브젝트 풀 컴포넌트를 부착하고 pooling Object Prefab 프로퍼티에 풀링해야할 게임 오브젝트의 프리팹을 할당해주면 된다.

그 다음에는 총알 오브젝트를 생성하는 부분과 파괴하는 부분을 수정해야 한다.

public class Shooter : MonoBehaviour { void Update() { if(Input.GetMouseButton(0)) { RaycastHit hitResult; if(Physics.Raycast(mainCam.ScreenPointToRay(Input.mousePosition), out hitResult)) { var bullet = ObjectPool.GetObject(); // 수정 var direction = new Vector3(hitResult.point.x, transform.position.y, hitResult.point.z) – transform.position; bullet.transform.position = direction.normalized; bullet.Shoot(direction.normalized); } } } }

우선 생성하는 부분은 Shooter 클래스의 Update() 함수에 Instanitate()로 총알을 생성하던 부분을 ObjectPool.GetObject()로 대체하면 된다.

public class Bullet : MonoBehaviour { private Vector3 direction; public void Shoot(Vector3 direction) { this.direction = direction; Invoke(“DestroyBullet”, 5f); } public void DestroyBullet() { ObjectPool.ReturnObject(this); } void Update() { transform.Translate(direction); } }

그 다음 파괴하는 부분은 Bullet 클래스에서 DestoryBullet() 함수에서 ObjectPool.ReturnObject()를 호출해서 오브젝트 풀에 돌려주도록 구현하고 Shoot() 함수에서 Destory() 함수를 호출하던 부분을 Invoke()로 5초 뒤에 DestoryBullet() 함수를 호출하도록 수정한다.

플레이를 해서 테스트 해보면 총알이 일정 갯수만큼 생성되고 나면 더 이상 생성되지 않으며, 시간이 지나면 소멸되어야 하는 총알 오브젝트들이 비활성화되서 오브젝트 풀로 반환되는 것을 확인할 수 있다.

프로파일러를 통해서 확인해보면 최대 생성량에 도달한 이후에는 Instatiate와 Destroy로 인한 작업이 발생하지 않는 것을 볼 수 있다.

[유니티 어필리에이트 프로그램]

아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.

[투네이션] [Patreon] [디스코드 채널]

반응형

유니티 – 오브젝트 풀링(Object Pooling)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244

///

복제된 오브젝트의 예약 정보

private class CloneScheduleInfo { public readonly GameObject clone ; public readonly Stack < GameObject > pool ; public bool DespawnScheduled => _despawnScheduled ; private bool _despawnScheduled ; private int _scheduleVersion ; public CloneScheduleInfo ( GameObject clone , Stack < GameObject > pool ) { this . clone = clone ; this . pool = pool ; this . _despawnScheduled = false ; this . _scheduleVersion = 0 ; } ///

Despawn 예약하고 버전 반환

public int ScheduleToDespawn () { _despawnScheduled = true ; _scheduleVersion ++; return _scheduleVersion ; } ///

예약 취소

public void CancelSchedule () { if ( _despawnScheduled == false ) return ; _despawnScheduled = false ; _scheduleVersion ++; } ///

예약 유효성 검증

public bool IsScheduleValid ( int prevVersion ) { return _despawnScheduled && ( prevVersion == _scheduleVersion ); } } // 복제된 게임오브젝트 – 클론 정보 private Dictionary < GameObject , CloneScheduleInfo > _cloneDict ; // 디스폰 스케줄링 동기화 큐 private readonly ConcurrentQueue < CloneScheduleInfo > _despawnScheduleQueue = new ConcurrentQueue < CloneScheduleInfo >(); private void Init () { // Codes.. _sampleDict = new Dictionary < KeyType , GameObject >( len ); _dataDict = new Dictionary < KeyType , PoolObjectData >( len ); _poolDict = new Dictionary < KeyType , Stack < GameObject >>( len ); // 추가 _cloneDict = new Dictionary < GameObject , CloneScheduleInfo >( len * PoolObjectData . INITIAL_COUNT ); // Codes.. } private void RegisterInternal ( PoolObjectData data ) { // Codes… Stack < GameObject > pool = new Stack < GameObject >( data . maxObjectCount ); for ( int i = 0 ; i < data . initialObjectCount ; i ++) { GameObject clone = Instantiate ( data . prefab ); clone . SetActive ( false ); pool . Push ( clone ); // 추가 _cloneDict . Add ( clone , new CloneScheduleInfo ( clone , pool )); } // Codes... } public GameObject Spawn ( KeyType key ) { // Codes... if ( pool . Count > 0 ) { go = pool . Pop (); DebugLog ( _debugSpawn , $”Spawn : { go . name } ( { go . GetInstanceID ()} )” ); } else { go = CloneFromSample ( key ); DebugLog ( _debugSpawn , $”Spawn[Create] : { go . name } ( { go . GetInstanceID ()} )” ); // 추가 _cloneDict . Add ( go , new CloneScheduleInfo ( go , pool )); } // Codes… return go ; } ///

Despawn 실제 처리

private void DespawnInternal ( CloneScheduleInfo data ) { // 예약되어 있던 경우, 해제 data . CancelSchedule (); // 풀에 집어넣기 data . clone . SetActive ( false ); data . pool . Push ( data . clone ); TestModeOnly (() => { KeyType key = _t_poolKeyDict [ data . pool ]; // 컨테이너 자식으로 넣기 data . clone . transform . SetParent ( _t_ContainerDict [ key ]. transform ); // 컨테이너 이름 변경 Test_ChangeContainerName ( key ); }); } ///

풀에 집어넣기

public void Despawn ( GameObject go ) { if ( go == null ) return ; if ( go . activeSelf == false ) return ; // 복제된 게임오브젝트가 아닌 경우 – 정책에 따라 처리 if (! _cloneDict . TryGetValue ( go , out var cloneData )) { switch ( _nonePoolObjectDespawnPolicy ) { case NonePoolObjectDespawnPolicy . Ignore : DebugLog ( _debugDespawn , $”풀에서 제공된 오브젝트가 아닙니다 : { go . name } ” ); break ; case NonePoolObjectDespawnPolicy . ThrowException : throw new ArgumentException ( $”풀에서 제공된 오브젝트가 아닙니다 : { go . name } ” ); case NonePoolObjectDespawnPolicy . Destroy : DebugLog ( _debugDespawn , $”풀에서 제공하지 않은 오브젝트를 파괴합니다 : { go . name } ( { go . GetInstanceID ()} )” ); Destroy ( go ); break ; } return ; } DespawnInternal ( cloneData ); DebugLog ( _debugDespawn && cloneData . DespawnScheduled , $”Despawn 예약 해제 및 즉시 실행 : { go . name } ( { go . GetInstanceID ()} )” ); DebugLog ( _debugDespawn && ! cloneData . DespawnScheduled , $”Despawn : { go . name } ( { go . GetInstanceID ()} )” ); } ///

n초 후 풀에 집어넣기

public void Despawn ( GameObject go , float seconds ) { if ( go == null ) return ; if ( go . activeSelf == false ) return ; int version ; // 1. 풀에서 제공한 오브젝트가 아닌 경우 – 정책에 따라 처리 if ( _cloneDict . TryGetValue ( go , out CloneScheduleInfo data ) == false ) { switch ( _nonePoolObjectDespawnPolicy ) { case NonePoolObjectDespawnPolicy . Ignore : DebugLog ( _debugDespawn , $”풀에서 제공된 오브젝트가 아닙니다 : { go . name } ” ); break ; case NonePoolObjectDespawnPolicy . ThrowException : throw new ArgumentException ( $”풀에서 제공된 오브젝트가 아닙니다 : { go . name } ” ); case NonePoolObjectDespawnPolicy . Destroy : DebugLog ( _debugDespawn , $”풀에서 제공하지 않은 오브젝트를 { seconds } 초 후 파괴합니다 : { go . name } ( { go . GetInstanceID ()} )” ); Destroy ( go , seconds ); break ; } return ; } // 2. 풀에서 제공한 오브젝트가 맞는 경우 else { // 0초 이하로 설정한 경우, 즉시 풀에 집어넣기 if ( seconds <= 0f ) { DespawnInternal ( data ); return ; } DebugLog ( _debugDespawn && ! data . DespawnScheduled , $" { seconds } 초 후 Despawn 예약 : { go . name } ( { go . GetInstanceID ()} )" ); DebugLog ( _debugDespawn && data . DespawnScheduled , $" { seconds } 초 후 Despawn 예약[갱신] : { go . name } ( { go . GetInstanceID ()} )" ); // 정상 : 예약 설정 version = data . ScheduleToDespawn (); } // 예약 Task . Run ( async () => { int prevVersion = version ; await Task . Delay (( int )( seconds * 1000 )); // 예약 정보가 유효한 경우, 큐에 넣기 if ( go != null && data . IsScheduleValid ( prevVersion )) { _despawnScheduleQueue . Enqueue ( data ); } }); } ///

Despawn 예약된 오브젝트들 확인하여 처리

private void HandleScheduledDespawning () { if ( _despawnScheduleQueue . Count == 0 ) return ; while ( _despawnScheduleQueue . TryDequeue ( out CloneScheduleInfo data )) { // 예약이 취소된 경우, 종료 if ( data . DespawnScheduled == false ) continue ; // —————————————— DespawnInternal ( data ); #if DEBUG_ON if ( _debugOn && data != null && data . clone != null ) DebugLog ( _debugDespawn , $”예약된 Despawn 처리 : { data . clone . name } ( { data . clone . GetInstanceID ()} )” ); #endif } } private void Update () { HandleScheduledDespawning (); }

오브젝트 풀링(Object Pooling)이란?

이번 포스팅에서는 다양한 최적화 기법들 중에서 오브젝트 풀링(Object Pooling)에 관해서 알아보겠습니다.

간단하게 오브젝트 풀링을 설명하자면, 오브젝트의 Pool 즉 웅덩이를 만들어두고, 그 웅덩이 안에서 필요할 때마다

객체를 꺼내서 사용하는 것을 뜻합니다.

게임에서는 엄청나게 많고 다양한 오브젝트를 사용하는데, 이런 오브젝트들을 실시간으로 생성하고, 파괴하고를 반복하면 어떻게 어떻게 될까요?

수천수백의 오브젝트들이 게임상에서 등장하고 사라질 때, 새로 오브젝트들을 생성하고 거기에 파괴하면 메모리를 할당하고 해제하는 일이 반복될 것입니다.

할당과 해제는 CPU가 담당하고, CPU에 부담이 오브젝트가 많아질수록 더해지게 됩니다. 게다가 유니티에서 메모리 해제를 하며 가비지 컬렉터가 발생하는데, 많은 오브젝트를 파괴할수록 많은 가비지 컬렉터가 발생하고, 이는 CPU에 더 큰 부담이 됩니다.

그림으로 한번 볼까요?

생성, 파괴 반복하는 방식

오브젝트 풀링 방식

이번에는 직접 2가지 방식을 구현하여 비교해보도록 합시다.

먼저 생성, 파괴 반복하는 방식부터 구현해봅시다.

using System.Collections; using System.Collections.Generic; using UnityEngine; public class CubeSpawner : MonoBehaviour { public GameObject SpawnObject; // Start is called before the first frame update void Start() { StartCoroutine(“Spawn”); } IEnumerator Spawn() { yield return new WaitForSeconds(0.01f); Instantiate(SpawnObject); StartCoroutine(“Spawn”); } }

위 코드는 0.01초마다 오브젝트를 생성해주는 코드입니다.

using System.Collections; using System.Collections.Generic; using UnityEngine; public class MovingCube : MonoBehaviour { private Vector3 direction; void Start() { direction = new Vector3(Random.Range(-0.1f, 0.1f), Random.Range(-0.1f, 0.1f), Random.Range(-0.1f, 0.1f)); StartCoroutine(“DestroyObject”); } private void FixedUpdate() { transform.position += direction; } IEnumerator DestroyObject() { yield return new WaitForSeconds(4.0f); Destroy(gameObject); } }

위 코드는 생성되는 오브젝트를 랜덤한 방향으로 움직이고 4초 후에 파괴하는 코드입니다.

실행을 시키면?

평균 150 FPS 내외로 출력되고, 간혹 120 FPS까지 떨어지는 것을 확인할 수 있었습니다.

이번에는 오브젝트 풀링 방식을 구현해봅시다.

using System.Collections; using System.Collections.Generic; using UnityEngine; public class CubeController : MonoBehaviour { public GameObject CubeObject; public GameObject[] gameObjects; private int pivot = 0; void Start() { gameObjects = new GameObject[500]; for(int i = 0; i < 500; i++) { GameObject gameObject= Instantiate(CubeObject); gameObjects[i] = gameObject; gameObject.SetActive(false); } StartCoroutine("EnableCube"); } IEnumerator EnableCube() { yield return new WaitForSeconds(0.01f); gameObjects[pivot++].SetActive(true); if (pivot == 500) pivot = 0; StartCoroutine("EnableCube"); } } 위 코드는 시작할 때 풀을 구성할 500개의 객체를 미리 만들고, 0.01초 마다 하나씩 활성화시키는 코드입니다. pivot변수로 마지막 객체까지 활성화시켰다면 처음 객체로 다시 돌아가 활성화 시키기 시작합니다. using System.Collections; using System.Collections.Generic; using UnityEngine; public class MovingCube_Pool : MonoBehaviour { private Vector3 direction; private void OnEnable() { transform.position = new Vector3(0, 0, 0); StartCoroutine("DisableObject"); } void Start() { direction = new Vector3(Random.Range(-0.1f, 0.1f), Random.Range(-0.1f, 0.1f), Random.Range(-0.1f, 0.1f)); StartCoroutine("DisableObject"); } private void FixedUpdate() { transform.position += direction; } IEnumerator DisableObject() { yield return new WaitForSeconds(4.0f); gameObject.SetActive(false); } } 위 코드는 오브젝트를 랜덤한 방향으로 움직이고, 4초 후에 비활성화시키는 코드입니다. 실행을 시키면? 180~200 FPS정도의 성능을 보여줍니다. 간혹 200 FPS까지의 성능도 보여줍니다. 둘을 동시에 비교해봅시다. 생성 파괴 방식 오브젝트 풀링 단순한 Cube 오브젝트로 테스트를 진행해보았는데 이정도의 차이가 발생합니다. 실제 게임에서의 성능차는 엄청납니다. 몇개~ 몇십 개까지의 오브젝트 숫자 정도에서는 두 방식 모두 큰 차이가 없을 것입니다. 하지만, 오브젝트의 개수가 많아질수록 두 방식에 따른 차이는 점점 벌어집니다. 물론, 오브젝트 풀링 방식은 메모리를 할당 해두기 때문에 메모리를 희생하여 성능을 높이는 것이지만, 실시간으로 작동하는 게임에서의 프레임 차이는 무시할 수 없기 때문에 오브젝트 풀링 방식이 선호 됩니다.

So you have finished reading the 유니티 오브젝트 풀링 topic article, if you find this article useful, please share it. Thank you very much. See more: 오브젝트 풀링 단점, 유니티 2021 오브젝트 풀링, Unity 2d object pooling, Unity-object pool GitHub, 유니티 메모리풀링, Unity material pooling, 유니티 자식 오브젝트 생성, 유니티 오브젝트 생성

Leave a Comment