> 위 영상의 핵심은 영상의 후반으로 갈수록 하이어라키에 오브젝트들이 더 이상 늘어나지 않는다는점과
> 비활성화된 오브젝트가 다시 활성화 상태가되며 목적을 달성하면 다시 비활성화 상태가 된다는 점이다.
오브젝트 풀링?
오브젝트 풀링은 프로젝트를 최적화하고 게임 오브젝트를 빠르게 생성하고 파괴해야 할 때 CPU에 가해지는 부담을 줄이는 좋은 방법입니다. CPU의 처리 능력을 완화하여 더 중요한 작업을 처리하고 반복적인 생성 및 소멸 호출에 의해 범람되지 않도록 염두에 두는 것이 좋은 사례 및 디자인 패턴입니다.
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
|
//OBJPool.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//<T> Type으로 제한하기 위해 OBJPool<T>로 명시한다.
//오브젝트 풀을 제네릭 하기 위해 Component를 붙이는 제한조건을 둔다.
public class OBJPool<T> : MonoBehaviour where T : Component
{
//초기 오브젝트를 담는다.
[SerializeField] protected T[] mOrigin;
//풀링에 사용할 공간
protected List<T>[] mPool;
//오브젝트 풀 시스템을 초기화한다.
void Start()
{
mPool = new List<T>[mOrigin.Length];
for (int i = 0; i < mPool.Length; ++i)
{
mPool[i] = new List<T>();
}
}
//풀(mPool)로부터 오브젝트를 가져온다.
public T GetFromPool(int id = 0)
{
for (int i = 0; i < mPool[id].Count; ++i)
{
if (!mPool[id][i].gameObject.activeInHierarchy)
{
mPool[id][i].gameObject.SetActive(true);
return mPool[id][i];
}
}
return MakeNewInstance(id);
}
//풀(mPool)이 비어있거나, 현재 모든 오브젝트가 활성화 상태일경우 인스턴스한다.
protected virtual T MakeNewInstance(int id)
{
T newObj = Instantiate(mOrigin[id]);
mPool[id].Add(newObj);
return newObj;
}
}
|
cs |
public class OBJPool<T> : MonoBehaviour where T : Component
- 오브젝트 풀을 여러 타입으로 제네릭 하기위해 OBJPool<T>로 명시한다.
- where T : Component는 Component를 붙이는 제한조건을 두어 제네릭을 완성시킨다.
[SerializeField] protected T[] mOrigin
- 오브젝트 풀링 할 오브젝트를 담는 공간이다.
- [SerializeField]를 사용하여 에디터의 인스펙터에서 미리 지정해준다.
protected List<T>[] mPool
- [SerializeField] protected T[] mOrigin 에서 사용하는 변수들의 오브젝트들을 각 mPool[]에서 저장(보관) 하고 필요시 새로 담아서 관리한다.
void Start()
- mPool[]을 mOrigin의 개수만큼 초기화 시키고 List<T>로 초기화하여 사용 준비를 완료시킨다.
public T GetFromPool(int id = 0)
- mPool[]에서 오브젝트를 가져와 리턴한다.
- mPool[id].Count까지 loop하면서 mPool[]에 활성화되지 않은 오브젝트가 있으면 해당 오브젝트를 리턴한다.
- loop 하면서 모든 오브젝트가 활성화 된 상태이거나, mPool[]이 비어있으면 MakeNewInstance(id) 함수를 호출하며 리턴한다.
- MakeNewInstance는 오브젝트를 새로 인스턴스하여 mPool[]에 추가한다.
- 디폴트 매개변수 = 0은 mPool[]에서 몇번째에 있는 대상을 가져올지 지정한다. 예시로, 돌을 떨어뜨린다고 했을 때, 여러 모양의 돌을 지정하여 리턴할 수 있다.
protected virtual T MakeNewInstance(int id)
- T 타입의 오브젝트를 인스턴스하고 이것을 mPool[]에 삽입한다.
- mPool[]에서 더 이상 리턴할 오브젝트가 없을때 새로 생성하여 리턴할 수 있도록 하는것이다.
오브젝트 풀링 스크립트의 사용 _ 예시
해당 예시는 씬 중의 골렘의 공격 패턴 중 여러개의 돌을 떨어뜨리는 과정을 담는다.
1
2
3
4
5
6
7
8
9
10
11 |
//GolemStonePool.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//단순히 상속을 통해 오브젝트 풀 기능을 이용할 수 있다. public class GolemStonePool : OBJPool<StoneObj>
{
}
|
cs |
작성한 OBJPool 스크립트는 제네릭화 되어있어, 여러 타입 (오브젝트 타입)에 따라 손쉽게 OBJPool<Type>으로 상속하여 손쉽게 사용할 수 있는 특징이 있다.
mOrigin 변수에 3개의 StoneObj가 들어있다. GetFromPool에서 인자에 따라 리턴되는 StoneObj가 서로 다를 수 있다.
public class GolemStonePool: OBJPool<StoneObj>
- OBJPool을 <StoneObj> 타입으로 상속받아 부모의 기능을 이용할 수 있도록 구현했다.
- 부모의 OBJPool에서 GetFromPool의 리턴 타입을 <StoneObj>로 하여 리턴받는다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
//StoneObj.cs
...
public class StoneObj : MonoBehaviour
{
...
//StoneObj가 비활성화 되는 조건
void Update()
{
if(transform.position.y < mGroundHeight)
{
gameObject.SetActive(false);
}
}
...
}
}
|
cs |
실제 오브젝트 풀의 리턴 대상인 프리팹이나 게임오브젝트에 붙는 StoneObj.cs 스크립트이다.
void Update()
- 해당 오브젝트가 오브젝트 풀에서 리턴되어 활성화 상태가 되면 특정 조건에 의해 다시 SetActive(false) 상태가 되어야 하는것을 권장한다. 그렇지 않으면 오브젝트 풀의 의미를 잃어버리는 상태가 되니 주의해야함.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
//GolemAttackCtrl.cs
...
public class GolemAttackCtrl : MonoBehaviour
{
...
//돌 오브젝트를 GetFromPool() 한다.
private void SpawnStone()
{
StoneObj obj = mStonePool.GetFromPool(Random.Range(0,2));
obj.gameObject.SetActive(true);
obj.transform.position = transform.position;
}
...
}
|
cs |
mStonePool에는 GolemStonePool이 담긴 상태에서 SpawnStone()을 사용하여 풀 기능을 사용한다.
private void SpawnStone()
- GolemStonePool에서 GetFromPool을 하여 오브젝트를 가져온다.
- 오브젝트를 가져오면 해당 오브젝트를 활성화 시킨다.
- 해당 오브젝트를 움직이거나, 총알처럼 앞으로 직진시키거나 자유롭게 해당 오브젝트를 사용한다.
- 특정 조건에서 해당 오브젝트를 비활성화 시키도록 하는것을 권장한다.
'unity game modules' 카테고리의 다른 글
[유니티] 안개 효과 (던전 입장 효과) (0) | 2022.07.16 |
---|---|
[유니티] 3인칭 움직이기 (0) | 2022.07.16 |
[유니티] 공격(스킬) 범위 표시 (0) | 2022.07.16 |
[유니티] 아이템 사용하기 (0) | 2022.03.05 |
[유니티] 인벤토리 장비 슬롯 (0) | 2022.03.05 |