Menu
CoddyTech

Kuyruk Kullanan Bir Havuz

Coddy'nin Unity Journey'sinin Unity'de Oyun Mimarisi bölümünün bir parçası. Ders 38 / 50.

Bir havuzun yedek nesnelerini saklayacak bir yere ihtiyacı vardır ve C# bunun için bir koleksiyona sahiptir: Queue<T>: Enqueue bir öğeyi kuyruğun sonuna ekler, Dequeue baştakini alır ve Count kaç öğenin beklediğini söyler. Bu akvaryum her 0.3 saniyede bir baloncuk çıkarır ve her baloncuk yüzeye ulaştığında havuza geri döner:

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, baloncuk prefab'inde
public BubblePool pool;

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

Get önce Count değerini kontrol eder, çünkü boş bir kuyrukta Dequeue çağrısı InvalidOperationException hatası verir. Ancak bundan sonra Instantiate çağrılır ve yalnızca yeni bir baloncuğun pool alanının ayarlanması gerekir: yeniden kullanılan bir baloncukta bu alan zaten vardır. Kuyruk, en uzun süredir bekleyen baloncuğu önce verir; yani ilk giren ilk çıkar. Yüzeye ulaşan bir baloncuk Destroy yerine Return çağrısı yapar ve bir sonraki Get çağrısına kadar sahnede etkin olmayan durumda kalır.

Get, baloncuğu SetActive(true) çağrısından önce konumlandırır; çünkü etkinleştirmek OnEnable yöntemini hemen çalıştırır ve buradaki her şey baloncuğun en son kaybolduğu yeri değil, yeni konumunu görmelidir. Yeniden kullanılan bir nesne de burada baştan başlar: Awake ve Start, baloncuk oluşturulduğunda bir kez çalışır; OnEnable ise her Get çağrısında çalışır.

challenge icon

Görev

Orta

Kumdaki ayak izleri. Ok tuşları Player'ı hareket ettirir (hazır). Player üzerindeki Trail.cs, yürünülen her 1 birimde Get(position) çağırarak bir ayak izi bırakır ve her Footprint life (1.5) saniye boyunca kalır. Bugün Get her seferinde yeni bir ayak izi örneği oluşturuyor ve her biri kendini yok ediyor. Bunları havuzda tut:

  • Trail.cs içinde, kullanılmayan ayak izlerini bir Queue<GameObject> içinde tut. Trail'in oluşturduğu her ayak izinin trail alanına bu Trail atanmalı.
  • Start içinde, ilk adımlarda yeni bir şey oluşturulmaması için havuzu oluşturulmuş ve kapatılmış prewarm (6) ayak iziyle doldur.
  • Get(position), kuyrukta varsa bir ayak izini alır ve yalnızca kuyruk boş olduğunda yeni bir tane oluşturur; ardından ayak izini konumlandırıp etkinleştirir.
  • Return(footprint), ayak izini devre dışı bırakır ve kuyruğa koyar.
  • Footprint.cs içinde, bir ayak izi yaşını sayar ve life saniye geçtikten sonra yok edilmek yerine trail.Return(gameObject) ile geri döner. Yeniden kullanılan bir ayak izi 1.5 saniyenin tamamı boyunca kalır.

Play'e bas, bir süre etrafta yürü, ardından Check'e bas.

Kendin dene

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;
        // Havuzu önceden hazırlanmış ayak izleriyle doldur
    }

    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)
    {
        // Yedek ayak izleri havuzda bekler
    }
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Unity'de Oyun Mimarisi bölümündeki tüm dersler