UNİTY İLE PROJE YAPISINI KURMAK VE UZUN VADELİ ÖLÇEKLENEBİLİRLİK SAĞLAMAK
Bir Unity projesi büyüdükçe “küçük kararların” etkisi katlanır: klasör isimleri, bağımlılıkların yönü, sahnelerin sorumlulukları, prefab hiyerarşisi ve veri akışı… İlk hafta sorun çıkarmayan şeyler, üçüncü ayda ekip hızını düşüren birer sürtünme noktası haline gelir.
Bu yazıda, Unity proje yapısı kurarken uzun vadede ölçeklenebilirliği destekleyen pratik bir yaklaşım anlatıyorum. Amaç; yeni birinin projeye hızlı girebilmesi, geliştirme sürecinin öngörülebilir olması ve değişikliklerin daha az riskle yayımlanabilmesidir.
Okurken kendi ürününüzü düşünün: farklı disiplinlerin aynı repo üzerinde çalıştığı, sürüm çıktılarının düzenli alındığı ve “işi bugün bitirelim” ile “yarın bakımını yapabilelim” dengesinin kritik olduğu senaryolarda, aşağıdaki adımlar doğrudan karşılık bulur.
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.

İ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.
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.
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.
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.

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.
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.
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.

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.
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.
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.
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.






