[Unity3D] 객체 미리 생성 후 재활용 - Memory pool [Part 1]

※ 주의 

이 글은 아마추어가 개인적으로 생각하여 작성하는 것으로, 이곳에 나오는 내용을 맹신하지 않는것을 당부드립니다.



Menu

0. 미리보기

1. 오브젝트를 미리 생성.

- 프리팹 제작.

- 싱글톤 제작.

- 오브젝트를 생성시킬 함수 제작.

- 오브젝트를 찾을 함수를 제작.

2. 만들어진 오브젝트 활용하기.




1. 오브젝트 미리 생성.


- 총알 프리팹 제작.



구체를 하나 생성한다.





1. 생성한 오브젝트의 이름을 'Bullet'으로 설정.

2. 스케일 x,y,z를 (0.2, 0.2, 0.5)로 설정.

3. Mesh Renderer컴포넌트에 Cast Shadows를 off로 설정.

4. Mesh Renderer컴포넌트에 Receive Shadows 체크박스 해제.

※ 3,4번 빛 연산 및 빛으로 인한 그림자 연산을 하지 않을 거다.

5. Rigidbody추가 후 Is Kinematic체크

※ Rigidbody없이 물리운동을 할 경우 시스템에 부담이 걸리므로 리지드바디 추가 후 키네틱을 체크해준다.

6. 마테리얼을 적색으로 생성 후 Bullet오브젝트에 적용.





하이러키창에 있는 Bullet을 프로젝트창에 드래그해서 프리팹을 생성한다.

그 뒤 하이러키창에 있는 Bullet을 삭제.




- 싱글톤 제작.


※ 지정한 클래스 인스턴스가 절대로 한 개밖에 존재하지 않는 것을 보증하고 싶을 경우 싱글톤을 사용한다.

보통 객체 생성 시 new키워드를 사용하여 객체화 하는데, 객체를 생성하게되면 Heap메모리에 올라가게 된다.

그 인스턴스를 가리키고 있는 변수는 Stack메모리 영역에 생기게 된다.


이러한 작업 자체가 시간이 걸리는 일이며, 한 객체를 여러번 new하게 되면 시간이 더욱 오래 걸리게 된다.

그래서 자주 사용되는 객체는 한 번만 생성하고, Heap에 존재하는 이 객체를 가르키도록 만들면 된다.

즉, 객체가 생성될 때 Heap영영에 올라가는 시간과 메모리를 줄일 수 있다.



단점.

- 싱글톤을 사용하여 여러곳에서 효과적으로 호출할 수 있어서 편하지만 결과적으로 프로그램의 Coupling을 높이게 되어 한곳에서의 변경이 다른 부분에 영향을 미치게 될 확률이 높아지게 된다.



'ObjManager' 스크립트 제작.


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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class ObjManager : MonoBehaviour {
 
    // 싱글톤
    static ObjManager st;
    public static ObjManager Call() { return st; }
    void Awake()                    { st = this; }
    // 게임종료 후 메모리 날려버림.
    void OnDestroy()                
    { 
        MemoryDelete();
        st = null
    } 
 
    public GameObject[] Origin;         // 프리팹 원본.
    public List<GameObject> Manager;    // 생성된 객체들을 저장할 리스트.
 
    void Start()
    {
        SetObject(Origin[0], 20"Bullet");   // 총알을 생성.
    }
 
    // 오브젝트를 받아 생성. (생성한 원본 오브젝트, 생성할 갯수, 생성할 객체의 이름)
    public void SetObject( GameObject _Obj, int _Count, string _Name)
    {
        for (int i = 0; i < _Count; i++)
        {
            GameObject obj = Instantiate(_Obj) as GameObject;
            obj.transform.name = _Name;                     // 이름을 정한다.
            obj.transform.localPosition = Vector3.zero;     // 위치를 정한다.
            obj.SetActive(false);                           // 객체를 비활성화.
            obj.transform.parent = transform;               // 매니저 객체의 자식으로.
            Manager.Add(obj);                               // 리스트에 저장.
        }
    }
 
    // 필요한 오브젝트를 찾아 반환.
    public GameObject GetObject(string _Name)
    {
        if (Manager == null)
            return null;
 
        int Count = Manager.Count;
        for (int i = 0; i < Count; i++)
        {
            // 이름이 같지 않으면.
if ( _Name != Manager[i].name )
             continue;
            
            GameObject Obj = Manager[i];
 
            // 활성화가 되어있다면.
            if (Obj.active == true)
            {
                // 리스트의 마지막까지 돌았지만 모든 객체가 사용중이라면.
                if (i == Count - 1)
                {
                    // 총알을 새롭게 생성.
                    SetObject(Obj, 1"Bullet");
                    return Manager[i + 1];
                }
                continue;
            }
            return Manager[i]; 
        }
        return null;
    }
 
    // 메모리 삭제.
    public void MemoryDelete()
    {
        if (Manager == null)
            return;
 
        int Count = Manager.Count;
 
        for (int i = 0; i < Count; i++)
        {
            GameObject obj = Manager[i];
            GameObject.Destroy(obj);
        }
        Manager = null;
    }
}

cs



빈 오브젝트를 생성하여 이름을 ObjectManager로 변경한다.

그뒤 만들어 두었던 ObjManager스크립트를 ObjectManager 객체에 드래그하여 컴포넌트를 생성한다.


Obj Manager스크립트 - Origin배열에 사이즈를 1로 늘리고, Bullet프리팹을 드래그하여 넣는다.



이 스크립트에는 싱글톤을 제외하고 몇 가지 기능을 가진 함수들이 있다.


1. 오브젝트를 생성시켜주는 함수.

2. 필요한 오브젝트를 찾아 반환시켜주는 함수.

3. 메모리를 삭제해주는 함수.


2번의 함수는 리스트내의 객체의 이름을 검색, 비교하여 필요한 오브젝트를 찾아주는데,

만약 필요한 객체가 없거나 모두 사용중이면 새롭게 생성해 그 객체를 반환해주는 역할을 수행하고 있다.




결과.



총알이 여러개 생성되었다.