유니티 오브젝트 풀이란

2020. 7. 22. 12:41유니티실습

반응형
728x170

안녕하세요 유니티 비기너입니다.

이번 시간에는 오브젝트 풀에 대해 간단하게 알아보겠습니다.

 

테스트화면

총알은 벽이나, 우주선과 충돌하면 오브젝트 풀에 반환합니다.

아래의 검은색은 활성화되어있는 총알 객체이며, 벽이나 우주선과

충돌하면 비활성화되어 반환됩니다.

 

오브젝트 풀이란

객체를 미리 지정된 양만큼 생성해놓고 객체를 필요로 할 때 풀에 요청하여 객체를 가져오고

객체의 사용이 끝났을 때 풀에 반환하는 형태의 패턴을 오브젝트 풀이라고 합니다.

 

스크립트 ObjectPool

public class ObjectPool : MonoBehaviour {

    private static ObjectPool _instance = null;

    public static ObjectPool Instance {
        get {
            if (_instance == null) {

                _instance = GameObject.FindObjectOfType<ObjectPool>();

                if (_instance == null) {
                    Debug.LogError("There's no active ObjectPool object");
                }
            }
            return _instance;
        }
    }

    public int InitializeCount;

    [SerializeField]
    private GameObject objectPrefab;

    Queue<Bullet> objectQueue = new Queue<Bullet>();

    private void Awake() {
        Initialize(InitializeCount);
    }

    private void Initialize(int initCount) {
        for (int i = 0; i < initCount; i++) {
            objectQueue.Enqueue(CreateObject());
        }
    }

    private Bullet CreateObject() {
        var newObj = Instantiate(objectPrefab).GetComponent<Bullet>();
        newObj.gameObject.SetActive(false);
        newObj.transform.SetParent(transform);
        return newObj;
    }

    public static Bullet GetObject() {
        if (Instance.objectQueue.Count > 0) {
            var obj = Instance.objectQueue.Dequeue();
            obj.transform.SetParent(null);
            obj.gameObject.SetActive(true);
            return obj;
        } else {
            var newObj = Instance.CreateObject();
            newObj.gameObject.SetActive(true);
            newObj.transform.SetParent(null);
            return newObj;
        }
    }

    public static void ReturnObject(Bullet obj) {
        obj.gameObject.SetActive(false);
        obj.transform.SetParent(Instance.transform);
        Instance.objectQueue.Enqueue(obj);
    }
}

 

Initialize()를 통해 객체를 미리 생성해놓습니다.

GetObject()를 활용하여 객체를 요청하며 미리 생성해놓은 객체를 초과할 경우 오브젝트를 추가 생성합니다.

ReturnObject()을 사용하여 오브젝트를 반환합니다.

 

스크립트 Bullet

public class Bullet : MonoBehaviour {

    private float bulletSpeed;
    private Transform target;
    private Quaternion rotation;
    private Rigidbody2D rb;
    private Vector2 direction;

    void Awake() {
        rb = GetComponent<Rigidbody2D>();
    }

    void Update() {
        if(target !=null) {
            direction = (target.position - transform.position).normalized;
            rb.velocity = new Vector2(direction.x * bulletSpeed, direction.y * bulletSpeed);
            target = null;
        }
    }

    public void SetTarget(Transform _target, Vector3 _position,  Quaternion _rotation, float _bulletSpeed) {
        target = _target;
        rotation = _rotation;
        bulletSpeed = _bulletSpeed;
        transform.position = _position;
    }

    public void OnTriggerEnter2D(Collider2D col) {
        if (col.tag == "Player") {            
            ObjectPool.ReturnObject(GetComponent<Bullet>());
        } else if (col.tag == "Wall") {
            ObjectPool.ReturnObject(GetComponent<Bullet>());
        }
    }
}

총알은 생성된 시점에 target의 방향으로 총알을 이동시키며

플레이어 또는 벽에 충돌하는 경우 오브젝트를 반환합니다.

 

사용 이유

슈팅게임으로 예를 들면 아군, 적군 할 거 없이 많은 수의 총알 객체들이 날아다니는데

메모리에 총알 객체가 할당되고, 소멸시키는 행위가 지속적으로 반복된다면

시스템 성능적으로 부담을 느낄 수밖에 없습니다.

 

이러한 경우 오브젝트 풀을 이용하여 생성, 소멸이 아닌 메모리에 미리 할당되어있는

객체를 활성 / 비 활성시키면서 사용하여 성능 부담을 줄여주는 것이 좋습니다.

 

반응형
그리드형