Sınıflar Olarak Durumlar
Coddy'nin Unity Journey'sinin Unity'de Oyun Mimarisi bölümünün bir parçası. Ders 28 / 50.
3. bölümdeki enum üzerindeki switch, tüm durumların işini tek bir Update içinde tutar. Durumların kendilerine ait verileri olduğunda bu yaklaşım ölçeklenemez: yalnızca tek bir durumun kullandığı bir zamanlayıcı, MonoBehaviour'ın alanı hâline gelir ve diğer tüm durumların alanlarının yanına eklenir; ayrıca her case, kullandığı değerleri sıfırlamayı hatırlamak zorunda kalır. C#'taki durum kalıbı, her duruma kendine ait bir sınıf verir ve her sınıf tek bir arayüzü uygular. Bu yol işareti yanıp söner veya sürekli yanık kalır; Space bu iki durum arasında geçiş yapar:
public interface IState
{
void Enter();
void Tick();
void Exit();
}
public class BlinkState : IState
{
private Renderer lamp;
private float timer;
public BlinkState(Renderer lamp)
{
this.lamp = lamp;
}
public void Enter() { timer = 0f; }
public void Tick()
{
timer += Time.deltaTime;
if (timer >= 0.5f)
{
timer = 0f;
lamp.enabled = !lamp.enabled;
}
}
public void Exit() { lamp.enabled = true; }
}
public class SteadyState : IState
{
public void Enter() { }
public void Tick() { }
public void Exit() { }
}
public class Beacon : MonoBehaviour
{
public Renderer lamp;
private IState blink;
private IState steady;
private IState current;
void Start()
{
blink = new BlinkState(lamp);
steady = new SteadyState();
SetState(steady);
}
void Update()
{
if (Keyboard.current.spaceKey.wasPressedThisFrame) SetState(current == steady ? blink : steady);
current.Tick();
}
void SetState(IState next)
{
if (current != null) current.Exit();
current = next;
current.Enter();
}
}Durumlar MonoBehaviour değil, yalın C# sınıflarıdır. Bunları new ile oluşturur ve ihtiyaç duydukları şeyleri kurucu aracılığıyla verirsin; burada Renderer olan lambayı veriyoruz. Çünkü bunlar bileşen değildir ve GetComponent çağırıp Inspector'da alan gösteremezler. Unity de metotlarını kendiliğinden çağırmaz: MonoBehaviour olan Beacon'dır, dolayısıyla Update'i her karede current.Tick() çağırır.
timer yalnızca BlinkState'e aittir ve Enter, işaret her yanıp sönmeye başladığında onu 0'a ayarlar. Exit, durum sona erdiğinde ortalığı toparlar: lamba kapalıyken Space'e basılabilir ve Exit lambayı yeniden yakar; böylece SteadyState hiçbir zaman karanlık bir lambayla başlamaz. SetState önce eski durumun Exit metodunu, ardından yeni durumun Enter metodunu çalıştırır. Yavaş titreşim gibi üçüncü bir durum için bir sınıf daha eklenir; Beacon'ın Update metodu değişmez.
Görev
OrtaBir nöbetçi taret avluyu koruyor. Ok tuşları Oyuncuyu hareket ettiriyor (hazır). Tarete sınıflar olarak yazılmış iki durum ver:
IState.csiçinde,void Enter(),void Tick()vevoid Exit()içerenpublic interface IStatetanımla.TurretStates.csiçinde, bu arayüzü uygulayan iki sıradan sınıf yaz.ScanState, kurucusunda taretin başını alır. Başı bir yandan diğer yana tarar: başın yerel y açısı, tarama her başladığında 0'dan başlayıp yukarı doğru dönecek şekilde, saniyede 90 derece hızla-45ile45arasında hareket eder. Enter ayrıca başıColor.greenrengine boyar.AlertState, başı ve oyuncuyu alır. Enter başıColor.redrengine boyar veIntruder!mesajını günlüğe yazar; Tick, başı yalnızca y ekseninde, eğmeden oyuncuya dönük hale getirir; Exit,All clearmesajını günlüğe yazar.Turret.csiçinde, Start'ta iki durumu da oluştur ve taramayı başlat. Her karede, oyuncu tareterange(4) değerinden daha yakın olduğunda uyarı durumuna, yakın olmadığında ise tarama durumuna geç; ardından mevcut durumun Tick metodunu çalıştır. Durum değişikliği, önce eski durumun Exit metodunu, sonra yeni durumun Enter metodunu çalıştırır.
Play'e bas, tarete doğru yürü ve sonra uzaklaş; ardından Check'e bas.
Kendin dene
using UnityEngine;
// ScanState ve AlertState
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
1Hiyerarşiler Değil, Bileşenler
Küçük BileşenlerTemel Bir Düşman BetiğiSoyut BileşenlerBirlikte Çalışan BileşenlerÖzet: Modüler Taret4Serileştirilmiş Veriler
Serileştirilebilir SınıflarInspector'da ListelerInspector'da Enum'larÖzet: Ganimet Tablosu7Durum Makineleri
Sınıflar Olarak DurumlarBir Durum MakinesiGeçişlerDüşmanların Yapay ZekâsıTekrar: Kapı Durumları10Proje: Arena Hayatta Kalma
KahramanDüşman Türleri5ScriptableObjects
Veri VarlıklarıSilah İstatistikleriPaylaşılan AyarlarVeri Olarak DalgalarTekrar: Eşya Veritabanı8Yeniden Kullanılabilir Kod
Genişletme MetotlarıGeneric SingletonGeneric YardımcılarTekrar: FindNearest