Menu
CoddyTech

ObjectPool di Unity

Termasuk bagian Arsitektur Game di Unity dalam perjalanan Unity di Coddy. Pelajaran 39 dari 50.

Unity menyediakan pool, ObjectPool<T> di UnityEngine.Pool. Kamu memberi tahu pool apa yang harus dilakukan pada setiap langkah dengan empat lambda, lalu pool menyimpan objek cadangan dan menghitung jumlahnya. Cerobong ini mengeluarkan asap setiap 0.2 detik, dan setiap kepulan dikembalikan setelah satu detik:

using UnityEngine;
using UnityEngine.Pool;

public class Chimney : MonoBehaviour
{
    public Puff puffPrefab;
    private ObjectPool<Puff> pool;
    private float timer;

    void Awake()
    {
        pool = new ObjectPool<Puff>(
            createFunc: () => Instantiate(puffPrefab),
            actionOnGet: puff => puff.gameObject.SetActive(true),
            actionOnRelease: puff => puff.gameObject.SetActive(false),
            actionOnDestroy: puff => Destroy(puff.gameObject),
            collectionCheck: true,
            defaultCapacity: 10,
            maxSize: 20);
    }

    void Update()
    {
        timer += Time.deltaTime;
        if (timer >= 0.2f)
        {
            timer = 0f;
            Puff puff = pool.Get();
            puff.transform.position = transform.position + Vector3.up;
            puff.Launch(pool);
        }
    }
}
// Puff.cs
private IObjectPool<Puff> pool;
private float age;

public void Launch(IObjectPool<Puff> owner)
{
    pool = owner;
    age = 0f;
}

void Update()
{
    transform.Translate(0f, Time.deltaTime, 0f);
    age += Time.deltaTime;
    if (age >= 1f) pool.Release(this);
}

createFunc berjalan saat Get mendapati pool kosong; actionOnGet berjalan setiap kali Get dipanggil dan actionOnRelease setiap kali Release dipanggil. Jika kepulan dikembalikan saat sudah ada maxSize objek cadangan di pool, pool tidak menyimpannya: actionOnDestroy akan menghapusnya. defaultCapacity hanya menentukan ukuran awal list pool, jadi tidak ada objek yang dibuat sejak awal. CountAll menghitung kepulan yang telah dibuat dan masih dimiliki pool, CountActive menghitung kepulan yang sedang ada di game, dan CountInactive menghitung objek cadangan. Get mengaktifkan kepulan sebelum cerobong menempatkannya, dan itu tidak masalah di sini karena Puff tidak memiliki OnEnable yang membaca posisinya. Kepulan menyimpan pool sebagai IObjectPool<Puff>, antarmuka yang diimplementasikan setiap pool Unity, dan Launch mengatur ulang usianya setiap kali digunakan.

Jika collectionCheck aktif, mengembalikan kepulan yang sudah ada di pool akan memunculkan InvalidOperationException: Trying to release an object that has already been released to the pool. Pemeriksaan ini hanya berjalan di Editor karena pemeriksaan tersebut mencari objek cadangan pada setiap pemanggilan Release; dalam build, kepulan akan tersimpan dua kali di pool dan dua pemanggilan Get akan memberikan object yang sama. Penyebab umumnya adalah object yang terus berjalan setelah dikembalikan lalu mengembalikan dirinya lagi, itulah sebabnya actionOnRelease menonaktifkannya.

challenge icon

Tantangan

Sedang

Kembang api. Setiap kali kamu menekan Space, 8 percikan melesat keluar dari peluncur, dan setiap Spark memanggil Return(this) saat masa hidupnya selama 1 detik berakhir (Spark sudah siap). Saat ini, peluncur membuat dan menghancurkan setiap percikan. Gunakan pool dari Unity:

  • Di Launcher.cs, buat ObjectPool<Spark> di Awake. Pool ini membuat percikan dengan menginstansiasi sparkPrefab, mengaktifkan percikan saat diambil dan menonaktifkannya saat dikembalikan, serta menghancurkan object percikan saat melepasnya.
  • Pool menyimpan paling banyak 5 percikan cadangan, jadi setelah semburan berisi 8 percikan, 5 menunggu dan 3 dihancurkan.
  • Space mengambil 8 percikannya dari pool alih-alih membuatnya, dan Return mengembalikan percikan ke pool alih-alih menghancurkannya.

Tekan Play, tembakkan beberapa semburan, lalu tekan Check.

Coba sendiri

using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Pool;

public class Launcher : MonoBehaviour
{
    public Spark sparkPrefab;
    public int sparks = 8;

    void Awake()
    {
        // Buat pool: buat, ambil, lepaskan, dan hancurkan, dengan maksimal 5 percikan cadangan
    }

    void Update()
    {
        if (Keyboard.current.spaceKey.wasPressedThisFrame)
        {
            for (int i = 0; i < sparks; i++)
            {
                Spark spark = Instantiate(sparkPrefab);
                spark.transform.position = transform.position + Vector3.up;
                spark.Launch(Direction(i), this);
            }
        }
    }

    // Percikan yang masa hidupnya sudah berakhir
    public void Return(Spark spark)
    {
        Destroy(spark.gameObject);
    }

    // Ke luar dan ke atas, tersebar merata di sekeliling peluncur
    Vector3 Direction(int i)
    {
        return Quaternion.Euler(0f, i * 360f / sparks, 0f) * new Vector3(0f, 1f, 3f);
    }
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Arsitektur Game di Unity