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.
Tantangan
SedangKembang 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, buatObjectPool<Spark>di Awake. Pool ini membuat percikan dengan menginstansiasisparkPrefab, 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
Returnmengembalikan 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);
}
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Arsitektur Game di Unity
1Komponen, Bukan Hierarki
Komponen KecilSkrip Dasar MusuhKomponen AbstrakKomponen yang Bekerja SamaRingkasan: Turret Modular5ScriptableObjects
Aset DataStatistik SenjataPengaturan BersamaGelombang sebagai DataUlasan: database Item8Kode yang Dapat Digunakan Kembali
Extension methodSingleton GenerikHelper GenerikUlasan: FindNearest