Menu
CoddyTech

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.

challenge icon

Görev

Orta

Bir 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.cs içinde, void Enter(), void Tick() ve void Exit() içeren public interface IState tanımla.
  • TurretStates.cs iç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 -45 ile 45 arasında hareket eder. Enter ayrıca başı Color.green rengine boyar.
  • AlertState, başı ve oyuncuyu alır. Enter başı Color.red rengine boyar ve Intruder! mesajını günlüğe yazar; Tick, başı yalnızca y ekseninde, eğmeden oyuncuya dönük hale getirir; Exit, All clear mesajını günlüğe yazar.
  • Turret.cs içinde, Start'ta iki durumu da oluştur ve taramayı başlat. Her karede, oyuncu tarete range (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
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