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

※ 주의 

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



Menu

0. 미리보기

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

- 프리팹 제작.

- 싱글톤 제작.

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

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

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


추가.

3. 적 생성

- 적 생성 후 프리팹으로 만들기.

- 적과 총알이 충돌하면 총알 비활성화.

- 적이 총알에 맞아 죽었을 때 단순한 객체로 이펙트 효과 표현하기.


4. 메모리 풀을 이용해서 적 생성하기.

- 적 리스폰

 * Enemy를 생산하는 Area만들기. (랜덤한 위치로 Area생산 및 Area간 간격조절.)

 * Araa범위 안에 Enemy 랜덤한 위치로 리스폰 시키기.

 * Enemy가 죽었을 경우 리스폰 되는 간격 조절.


5. FSM을 이용해 적 AI만들기.




미리보기





4. 메모리 풀을 이용해서 적 생성하기.


구조



ObjManager에서 Enemy를 자체 생산 해버리면 코드가 여러모로 더러워지고, 관리또한 힘들어진다.

현재 ObjManager는 잔해물 및 총알에 대해서 자체생산하고 있는데, 그 구조를 고쳐보도록 하자.


- 잔해물

- 총알

- 적


각 매니저는 ObjManager에게 필요한 객체의 생산을 요청하고 객체가 필요할때마다 ObjManager에게 요청하여

필요한 객체를 찾아 반환받아 사용할 것이다.


1). Player스크립트에서 ObjManager로 총알 생성 요청하기.

2). Wreckage스크립트에서 ObjManager로 잔해물 생성 요청하기.

3). CreateArea스크립트에서 ObjManager로 적 생성 요청하기.

4). CreateArea스크립트에서 Area생성하기.

5). 각 Area에서 ObjManager에게 비활성화인 Enemy객체 요청하기.

6). Area에서 Enemy소환하기.

7). Enemy가 죽을때 자신의 부모 Area에게 자신의 죽음을 알려, 다음 리스폰여부를 결정하게 한다.




0) ObjManager스크립트에 SetObject()함수 2번째 인자 값의 기본값을 설정


1
2
3
4
5
6
7
8
9
10
11
12
public void SetObject(string _Name, int _Count = 20)
{
    GameObject obj = null;
    int Count = Origin.Length;
    for(int i = 0; i < Count; i++)
    {
        if (Origin[i].name == _Name)
            obj = Origin[i];
    }
 
    SetObject(obj, _Count, _Name);
}
cs

SetObject함수 호출 시 2번째 인자값을 입력하지 않아도 기본 값으로 20이 셋팅된다.


ps. 각 객체의 매니저가 생산요청을 하기 때문에 ObjManager에서 Start()는 할일이 없어졌으므로 지워버리면 된다.


"ObjManager" 풀 소스



1). Player스크립트에서 ObjManager로 총알 생성 요청하기.


1
2
3
4
5
6
7
8
    void Start()
    {
        // 총알 생성 요청.
        ObjManager.Call().SetObject("Bullet");
        Vec = GameObject.Find("CameraVector").transform;
 
        Init();
    }
cs


Start() 함수에 한 줄만 추가하면 끝.



2). Wreckage스크립트에서 ObjManager로 잔해물 생성 요청하기.


Wreckage스크립트 생성 후 하이러키창 ObjManager객체에 스크립트를 추가.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class WreckageManager : MonoBehaviour {
 
    void Start () 
    {
        string Name = "NoData";
 
        for (int i = 0; i < 4; i++)
        {
            switch (i)
            {
                case 0: Name = "Cube";     break;
                case 1: Name = "Cylinder"break;
                case 2: Name = "Capsule";  break;
                case 3: Name = "Sphere";   break;
            }
            ObjManager.Call().SetObject(Name);
        }
    }
}
cs



3). CreateArea스크립트에서 ObjManager로 적 생성 요청하기.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class EnemyArea : MonoBehaviour {
 
    public List<Transform> RespawnArea; // 리스폰 구역.
 
    public int AreaCount;   // 에리어 개수.
    public int AreaGap;     // 에리어간 간격.
    public int CreateCount; // 적 머리수.
 
    void Start ()
    {
        CreateArea(AreaCount);
 
        // 에너미 생산 요청.
        ObjManager.Call().SetObject("Enemy", CreateCount);
    }
}
cs



4). CreateArea스크립트에서 Area생성하기.


설명은 주석으로.



하이러키창에 생성된 Area객체.





5). 각 Area에서 ObjManager에게 비활성화인 Enemy객체 요청하기. &

6). Area에서 Enemy소환하기.





7). Enemy가 죽을때 자신의 부모 Area에게 자신의 죽음을 알려, 다음 리스폰여부를 결정하게 한다.


'Enemy' Script



에너미의 HP가 0이 되었을 때

에너미 자신이 속한 에리어의 스크립트를 가져와 Dead함수를 호출하여 자신이 죽었다는 사실을 알린다.

에리어는 그 사실을 인지하고 현재 살아있는 에너미 머리수 중 1을 줄인다.

머리수가 0이 되면 일정 시간 후에 에너미를 리젠 시킨다.