Unity'nin ObjectPool'ı
Coddy'nin Unity Journey'sinin Unity'de Oyun Mimarisi bölümünün bir parçası. Ders 48 / 64.
Unity, UnityEngine.Pool içindeki ObjectPool<T> havuzunu sunar. Dört lambda ile her adımda ne yapacağını belirtirsin; havuz da yedek nesneleri ve sayaçları yönetir. Bu baca her 0.2 saniyede bir duman püskürtür ve her duman püskürtüsü bir saniye sonra havuza geri döner:
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, Get havuzun boş olduğunu bulduğunda çalışır; actionOnGet her Get çağrısında, actionOnRelease ise her Release çağrısında çalışır. maxSize kadar yedek nesne zaten beklerken bir duman püskürtüsü serbest bırakılırsa havuz onu saklamaz: actionOnDestroy onu yok eder. defaultCapacity yalnızca havuz listesinin başlangıç boyutudur; dolayısıyla başlangıçta hiçbir nesne oluşturulmaz. CountAll, havuzun oluşturduğu ve hâlâ sahip olduğu duman püskürtülerinin sayısını; CountActive, oyunda olanların sayısını; CountInactive ise yedeklerin sayısını tutar. Get, baca onu yerleştirmeden önce duman püskürtüsünü etkinleştirir; burada sorun olmaz, çünkü Puff'ın konumunu okuyan bir OnEnable metodu yoktur. Duman püskürtüsü havuzu, her Unity havuzunun uyguladığı arayüz olan IObjectPool<Puff> olarak saklar ve Launch, her kullanımda yaşını sıfırlar.
collectionCheck açıkken, havuzda zaten bulunan bir duman püskürtüsünü serbest bırakmak bir InvalidOperationException hatasına yol açar: Trying to release an object that has already been released to the pool. Kontrol yalnızca Editor'de çalışır; çünkü her Release çağrısında yedekleri arar. Derlemede duman püskürtüsü havuzda iki kez bulunur ve iki Get çağrısı aynı nesneyi verir. Bunun yaygın bir nedeni, serbest bırakıldıktan sonra çalışmayı sürdürüp kendini tekrar serbest bırakan bir nesnedir; bu yüzden actionOnRelease nesneyi devre dışı bırakır.
Görev
OrtaHavai fişekleri Unity havuzundan fırlat.
Launcher'ınAwakemetodunda birObjectPool<Spark>oluştur:Instantiate(sparkPrefab)ile oluştur, havuzdan alındığında etkinleştir, bırakıldığında devre dışı bırak, havuza geri verildiğinde nesneyi yok et,maxSize: 5.Updateiçinde her kıvılcımıInstantiateyerinepool.Get()ile al.ReturniçindeDestroyyerinepool.Release(spark)çağır.
“Oyna”'ya bas ve birkaç salvo ateşle. Ardından “Kontrol et”'e bas.
Kendin dene
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Pool;
public class Launcher : MonoBehaviour
{
public Spark sparkPrefab;
public int sparks = 8;
void Awake()
{
// Havuzu oluştur: en fazla 5 yedek kıvılcım olacak şekilde oluşturma, alma, geri bırakma ve yok etme işlemlerini tanımla
}
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);
}
}
}
// Ömrü bitmiş bir kıvılcım
public void Return(Spark spark)
{
Destroy(spark.gameObject);
}
// Dışarı ve yukarı doğru, fırlatıcının çevresine eşit aralıklarla dağılmış
Vector3 Direction(int i)
{
return Quaternion.Euler(0f, i * 360f / sparks, 0f) * new Vector3(0f, 1f, 3f);
}
}
Unity'de Oyun Mimarisi bölümündeki tüm dersler
1Kalıtım Değil, Bileşenler
Küçük BileşenlerTemel Düşman Script'iSoyut BileşenlerBirlikte Çalışan BileşenlerTekrar: Modüler TaretTekrar: Çift Namlulu Top4Serileştirilmiş Veriler
Serileştirilebilir SınıflarInspector'da ListelerInspector'da Enum'larTekrar: Ganimet TablosuTekrar: Ganimeti At2Unity'de Arayüzler
IDamageableArayüzler ve TryGetComponentGetComponentsÖzet: Etkileşim TuşuÖzet: Erişim Mesafesindeki En Yakın5ScriptableObjects
Veri VarlıklarıSilah İstatistikleriOrtak AyarlarRüzgârı KaydetVeri Olarak DalgalarTekrar: Eşya VeritabanıTekrar: Dükkândan Satın Al8Yeniden Kullanılabilir Kod
Genişletme MetotlarıGeneric SingletonGeneric YardımcılarTekrar: FindNearest3Olaylar
Unity'de C# OlaylarıOnEnable'da Abone OlUnityEvent AlanlarıOlaylar UI'ı YönlendirirÖzet: Başarım Açılır PenceresiÖzet: Açılır Pencere Zamanlayıcısı6JSON ile Kaydetme
JsonUtilityOyunu KaydetmeYükleme ve VarsayılanlarÖzet: Kayıt YuvalarıBir Yuva Seçme ve Silme9Nesne Havuzu
Nesneleri Neden Havuzda ToplarızKuyruk Kullanan Bir HavuzUnity'nin ObjectPool'ıÖzet: Mermi HavuzuKendi başına pratik yap: Unity playground