본문 바로가기

유니티 교재 정리 오브젝트풀 (256pg~291pg) 멋쟁이사자처럼 43회차 2

@salmu2025. 7. 24. 17:36
반응형

오브젝트 풀 

 

1. Start / OnEnable

Start는 오브젝트가 처음 활성화될 때 한 번만 실행됨 → 오브젝트풀에서 재활용 시에는 재활성화되어도 다시 호출 안 됨

OnEnable은 오브젝트가 활성화될 때마다 매번 호출→ 오브젝트풀에서 총알 재사용할 때마다 초기화 작업(위치, 속도 등) 수행 가능

 

 

2. 총알 관리 _ 배열 <-> 리스트 사용 오브젝트풀

배열은 오브젝트 풀을 전수조사해 비활성화 객체를 찾지만 리스트에는 비활성화 객체만 들어있음. 
(리스트는 Add로 추가 Remove로 제거)

 

 

3. +  Queue 사용  오브젝트풀: 순차적 접근이 쉬워 구현 단순 (Queue = 줄 = 선입선출)

using System.Collections.Generic;
using UnityEngine;

public class ObjectPoolQueue : MonoBehaviour
{
    // 오브젝트들이 저장될 큐 (FIFO 방식)
    public Queue<GameObject> objQueue = new Queue<GameObject>();
    
    // 생성할 오브젝트 프리팹
    public GameObject objPrefab;
    
    // 생성된 오브젝트들이 계층 구조상 붙을 부모 Transform
    public Transform parent;

    // 게임 시작 시 호출되는 함수
    void Start()
    {
        CreateObject(); // 오브젝트풀 초기화: 미리 오브젝트를 생성해서 큐에 넣음
    }

    // 미리 정해진 개수(100개)만큼 오브젝트를 생성하고 풀에 저장하는 함수
    private void CreateObject()
    {
        for (int i = 0; i < 100; i++)
        {
            // objPrefab을 parent 자식으로 생성
            GameObject obj = Instantiate(objPrefab, parent);

            // 생성한 오브젝트를 큐에 넣고 비활성화 처리
            EnqueueObject(obj);
        }
    }

    // 오브젝트를 다시 풀에 넣을 때 호출하는 함수
    public void EnqueueObject(GameObject newObj)
    {
        // Rigidbody가 있으면 물리 속도 초기화 (중요!)
        Rigidbody rb = newObj.GetComponent<Rigidbody>();
        if (rb != null)
        {
            rb.velocity = Vector3.zero;        // 선형 속도 초기화
            rb.angularVelocity = Vector3.zero; // 각속도 초기화
        }
        
        objQueue.Enqueue(newObj); // 큐에 오브젝트 저장
        newObj.SetActive(false);  // 오브젝트 비활성화 (게임 내에서 보이지 않고 작동 안 함)
    }

    // 오브젝트를 사용할 때(풀에서 꺼낼 때) 호출하는 함수
    public GameObject DequeueObject()
    {
        // 큐에서 가장 먼저 들어온 오브젝트 하나 꺼냄 (FIFO)
        GameObject obj = objQueue.Dequeue();
        
        obj.SetActive(true); // 활성화해서 게임 내에서 사용 가능 상태로 만듦
        
        return obj; // 꺼낸 오브젝트 반환
    }
}

 

+ 활용

// 아이템 생성 및 발사 기능을 담당하는 컨트롤러
using UnityEngine;

public class ObjectPoolController : MonoBehaviour
{
    public ObjectPoolQueue pool;    // 오브젝트 풀 참조 (총알 등)
    public Transform shootPos;      // 총알이 발사될 위치 (발사 위치 Transform)

    void Update()
    {
        // 마우스 왼쪽 버튼 클릭 시 실행
        if (Input.GetMouseButtonDown(0))
        {
            // 풀에서 비활성화된 총알을 꺼내 활성화함
            GameObject bullet = pool.DequeueObject();
            // 총알 위치를 발사 위치로 옮김
            bullet.transform.position = shootPos.position;
        }
    }
}

 

 

// 풀에서 재사용되는 총알 오브젝트 동작 스크립트
using UnityEngine;

public class PoolObject : MonoBehaviour
{
    private ObjectPoolQueue pool;     // 풀 관리 스크립트 참조
    
    public float bulletSpeed = 100f;  // 총알 이동 속도

    void Awake()
    {
        // 씬에서 ObjectPoolQueue 스크립트를 찾아 참조 저장
        pool = FindFirstObjectByType<ObjectPoolQueue>();
    }

    void OnEnable()
    {
        // 활성화되면 3초 후 자동으로 ReturnPool() 호출해서 풀에 반환 예약
        Invoke("ReturnPool", 3f);
    }

    void Update()
    {
        // 매 프레임 총알을 앞으로 이동시킴 (Z축 방향)
        transform.position += Vector3.forward * Time.deltaTime * bulletSpeed;
    }

    private void ReturnPool()
    {
        // 총알을 다시 비활성화하고 풀에 넣음 (재사용 준비)
        pool.EnqueueObject(gameObject);
    }
}

 

 

 

 

4. 유니티 내장된 오브젝트풀링 

  • 직접 큐나 리스트를 관리하지 않아도 되고, 풀링 관련 콜백(생성, 활성화, 비활성화, 파괴)을 쉽게 등록해서 관리 가능
  • 최대 풀 크기 지정 가능(maxSize) → 너무 커지는 것 방지
using UnityEngine.Pool;
public ObjectPool<GameObject> pool;

//꺼내기
GameObject obj = pool.Get();

//반환하기
pool.Release(obj);

 

 

 

반응형
salmu
@salmu :: SMU 각종 기록

목차