오브젝트 풀링 Object Pooling

스페이스바를 누르면 총알을 생성되고, forward방향으로 이동하며 3초후에 사라진다.



1) 처음에 10개를 만들어 놓는다.

2) 플레이어가 스페이스바를 누르면 하나씩 SetActive(true)로 활성화 시켜 마치 새로 생성된 것처럼 보여준다.

3) 정해둔 시간이 되면 총알은 SetActiv(false)되어 삭제된 것처럼 보여준다.

4) 만약 씬안에 10개가 이상 총알이 생성돼야 한다면 추가적으로 10개씩 생성해준다.


위 gif처럼 천천히 총알을 쏘면 10개로 활/비활성화로 돌려 쓸수 있다.

하지만 빨리 쏘게되면 추가적으로 10개가 되는것을 볼 수 있다.


오브젝트를 생성과 삭제를 하지 않고 활/비활성화로 구현한다.

( Instantiate과 Destroy을 쓰지 않는 기법이다.)


오브젝트를 복제 생성하고 삭제하는 Instantiate과 Destroy을 사용하게 되면 가비지 콜렉터를 호출하게 된다.

가비지 콜렉터란?

C#에서는 메모리 관리를 프로그래머가 따로 관리 하지 않는다.

가비지 컬렉터는 메모리에 있는 참조가 끝난 객체를 쓰레기 치우는 것처럼 소멸 시키는 역할을 한다.

=> 가비지 컬렉터 호출이 많이 발생 할 수록 성능이 낮아 진다.



pool 컬렉터 셋팅

LinkedList<Bullet> m_lipool = new LinkedList<Bullet>(); //풀에 담을

LinkedList<Bullet> m_liActive = new LinkedList<Bullet>(); //(생성)활성화된 총알을 담을


    const int nMAKE_BULLET_COUNT = 10;


    public void Init(Transform a_objRoot, GameObject a_objBulletOrigin) 

    {

        m_objRoot      = a_objRoot;

        m_BulletOrigin = a_objBulletOrigin;


        MakeBullet(nMAKE_BULLET_COUNT);

    }


~~생략

풀에 담을 오브젝트를 담을 컬렉터와 게임에서 보여질 오브젝트를 담을 컬렉터를 만들어준다.



pool에 오브젝트(값) 삽입
private void MakeBullet(int a_nCount) { for (int i=0; i<=a_nCount; ++i) { var b = Instantiate(m_BulletOrigin).GetComponent<Bullet>(); b.transform.parent = m_objRoot.transform; b.gameObject.SetActive(false); //비활성화 m_lipool.AddLast(b); } }

씬에 생성을 하고 비활성화로 해주고 LinkedList풀에 Add해준다.


오브젝트 생성(생성될 위치, 데이터)

public void AddShot(Vector3 a_vcPos, ref BulletData a_vcData)

    {

        if(m_lipool.Count == 0) 

        {

            MakeBullet(nMAKE_BULLET_COUNT); //10개 

}

            var bullet = m_lipool.First.Value; 

            m_lipool.RemoveFirst() //삭제

            bullet.Init(ref a_vcData); 

            bullet.transform.localPosition = a_vcPos;

            bullet.gameObject.SetActive(true);

            m_liActive.AddLast(bullet); 

    }

오브젝트풀 카운트가 0이되면 추가적으로 다시 10개를 생성한다.

첫번째로 담았던 오브젝트를 위치와 데이터를 정보를 입력해주고 활성화 해준다.

m_lipool 풀에서는 지워준다.

m_liActive 에 추가 해준다.


pool반환

    List<Bullet> m_listemp = new List<Bullet>(); //리스트 생성

    private void Update()

    {

        foreach(var b in m_liActive) //활성화된 풀중에서

        {

            b.DoUpdate(); //DoUpdate(총알 위치 업데이트)

            if(b.IsDie == true) // 사라질 시간이 됐다면

            {

                m_listemp.Add(b); //사라진 총알은 리스트에 추가

            }

        }

        foreach(var b in m_listemp) //리스트에 저장된 사라진 총알들

        {

            b.gameObject.SetActive(false); //비활성화

            m_liActive.Remove(b); //활성화된 풀삭제

            m_lipool.AddLast(b); //다시 풀에  넣는다 (뒤에)

        }

        m_listemp.Clear(); //넣어준 리스트 클리어

    }

풀에 넣을 리스트를 생성해준다 중간 바구니라고 생각하면 쉽다. 

1) 사라질 시간이 될 총알들은 비활성화 해주고  

2) m_liActive에 지운다.

3) 그 총알들을 리스트에 담는다.

4) 바구니에 담은 총알들을 다시 m_lipool 생성풀에 넣어준다.


반응형

+ Recent posts