Unity Platformer: Koleksiyon ve Puan Sistemi Nasıl Yapılır?

Unity'de platformer oyunlarınız için etkili bir koleksiyon eşyası ve puan sistemi oluşturmayı öğrenin. Temel kurulumdan ileri ipuçlarına kadar her şey bu rehberde!

Platformer oyunların vazgeçilmez unsurlarından biri, oyuncuların toplayabileceği eşyalar ve bu eşyaların oyuna kattığı puan sistemidir. Bu sistemler, oyunculara hedef belirleme, ilerleme hissi ve tekrar oynanabilirlik sunarak oyun deneyimini zenginleştirir. Bu kapsamlı rehberde, Unity’de sıfırdan bir Unity Koleksiyon Sistemi ve puan sistemi nasıl kurulur, temel adımlardan ileri seviye optimizasyonlara kadar detaylı bir şekilde inceleyeceğiz.

Kısa Özet

Bu makale, Unity’de bir platformer oyunu için koleksiyon eşyalarını (madeni para, mücevher vb.) ve bir puan sistemini nasıl entegre edeceğinizi adım adım açıklayacaktır. `Collider`’ların doğru kullanımı, UI (Kullanıcı Arayüzü) güncellemeleri, performans ipuçları ve sık karşılaşılan hataların çözümleri üzerinde duracağız. Amacımız, oyuncu etkileşimini artıracak ve oyununuza değer katacak sağlam bir Unity Koleksiyon Sistemi oluşturmaktır.

Konunun Temelleri ve Orta Seviye Detaylar

1. Koleksiyon Eşyaları (Collectibles) Nedir ve Neden Önemlidir?

Koleksiyon eşyaları, oyuncuların oyun dünyasında bulup toplayabileceği nesnelerdir. Bunlar genellikle madeni paralar, mücevherler, güçlendirmeler (power-ups) veya anahtarlar olabilir. Platformer oyunlarda:

  • İlerleme Hissi: Oyunculara bir hedef sunar.
  • Keşif Teşviki: Oyuncuları seviyeleri daha dikkatli keşfetmeye yönlendirir.
  • Puanlama: Oyuncunun performansını ölçmek ve rekabet unsuru eklemek için kullanılır.

2. Puan Sistemi Nasıl Çalışır?

Puan sistemi, toplanan her eşya için oyuncuya belirli bir değer atar. Bu değerler toplanarak toplam puanı oluşturur ve genellikle oyunun UI’ında gösterilir. Temel bir puan sistemi için şunlara ihtiyacımız var:

  • Toplam puanı tutacak bir değişken.
  • Puanı artıracak bir metod.
  • Puanı ekranda gösterecek bir UI elemanı (örneğin, `Text` veya `TextMeshPro`).

3. Unity Kurulumu: Sahne ve Objeler

Öncelikle Unity projenizde temel bir platformer sahnesine sahip olduğunuzu varsayalım. Bir oyuncu karakteri, zeminler ve kameranız hazır olmalı. Şimdi koleksiyon eşyamızı ve puan sistemimizi entegre edelim.

a) Koleksiyon Eşyası Oluşturma

  1. Bir 3D küp veya 2D sprite kullanarak basit bir koleksiyon eşyası (`Coin` veya `Gem`) oluşturun.
  2. Bu objeye bir `Collider2D` (örneğin, `CircleCollider2D` veya `BoxCollider2D`) ekleyin ve `Is Trigger` kutucuğunu işaretleyin. Bu, objelerin çarpışma yerine tetikleyici olarak davranmasını sağlar.
  3. Objeye bir `Rigidbody2D` ekleyin. `Body Type`’ını `Kinematic` olarak ayarlayabilirsiniz, çünkü bu objenin fiziksel olarak hareket etmesini istemiyoruz.
  4. Yeni bir C# scripti oluşturun (örneğin, `Collectible.cs`) ve objeye ekleyin.

// Collectible.cs
using UnityEngine;

public class Collectible : MonoBehaviour
{
    public int scoreValue = 10;

    private void OnTriggerEnter2D(Collider2D other)
    {
        // Eğer çarpan obje oyuncu ise
        if (other.CompareTag("Player"))
        {
            // Oyuncuya puan ekle
            ScoreManager.Instance.AddScore(scoreValue);

            // Koleksiyon eşyasını yok et
            Destroy(gameObject);
        }
    }
}

Bu kodda, `OnTriggerEnter2D` metodu, başka bir `Collider2D` bu objenin tetikleyicisine girdiğinde çalışır. `CompareTag(“Player”)` ile çarpan objenin etiketinin “Player” olup olmadığını kontrol ediyoruz. Oyuncunuzun etiketini “Player” olarak ayarlamayı unutmayın. Ardından `ScoreManager` aracılığıyla puanı artırıp objeyi yok ediyoruz.

b) Puan Yöneticisi (Score Manager) Oluşturma

Puanı yönetmek ve UI’ı güncellemek için merkezi bir yöneticiye ihtiyacımız var. `ScoreManager.cs` adında yeni bir script oluşturun ve boş bir GameObject’e (örneğin, “GameManager”) ekleyin.


// ScoreManager.cs
using UnityEngine;
using TMPro; // TextMeshPro kullanıyorsanız bu satırı ekleyin

public class ScoreManager : MonoBehaviour
{
    public static ScoreManager Instance; // Singleton yapısı

    public int currentScore = 0;
    public TextMeshProUGUI scoreText; // Veya UnityEngine.UI.Text

    void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
        } else if (Instance != this)
        {
            Destroy(gameObject);
        }
    }

    void Start()
    {
        UpdateScoreUI();
    }

    public void AddScore(int amount)
    {
        currentScore += amount;
        UpdateScoreUI();
        Debug.Log("Current Score: " + currentScore);
    }

    void UpdateScoreUI()
    {
        if (scoreText != null)
        {
            scoreText.text = "Puan: " + currentScore.ToString();
        }
    }
}

Bu script bir Singleton deseni kullanarak `ScoreManager`’a her yerden kolayca erişilmesini sağlar. `AddScore` metodu puanı artırır ve `UpdateScoreUI` metodunu çağırarak arayüzü günceller. `TextMeshPro` kullanıyorsanız, `using TMPro;` satırını eklediğinizden ve `TextMeshProUGUI` tipini kullandığınızdan emin olun. Eğer standart Unity UI `Text` kullanıyorsanız, `using UnityEngine.UI;` ekleyip `Text` tipini kullanın.

c) UI Kurulumu

  1. Hiyerarşi penceresinde sağ tıklayın: `UI -> Canvas` oluşturun.
  2. `Canvas` altına `UI -> Text (TextMeshPro)` veya `UI -> Text` ekleyin.
  3. Bu Text objesinin adını “ScoreText” olarak değiştirin ve uygun bir konuma yerleştirin.
  4. `GameManager` objesindeki `ScoreManager` scriptine, oluşturduğunuz “ScoreText” objesini sürükleyip bırakarak `scoreText` alanına atayın.

Pratik İpuçları

1. Ses Efektleri ve Görsel Geri Bildirim

Bir koleksiyon eşyası toplandığında, oyuncuya görsel ve işitsel geri bildirim vermek deneyimi çok daha tatmin edici hale getirir. `Collectible` scriptinize bir `AudioSource` ve `ParticleSystem` ekleyebilirsiniz:


// Collectible.cs (Güncellenmiş)
using UnityEngine;

public class Collectible : MonoBehaviour
{
    public int scoreValue = 10;
    public AudioClip collectSound; // Toplama sesi
    public GameObject collectEffectPrefab; // Parçacık efekti prefab'ı

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
        {
            ScoreManager.Instance.AddScore(scoreValue);

            // Ses çal
            if (collectSound != null)
            {
                AudioSource.PlayClipAtPoint(collectSound, transform.position);
            }

            // Efekt oluştur
            if (collectEffectPrefab != null)
            {
                Instantiate(collectEffectPrefab, transform.position, Quaternion.identity);
            }

            Destroy(gameObject);
        }
    }
}

Bu, oyuncunun her koleksiyon eşyası topladığında küçük bir zafer anı yaşamasını sağlar ve Unity Koleksiyon Sistemi‘ni daha çekici kılar.

2. Object Pooling Kullanımı (Performans Optimizasyonu)

Özellikle çok sayıda koleksiyon eşyasının olduğu seviyelerde, her eşya toplandığında `Destroy` ve yeni eşyalar oluşturulduğunda `Instantiate` kullanmak performans düşüşlerine yol açabilir. Bunun yerine, Object Pooling (Nesne Havuzlama) tekniğini kullanmak çok daha verimlidir. Bu teknikte, başlangıçta belirli sayıda koleksiyon eşyası oluşturulur ve toplandıklarında yok etmek yerine devre dışı bırakılıp (deactivate) havuza geri gönderilirler. İhtiyaç duyulduğunda havuzdan tekrar aktif hale getirilirler. Bu, bellek ayırma (memory allocation) ve çöp toplama (garbage collection) maliyetlerini azaltır.

3. Scriptable Object ile Koleksiyon Eşyası Verilerini Yönetme

Farklı türde koleksiyon eşyalarınız (altın, gümüş, mücevher) varsa, her biri için ayrı `scoreValue` tanımlamak yerine bir `ScriptableObject` kullanabilirsiniz. Bu, eşya verilerini merkezi ve kolayca yönetilebilir hale getirir.


// CollectibleData.cs (ScriptableObject)
using UnityEngine;

[CreateAssetMenu(fileName = "NewCollectibleData", menuName = "Collectible/Data")]
public class CollectibleData : ScriptableObject
{
    public string collectibleName = "Coin";
    public int scoreValue = 10;
    public AudioClip collectSound;
    public GameObject collectEffectPrefab;
}

Ardından `Collectible.cs` scriptinizde bu `CollectibleData` objesini referans alırsınız:


// Collectible.cs (ScriptableObject ile)
using UnityEngine;

public class Collectible : MonoBehaviour
{
    public CollectibleData data; // ScriptableObject verisi

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
        {
            ScoreManager.Instance.AddScore(data.scoreValue);

            if (data.collectSound != null)
            {
                AudioSource.PlayClipAtPoint(data.collectSound, transform.position);
            }

            if (data.collectEffectPrefab != null)
            {
                Instantiate(data.collectEffectPrefab, transform.position, Quaternion.identity);
            }
            Destroy(gameObject);
        }
    }
}

Bu yaklaşım, farklı koleksiyon eşyaları tanımlamanızı ve özelliklerini Unity editöründen kolayca ayarlamanızı sağlar. Bu da Unity Koleksiyon Sistemi‘nin esnekliğini artırır.

Yaygın Hatalar ve Çözümleri

  • `Is Trigger` işaretlenmemiş: Koleksiyon eşyasının `Collider2D` bileşeninde `Is Trigger` kutucuğunu işaretlemeyi unutmak, `OnTriggerEnter2D` metodunun tetiklenmemesine neden olur. Çözüm: İşaretleyin.
  • Yanlış Collider Tipi: 2D oyunlarda `Collider` yerine `Collider2D` kullanmak gerekir. Aksi takdirde çarpışma algılanmaz. Çözüm: Doğru 2D bileşenlerini kullanın (`BoxCollider2D`, `CircleCollider2D` vb.).
  • Oyuncu Etiketi (Tag) Ayarlanmamış: Oyuncu objenizin etiketini (“Player” gibi) doğru şekilde ayarlamamak, `other.CompareTag(“Player”)` kontrolünün her zaman `false` dönmesine neden olur. Çözüm: Oyuncuya doğru etiketi atayın.
  • UI Güncellenmiyor: `scoreText` referansının `ScoreManager` scriptinde atanmamış olması veya `UpdateScoreUI()` metodunun çağrılmaması, UI’ın güncellenmemesine yol açar. Çözüm: `scoreText` referansını atayın ve `AddScore` içinde `UpdateScoreUI()`’ı çağırdığınızdan emin olun.
  • Singleton Deseni Hataları: `Awake` metodunda `Instance` atamalarını doğru yapmamak, birden fazla `ScoreManager` objesinin oluşmasına veya `null` referans hatalarına yol açabilir. Çözüm: Yukarıdaki Singleton yapısını dikkatle uygulayın.

Performans ve Optimizasyon Notları

Yukarıda bahsedilen Object Pooling, performansı artırmak için en önemli adımlardan biridir. Bunun yanı sıra:

  • `FindObjectOfType` Kullanımından Kaçının: `Start()` veya `Awake()` dışında `FindObjectOfType()` gibi metodları sıkça kullanmak performans düşüşüne neden olur. Singleton deseni bu sorunu çözer.
  • UI Batching: Birden fazla UI elemanı kullanıyorsanız, bunları aynı Canvas altında tutarak ve olabildiğince az `Graphic Raycaster` kullanarak UI çizim çağrılarını (batching) optimize edebilirsiniz.
  • Gereksiz Fizik Hesaplamaları: Koleksiyon eşyaları gibi statik objeler için `Rigidbody2D`’nin `Body Type`’ını `Kinematic` olarak ayarlayarak gereksiz fizik hesaplamalarını önleyin.

Bu rehber sayesinde, Unity platformer oyunlarınız için sağlam ve optimize edilmiş bir Unity Koleksiyon Sistemi ve puan sistemi oluşturma konusunda güçlü bir temel atmış olmalısınız. Oyununuzu daha etkileşimli ve eğlenceli hale getirmek için bu teknikleri kullanmaktan çekinmeyin!

Leave a Reply

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir