UNITY İLE PROJE YAPISINI KURMAK VE UZUN VADELİ ÖLÇEKLENEBİLİRLİK SAĞLAMAK

Animasyon Akademi12 dk okuma
Unity logosu yanında büyük klasör ağacı Assets Scripts Scenes Prefabs hiyerarşisi diyagramı

Unity’de doğru kurulmuş bir proje yapısı, projeyi büyürken yavaşlatan sürtünme noktalarını en baştan önler; bu yazıda klasör düzenini, bağımlılık yönetimini, ScriptableObject tabanlı veri akışını, adreslenebilir varlıkları, versiyon kontrolü ve build otomasyonunu kurarak uzun vadeli ölçeklenebilirlik sağlamayı öğreneceksiniz.

1. Unity proje yapısı için net bir klasör düzeni kurmak

Ölçeklenebilirlik için ilk adım, içeriklerin rastgele değil amaç odaklı yerleşmesidir. “Assets içinde her şey var” yaklaşımı kısa vadede hızlı görünür; uzun vadede ise arama, taşıma ve bağımlılık yönetimini zorlaştırır. Burada hedef; “bir şey nerede olmalı?” sorusunun ekip içinde tartışma konusu olmamasıdır.

Kök dizinde okunabilir bir hiyerarşi oluşturmak

Pratik bir başlangıç şablonu şu şekilde olabilir:

  • Assets/_Project: Projeye özel tüm kod ve içerikler
  • Assets/_Project/Art: Model, materyal, shader, VFX, UI görselleri
  • Assets/_Project/Audio: Sesler ve miks ayarları
  • Assets/_Project/Prefabs: Prefab varlıkları
  • Assets/_Project/Scenes: Oyun sahneleri
  • Assets/_Project/Scripts: Runtime ve Editor kodları
  • Assets/_Project/Settings: ScriptableObject ayar varlıkları

Üçüncü parti paketleri ise ayrı tutmak iyi bir alışkanlıktır. Paketleri Packages altında yönetmek ve proje içi kodu “_Project” altında toplamak, güncelleme/geri dönüş süreçlerini daha güvenli hale getirir.

Unity Editor Project window panelinde Assets _Project Art Audio Prefabs Scenes Scripts Settings klasör listesi

İsimlendirme kurallarını yazılı hale getirmek

Dosya isimlerinde karışıklık çıktığında, zaman kaybı çoğu zaman arama değil karar verme aşamasında yaşanır. Bu yüzden küçük bir “kural seti” belirlemek önemlidir: Prefab’lar “PF_”, ScriptableObject ayarları “SO_”, sahneler “SC_” gibi ön ekler; UI varlıklarında “UI_” gibi net ayrımlar. Böyle bir standardın amacı estetik değil, sürtünmeyi azaltmaktır.

2. Bağımlılık yönetimini doğru yönde kurgulamak

Projeler büyürken en sık görülen sorunlardan biri, kodun birbirine “yanlış yönde” bağlanmasıdır. UI’nın gameplay’e, gameplay’in altyapıya, altyapının da UI’ya bağlandığı döngüsel bir yapı test etmeyi, yeniden kullanımı ve refaktörü zorlaştırır. Burada ana hedef; bağımlılıkları tek yöne akıtmaktır.

Assembly Definition ile modülerleşmeyi planlamak

Assembly Definition (asmdef) kullanmak, derleme sürelerini düşürmenin yanı sıra modüler tasarım için de güçlü bir araçtır. Örnek bir ayrım:

  • Project.Core (genel altyapı, yardımcılar)
  • Project.Gameplay (oyun kuralları ve sistemleri)
  • Project.UI (arayüz katmanı)
  • Project.Editor (sadece editor araçları)

Bu ayrımın içinde, UI’nın doğrudan Gameplay sınıflarına bağlanması yerine, araya bir “Application” katmanı koymak veya mesajlaşma/olay sistemi kullanmak daha sürdürülebilir olur. Burada önemli olan, kararın en baştan verilmesi değil; bilinçli bir yönlendirme ile büyümeye izin vermektir.

Bağımlılıkları görünür kılan pratik kontrol listesi çıkarmak

Her büyük eklemeden sonra şu soruları sormak iyi çalışır: “Bu sınıf hangi katmana ait?”, “Bu referans ters yönde mi?”, “Bu sistem tek sorumluluk mu taşıyor?”. Bu tür kontrol listeleri, ekip içi code review’larda aynı dili konuşmayı sağlar ve sürprizleri azaltır.

3. ScriptableObject ve veri akışıyla esnek bir mimari kurmak

Unity’de veri odaklı yaklaşım, hem tasarım hem de geliştirme tarafında hız kazandırır. Burada ScriptableObject’ler, ayarları koddan ayırmak, farklı varyasyonları hızlıca denemek ve sahne bağımlılığını azaltmak için ideal bir araçtır. Özellikle dengeleme (balance), item/skill tanımları, UI temaları ve yapılandırma değerleri için güçlü bir temel sunar.

Konfigürasyonu sahneden ayırmak ve tekrar kullanılabilir yapmak

Bir sahne kapandığında kaybolmaması gereken veriler (örneğin oyun ekonomisi ayarları) sahne objelerine değil, ayrı varlıklara taşındığında bakım kolaylaşır. Ayrıca aynı ayar seti farklı sahnelerde tutarlı davranış sağlar.

// Örnek: Oyun ayarlarını ScriptableObject ile yönetmek
using UnityEngine;

[CreateAssetMenu(menuName = "Project/Settings/GameConfig")]
public class GameConfig : ScriptableObject
{
    public int targetFrameRate = 60;
    public float masterVolume = 0.8f;
    public string defaultLanguage = "tr";
}

Bu yaklaşımın yanında, runtime’da bu ayarları uygulayan tek bir başlangıç noktası tanımlamak önemlidir. Dağınık “Start() içinde ayar uygulama” yaklaşımı yerine, merkezi bir bootstrap akışı daha kontrollüdür.

Olay tabanlı iletişimle katmanlar arası bağı gevşetmek

UI’nın gameplay’den haberdar olması gerekir; ama bu, doğrudan sınıf referansı anlamına gelmek zorunda değildir. Olaylar, sinyaller veya basit bir “event bus” yaklaşımıyla UI’yı daha bağımsız hale getirebilirsiniz. Böylece farklı ekranların eklenmesi veya kaldırılması daha düşük risk taşır.

4. Adreslenebilir varlıklarla içerik ölçeklemek

İçerik sayısı arttıkça asset yönetimi de zorlaşır. Bu noktada adreslenebilir varlıklar yaklaşımı, içerikleri gruplamak, yükleme stratejisini netleştirmek ve paketleme süreçlerini kontrol etmek için önemli avantajlar sağlar. Özellikle çok sayıda prefab, büyük doku setleri veya çok dilli içerikler olan projelerde etkisi belirginleşir.

Yükleme stratejisini tasarım kararı olarak ele almak

“Her şeyi başta yükleyelim” yaklaşımı, ilk çalıştırma süresini ve bellek kullanımını şişirebilir. Bunun yerine ekran akışına göre yükleme planı yapmak, kullanıcı deneyimini daha tutarlı kılar. Örneğin ana menü, oyun içi, mağaza gibi bölümler ayrı gruplar olarak ele alınabilir.

Unity Addressables Groups window tree Default Local UI MainMenu Gameplay Shop grup listesi Bundle Mode kolonu

Basit bir Addressables kullanım örneğiyle riskleri azaltmak

Teknik ekip için önemli nokta, yükleme/boşaltma döngüsünü kontrol altında tutmaktır. Basit bir örnek:

// Örnek: Addressables ile prefab yüklemek ve instantiate etmek
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public class SpawnWithAddressables : MonoBehaviour
{
    [SerializeField] private AssetReferenceGameObject enemyRef;

    public void Spawn(Vector3 position)
    {
        enemyRef.InstantiateAsync(position, Quaternion.identity)
            .Completed += OnSpawned;
    }

    private void OnSpawned(AsyncOperationHandle<GameObject> handle)
    {
        if (handle.Status != AsyncOperationStatus.Succeeded) return;

        GameObject enemy = handle.Result;
        // Burada gerekli init işlemleri yapılabilir
    }
}

Bu örnekte en sık unutulan parça, ihtiyaç bittiğinde varlıkları serbest bırakmaktır. Ölçek büyüdükçe bellek yönetimi bir “sonradan bakarız” konusu olmaktan çıkar; planlı bir disiplin haline gelir.

5. Versiyon kontrolü ve proje hijyeniyle çatışmaları azaltmak

Birden fazla kişinin aynı projede çalıştığı ortamlarda, versiyon kontrolü sadece “dosya saklama” değil, ekip verimliliğini belirleyen bir süreçtir. Unity projelerinde özellikle meta dosyaları, sahne/prefab değişiklikleri ve büyük dosyalar doğru yönetilmediğinde günlük çalışma temposu ciddi şekilde düşebilir.

Unity ayarlarını versiyon kontrolüne uygun hale getirmek

En temel adımlardan biri, meta dosyalarının ve text serialization ayarlarının doğru kurgulanmasıdır. Böylece sahne/prefab farklarını daha okunur hale getirir, merge çatışmalarını azaltırsınız. Ek olarak, “hangi klasörler repoya girer” sorusunun net cevabı olmalıdır. Library gibi türetilen klasörleri repo dışında tutmak, repoyu daha sağlıklı hale getirir.

Branch stratejisini ekip ritmine göre seçmek

Basit bir akış çoğu ekipte iyi çalışır: ana dal (main) her zaman çalışır durumda, geliştirme dalı (develop) günlük entegrasyon için, feature branch’ler ise izole geliştirme için. Burada kritik olan, “çok uzun yaşayan branch” alışkanlığını azaltmaktır. Küçük ve sık entegre edilen değişiklikler, sürprizleri düşürür.

6. CI/CD ve build otomasyonuyla teslim süreçlerini standartlamak

Ölçeklenebilirlik yalnızca kodun düzeni değildir; teslim ve test süreçlerinin tekrarlanabilir olması da aynı ölçüde önemlidir. Build’in “birinin bilgisayarında” alınması, hata ayıklamayı zorlaştırır ve sürüm güvenilirliğini düşürür. Otomasyon ise bu riski azaltır.

Build pipeline’ı yazılı bir süreç haline getirmek

Hangi platformlara build alınacak, sürüm numarası nasıl artacak, hangi sahneler build’e girecek, hangi ayarlar ortam bazlı değişecek… Bu soruların cevabı net değilse, teslimler kişiye bağımlı hale gelir. Süreci standartlaştırmak, ekibin her üyesine güven verir ve hız kazandırır.

Test otomasyonu ve kalite kapıları eklemek

Her projede kapsamlı test kurmak mümkün olmayabilir; ama küçük bir başlangıç bile büyük fark yaratır. Örneğin temel oyun kuralları için editmode testleri, kritik akışlar için playmode testleri ve her merge öncesi otomatik çalıştırma. Burada amaç, hatayı erken yakalamaktır.

GitHub Actions YAML workflow dosyası unity build job steps checkout setup-unity build matrix iOS Android WebGL

7. Profiling, loglama ve bakım maliyetini azaltmak

Performans sorunları genellikle “en sonunda” değil, proje büyürken yavaş yavaş birikir. Düzenli performans profilleme alışkanlığı, sürprizleri azaltır. Aynı şekilde logların yapılandırılması, canlı ortamda hata yakalamayı kolaylaştırır.

Profiler kullanımını düzenli bir ritme oturtmak

Her sprint sonunda kısa bir profil kontrolü yapmak, özellikle mobil hedeflerde büyük kazanç sağlar. CPU, GPU, garbage collection, draw call gibi metrikler; “hangi değişiklik neyi etkiledi?” sorusunun cevabını somutlaştırır.

Log seviyeleriyle hata ayıklamayı yönetilebilir kılmak

Her yerde Debug.Log yazmak kısa vadede yardımcı olur; uzun vadede gürültüye dönüşür. Log seviyelerini (info/warn/error) düzenlemek, kritik hataları öne çıkarır ve ekip içi iletişimi kolaylaştırır. Üretim ortamında logların güvenliğini ve kişisel verileri de göz önünde bulundurmak gerekir.

8. Ekibin ortak dilini güçlendirmek için eğitimle süreci hızlandırmak

Yukarıdaki yapı taşları tek tek uygulanabilir; ancak asıl değer, ekipte herkesin aynı yaklaşımı benimsemesiyle ortaya çıkar. Proje yapısı, modülerleşme, ScriptableObject tabanlı veri yönetimi, Addressables stratejisi ve otomasyon başlıklarında ortak pratikler oluşturmak, geliştirme hızını doğrudan etkiler.

Ortak pratikleri eğitimle standartlaştırmak

Bu konuları uygulamalı örneklerle ekip içinde standartlaştırmak isterseniz, Unity eğitimi kapsamında proje mimarisi, ölçeklenebilir yapı kurma ve üretim süreçleri üzerine hedefe yönelik içerikler planlanabilir. Hedef; herkesin aynı dili konuşması, daha az çatışma yaşaması ve daha öngörülebilir teslimler almasıdır.

İyi bir yapının gerçek anlamı

Sonuçta iyi bir Unity proje yapısı; sadece düzenli klasörlerden ibaret değildir. Bağımlılıkların yönünü doğru kurgulamak, veriyi sahneden ayırmak, içerik büyümesini planlamak ve teslim süreçlerini otomatikleştirmekle birlikte anlam kazanır. Bu parçaları erken ele almak, ileride çok daha büyük maliyetleri önler.

Sıkça Sorulan Sorular

Unity proje yapısı kurarken ilk hangi kararlar kritik olur?

İlk kritik kararlar klasör hiyerarşisi, isimlendirme standardı ve bağımlılıkların yönüdür. Kodun modüllere ayrılması, Editor ve Runtime ayrımı, üçüncü parti paketlerin izole edilmesi de erken belirlenirse büyüme daha sorunsuz olur. Bu kararlar, yeni birinin projeye giriş süresini kısaltır ve refaktör maliyetini azaltır.

Assembly Definition kullanmak derleme sürelerini nasıl etkiler?

Assembly Definition, kodu ayrı derleme birimlerine bölerek gereksiz yeniden derlemeleri azaltabilir. Özellikle büyük projelerde, küçük bir değişiklik yaptığınızda tüm kodun değil sadece ilgili modülün derlenmesi mümkün olur. Ayrıca katmanlar arası referansları sınırlayarak mimariyi daha disiplinli tutmanıza yardımcı olur.

ScriptableObject ile ayar yönetimi ne zaman tercih edilmeli?

Ayarların sık değiştiği, tasarım ekibinin deneme yaptığı veya farklı ortamlar için farklı değerler gerektiği durumlarda ScriptableObject iyi bir tercihtir. Sahneye bağlı olmadan konfigürasyon sağlayarak tekrar kullanılabilirliği artırır. Ayrıca sürüm kontrolünde ayar değişikliklerini izlemek daha kolay hale gelir.

Adreslenebilir varlıklar hangi projelerde daha çok fayda sağlar?

Çok sayıda prefab ve büyük içerik setleri olan, platforma göre farklı paketleme gerektiren veya yükleme süreleri kritik olan projelerde daha çok fayda sağlar. İçerikleri gruplandırmak, gerektiğinde yüklemek ve ihtiyaç bittiğinde serbest bırakmak kolaylaşır. Bu yaklaşım, bellek yönetimini ve sürüm boyutunu daha kontrollü hale getirir.

Unity projelerinde versiyon kontrolü için en sık yapılan hata nedir?

En sık yapılan hata, Unity’nin meta dosyalarını ve text serialization ayarlarını doğru yapılandırmamaktır. Bu durum sahne ve prefab merge çatışmalarını artırır, farklı makinelerde referansların bozulmasına yol açabilir. Ayrıca türetilen klasörlerin repoya eklenmesi repo şişmesine ve gereksiz sorunlara neden olur.

 ANİMASYON AKADEMİ