객체가 생성될 때 메모리에는 각 객체가 필요한 메모리 공간이 할당된다. 주로 인스턴시에이트로 객체를 생성하는 방식으로 사용했다.
또한 객체를 파괴할 때는 GC(가비지 컬렉터)가 할당을 해제시켜준다. 이는 디스트로이로 객체를 파괴하는 방식으로 사용했다.
객체의 생성과 파괴는 무척이나 편리한 기능이지만 자주 사용되면 최적화에 좋지 않은 영향을 끼치는데,
생성과 파괴를 자주하게되면 메모리 단편화가 일어 날 수가 있다.
메모리 공간이 존재하긴 하나 할당이 불가능한 경우를 말한다. 주로 내부 단편화, 외부 단편화로 구분되어진다.
이렇듯 무분별한 생성과 파괴는 메모리에 부담을, GC가 자주 활성화되어 일시적인 성능저하, 프레임 드랍등 게임에 영향을 크게 미치는 최적화 악영향을 줄 수 있기 때문에 오브젝트 풀이라는 디자인 패턴으로 객체를 효율적으로 관리하는 기법을 사용한다.
오브젝트 풀은 미리 할당된 공간에 여러 객체를 생성시키고 활성화, 비활성화 하면서 넣었다 뺐다 하듯이 재사용하는 디자인 패턴을 말한다.
아주 큰 상자에 여러가지 도구를 담고, 도구가 필요할 때 마다 가져왔다가 필요 없으면 다시 상자로 넣기.
FPS에서 총알을 발사하는데 굳이 총알을 만들고 삭제하고 할 필요 없이 총알을 미리 생성한 후 총을 발사하면 총알을 나타내고
총알이 사라지면 총알을 비활성화해 불필요한 삭제를 방지 (오브젝트 객체 뿐만이 아닌 맵, 이펙트도 같은 방식으로 사용가능)
using UnityEngine;
using System.Collections.Generic;
public Class ObjPool : MonoBehavior
{
[SerializeField] GameObject objPrefab;
[SerializeField] int objCount = 5;
private Queue<GameObject> myPool;
private void Awake()
{
//큐를 초기화
myPool = new Queue<GameObject>();
for(int i = 0; i<objCount; i++)
{
GameObject obj = Istantiate(objPrefab);
//게임 오브젝트를 비활성화하여 큐에 추가
obj.SetActive(false);
myPool.Enqueue(obj);
}
}
GameObject GetObj()
{
//만약 큐에 오브젝트가 존재한다면
if(myPool.Count > 0)
{
GameObject orb = myPool.Dequeue();
orb.gameObject.SetActive(true);
return orb;
}
//만약 프리팹을 더 추가해야할 경우
GameObject newOrb = Instantiate(objPrefab);
return newOrb;
}
public void ReturnBullet(GameObject obj)
{
//오브젝트를 비활성화
obj.SetActive(false);
myPool.Enqueue(obj);
}
}
using UnityEngine;
using UnityEngine.Pool;
public Class ObjPool : MonoBehaviour
{
//생성할 프리팹 지정
[SerializeField] GameObject toInstantiate;
private ObjectPool<GameObject> myPool;
private void Start()
{
//오브젝트 풀 초기화
myPool = new ObjectPool<GameObject>
(
//각 함수를 람다식으로 표현, 인자값에 명명된 인수를 반영
// 오브젝트 생성 시 호출되는 함수
createFunc: () => Instantiate(toInstantiate),
//오브젝트를 가져올 때 호출되는 함수
actionOnget: obj => obj.SetActive(true),
//오브젝트를 반납될 때 호출되는 함수
actionOnRelease: obj => obj.SetActive(false),
//오브젝트 파괴될 때 호출되는 함수
actionOnDestroy: obj => Destroy(obj.gameObject)
);
}
//오브젝트 가져오기
public GameObject GetObj()
{
return myPool.Get();
}
//오브젝트 반납하기
public void ReleaseObj(GameObject obj)
{
myPool.Release(obj);
}
}