Menu
CoddyTech

큐를 이용한 풀

Coddy Unity 여정의 Unity 게임 아키텍처 섹션에 포함된 레슨. 64개 중 47번째.

풀에는 여분의 객체를 보관할 곳이 필요하며, C#에는 이를 위한 컬렉션인 Queue<T>가 있습니다. Enqueue는 항목을 뒤에 추가하고, Dequeue는 맨 앞의 항목을 가져오며, Count는 대기 중인 항목이 몇 개인지 알려 줍니다. 이 수족관에서는 0.3초마다 거품이 하나씩 올라오고, 각 거품은 수면에 도달하면 풀로 돌아옵니다:

using System.Collections.Generic;
using UnityEngine;

public class BubblePool : MonoBehaviour
{
    public GameObject bubblePrefab;
    private Queue<GameObject> pool = new Queue<GameObject>();
    private float timer;

    void Update()
    {
        timer += Time.deltaTime;
        if (timer >= 0.3f)
        {
            timer = 0f;
            Get(new Vector3(Random.Range(-2f, 2f), 0f, 0f));
        }
    }

    public GameObject Get(Vector3 position)
    {
        GameObject bubble;
        if (pool.Count > 0)
        {
            bubble = pool.Dequeue();
        }
        else
        {
            bubble = Instantiate(bubblePrefab);
            bubble.GetComponent<Bubble>().pool = this;
        }
        bubble.transform.position = position;
        bubble.SetActive(true);
        return bubble;
    }

    public void Return(GameObject bubble)
    {
        bubble.SetActive(false);
        pool.Enqueue(bubble);
    }
}
// Bubble.cs, 버블 프리팹에 있음
public BubblePool pool;

void Update()
{
    transform.Translate(0f, 2f * Time.deltaTime, 0f);
    if (transform.position.y > 5f) pool.Return(gameObject);
}

Get은 먼저 Count를 확인합니다. 빈 큐에서 Dequeue를 호출하면 InvalidOperationException이 발생하기 때문입니다. 그다음에야 Instantiate를 호출하며, 새 거품에만 pool 필드를 설정하면 됩니다. 재사용하는 거품에는 이미 설정되어 있습니다. 큐는 가장 오래 기다린 거품부터 내보내므로 선입선출 방식으로 동작합니다. 수면에 도달한 거품은 Destroy 대신 Return을 호출하며, 다음 Get이 호출될 때까지 비활성 상태로 씬에 남아 있습니다.

Get은 거품을 배치한 다음 SetActive(true)를 호출합니다. 활성화하면 OnEnable이 곧바로 실행되므로, 그 안의 코드가 거품이 마지막으로 사라졌던 위치가 아니라 새 위치를 보게 해야 하기 때문입니다. 재사용되는 객체가 다시 시작하는 것도 이 시점입니다. Awake와 Start는 거품이 만들어질 때 한 번 실행되고, OnEnable은 Get이 호출될 때마다 실행됩니다.

challenge icon

챌린지

중급

발자국을 삭제하는 대신 풀링하세요.

  1. Trail에서 여분을 Queue<GameObject>에 보관하세요. Return(footprint)은 발자국을 비활성화하고 큐에 넣습니다. Start에서는 발자국을 prewarm개 만들고 반환합니다.
  2. Get(position)은 여분을 큐에서 꺼내거나 하나 만들고, 위치를 설정한 다음 활성화합니다.
  3. Footprint에서 Destroy를 대체하세요. OnEnable에서 나이를 초기화하고, life초가 지나면 trail.Return(gameObject)을 호출하세요.

‘플레이’를 누르고 걸어 보세요. 발자국은 1.5초 후 사라집니다. 그런 다음 ‘확인’을 누르세요.

직접 해보기

using System.Collections.Generic;
using UnityEngine;

public class Trail : MonoBehaviour
{
    public GameObject footprintPrefab;
    public float step = 1f;
    public int prewarm = 6;
    private Vector3 lastDrop;

    void Start()
    {
        lastDrop = transform.position;
        // 풀을 미리 준비할 발자국으로 채웁니다
    }

    void Update()
    {
        if (Vector3.Distance(transform.position, lastDrop) >= step)
        {
            lastDrop = transform.position;
            Get(new Vector3(transform.position.x, 0.02f, transform.position.z));
        }
    }

    public GameObject Get(Vector3 position)
    {
        GameObject footprint = Instantiate(footprintPrefab, position, Quaternion.identity);
        footprint.GetComponent<Footprint>().trail = this;
        return footprint;
    }

    public void Return(GameObject footprint)
    {
        // 여분의 발자국은 풀에서 대기합니다
    }
}

Unity 게임 아키텍처의 모든 레슨

직접 연습해 보세요: Unity 플레이그라운드