UNİTY İLE MOBİLE OPTİMİZASYON YAPMAK VE BELLEK KULLANIMINI AZALTMAK
Mobilde “çalışıyor” demek çoğu zaman yetmez; önemli olan cihaz ısınıp pil tüketmeden, stabil FPS ile akıcı akmak ve bellek taşmasına yaklaşmadan güvenli sınırda kalmaktır. Unity ile geliştirilen uygulamalarda performans sorunları genellikle iki yerde toplanır: gereksiz bellek kullanımı ve beklenmedik kare süresi sıçramaları.
Bu yazıda, Unity mobile optimizasyon yaklaşımını uçtan uca ele alacağız: önce ölçmek, sonra hedef seçmek, ardından bellek kullanımını azaltmak için varlıkları (texture, model, ses) ve kodu düzenlemek. Amaç “rastgele ayar kurcalamak” değil; doğrulanabilir, tekrarlanabilir bir optimizasyon akışı kurmaktır.
İhtiyacınız olan şey, ekibin herkesçe aynı dili konuşmasıdır: profil alma, GC allocation, streaming, asset yükleme-boşaltma, cihaz testleri… Eğer ekipte ortak bir yöntem oturtmak isterseniz Unity eğitimi sayfasındaki kapsamı inceleyip aynı standartta ilerleyebilirsiniz.
Profil çıkarıp darboğazları doğru bulmak
Optimizasyonun ilk adımı, ölçmeden karar vermemektir. Editörde akıcı görünen bir sahne, gerçek cihazda CPU ve GPU yükleri yüzünden takılabilir. Bu yüzden önce hedef cihaz(lar) üzerinde profil çıkarıp hangi metriğin sorunlu olduğunu netleştirmek gerekir: kare süresi mi artıyor, bellek mi şişiyor, yoksa ikisi birden mi?
Unity Profiler ile bakmanız gereken temel alanlar: CPU Usage, Rendering, Memory, GC Alloc ve varsa Timeline görünümüdür. Özellikle mobilde küçük GC tahsisleri bile zamanla birikip ani GC spike olarak geri dönebilir.

Hedef cihazlarda ölçüm rutinini oturtmak
Bir “test sahnesi” hazırlayıp aynı rota ile uygulamayı gezmek, ölçümleri kıyaslamayı kolaylaştırır. Şu pratikler işinizi hızlandırır:
- Her ölçümde aynı sahne/rota ile ilerlemek
- Uygulamayı soğuk başlangıç ve sıcak başlangıç olarak ayrı izlemek
- En az 2–3 dakika çalıştırıp bellek trendini gözlemek
- FPS yerine frame time (ms) üstünden değerlendirmek
Memory Profiler ile snapshot karşılaştırmak
Bellek kullanımını azaltmak için “ne yiyor?” sorusuna net cevap gerekir. Memory Profiler paketinde iki snapshot alıp karşılaştırmak, sızıntı gibi görünen büyümelerin kaynağını hızlı yakalar: Textures mı şişiyor, Managed heap mi büyüyor, yoksa Native allocations mı artıyor?
GC tahsislerini azaltıp akıcılığı korumak
Mobilde takılmaların çok yaygın bir sebebi, kare sırasında gereksiz allocation oluşmasıdır. Özellikle Update içinde string birleştirmek, LINQ kullanmak, her kare yeni koleksiyon oluşturmak gibi alışkanlıklar GC allocation üretir. Bu tahsisler biriktiğinde, GC devreye girip kare süresini zıplatır.
Update döngüsünde allocation üretmemek
En iyi yöntem, “her kare çalışacak” kodu katı şekilde sadeleştirmektir. String formatlama, List büyütme, boxing gibi noktaları kontrol etmek gerekir. Aşağıdaki örnek, profil işaretleriyle hangi fonksiyonun kaç ms aldığını daha görünür kılmaya yarar:
using UnityEngine;
using Unity.Profiling;
public class MobileHotpathSample : MonoBehaviour
{
static readonly ProfilerMarker TickMarker = new ProfilerMarker("Gameplay.Tick");
void Update()
{
TickMarker.Begin();
// Hot path: burada allocation üretmemeye çalışın
// Örn: LINQ, string birleştirme, foreach boxing, yeni List oluşturma
SimulateGameplayTick();
TickMarker.End();
}
void SimulateGameplayTick()
{
// Basit örnek iş yükü
float t = Time.deltaTime;
transform.Rotate(0f, 90f * t, 0f);
}
}Object pooling ile sürekli üretmeyi bırakmak
Mermi, parçacık, UI toast gibi sık üretilip yok edilen objeler, hem CPU hem bellek tarafında maliyet çıkarır. Object pooling yaklaşımıyla instantiate/destroy döngüsünü azaltıp stabil kare süresi yakalamak kolaylaşır. Aşağıdaki örnek, basit bir havuz mantığını gösterir:
using System.Collections.Generic;
using UnityEngine;
public class SimplePool : MonoBehaviour
{
[SerializeField] GameObject prefab;
[SerializeField] int warmCount = 20;
readonly Queue<GameObject> pool = new Queue<GameObject>();
void Awake()
{
for (int i = 0; i < warmCount; i++)
{
var go = Instantiate(prefab);
go.SetActive(false);
pool.Enqueue(go);
}
}
public GameObject Get(Vector3 pos, Quaternion rot)
{
var go = pool.Count > 0 ? pool.Dequeue() : Instantiate(prefab);
go.transform.SetPositionAndRotation(pos, rot);
go.SetActive(true);
return go;
}
public void Release(GameObject go)
{
go.SetActive(false);
pool.Enqueue(go);
}
}Bu yaklaşım, özellikle yoğun anlarda kare süresi sıçramalarını belirgin şekilde azaltabilir. Havuz boyutunu, gerçek kullanım dağılımına göre ayarlamak önemlidir.
Texture ve atlas ayarlarını doğru seçmek
Mobilde bellek kullanımını azaltmak denince ilk büyük kalem genellikle texture olur. Aynı görsel kaliteyi daha düşük RAM ile taşımak mümkündür; kritik olan çözünürlük, sıkıştırma formatı, mipmap ve atlas stratejisidir. “Yüksek çözünürlük güven verir” yaklaşımı, cihaz tarafında bellek taşmasına gidebilir.
Sıkıştırma formatını hedef platforma göre seçmek
Android tarafında ASTC/ETC2 seçenekleri, iOS tarafında ASTC ve PVRTC gibi formatlar öne çıkar. Hedef cihaz kitlenize göre bir kalite/performans profili belirleyin. Büyük bir kazanım, sadece uygun sıkıştırmaya geçmekle bile gelebilir.

Mipmap ve çözünürlük bütçesini planlamak
Mipmap açmak, uzaktaki yüzeylerde kaliteyi korurken shimmering azaltır; ancak bellek maliyeti getirir. Bu yüzden UI elementlerinde mipmap kapatmak, 3D ortam dokularında ise kontrollü kullanmak mantıklıdır. Ayrıca “her şey 2048” yaklaşımı yerine, kategori bazlı bütçe tanımlamak faydalıdır: karakter, çevre, UI, ikonlar gibi.
Sprite Atlas ile draw call azaltmak
UI ve 2D projelerde sprite atlas kullanmak, rendering tarafında draw call sayısını düşürmeye yardım eder. Bu, doğrudan bellek değil; ama performans için kritik bir adımdır. Atlas stratejisini sahne akışına göre kurmak gerekir: aynı ekranda görünen sprite’ları aynı atlasta toplamak, yükleme-boşaltma maliyetini de yönetilebilir kılar.
Model, animasyon ve shader maliyetini dengelemek
3D projelerde bellek ve performansın bir diğer büyük kalemi modellerin vertex sayısı, animasyon rigleri ve shader karmaşıklığıdır. Mobilde hedef, “göze yeterli kalite”yi yakalarken maliyeti sürekli kontrol altında tutmaktır. Aşırı gerçekçilik uğruna cihazın sınırlarını zorlamak, kullanıcıyı doğrudan kaybettirir.
LOD kullanıp sahne yükünü hafifletmek
LOD (Level of Detail) ile uzaktaki objeleri daha düşük detaylı mesh’lerle göstermek, GPU ve CPU yükünü azaltır. Özellikle geniş açık sahnelerde bu yaklaşım, kare süresini daha stabil tutar. LOD geçiş mesafelerini cihaz testleriyle kalibre etmek en doğrusudur.
Animator katmanlarını sadeleştirip geçişleri azaltmak
Animator Controller karmaşıklaştıkça, değerlendirme maliyeti artar. Kullanılmayan layer’ları kaldırmak, gereksiz blend tree’leri azaltmak ve geçiş koşullarını sadeleştirmek mobilde fark yaratır. Ayrıca sık tekrar eden küçük animasyonlar için daha hafif çözümler (ör. basit timeline veya script tabanlı hareket) düşünülebilir.
Shader varyantlarını kontrol edip derlemeyi azaltmak
Mobilde shader varyantları, hem build süresini hem de çalışma zamanı bellek kullanımını etkileyebilir. Kullanılmayan keyword’leri temizlemek ve gerekli varyantları sınırlamak önemlidir. Özellikle URP kullanırken özellik setini proje ihtiyacına göre daraltmak, daha temiz bir çalışma alanı sağlar.
Sahne akışını düzenleyip yüklemeyi yönetmek
Bellek kullanımını azaltmak için en etkili yaklaşım, “her şeyi başta yüklemek” yerine, ihtiyaç oldukça yükleyip iş bitince boşaltmaktır. Mobilde RAM sınırlı olduğu için sahne akışını küçük modüller halinde tasarlamak, taşma riskini azaltır. Burada Addressables veya AssetBundle tabanlı bir yaklaşım, ekip ölçeklenince daha da değerli hale gelir.
Addressables ile içerik akışını planlamak
Addressables kullanıyorsanız, içerikleri gruplara ayırıp indirme ve yükleme anlarını oyun akışına yedirmek gerekir. “Bir anda büyük yük” yerine, kademeli yükleme kullanıcı deneyimini korur. İş bittiğinde referansları düşürmek ve uygun şekilde release etmek, bellek kullanımını azaltmak için kritiktir.
Sahne geçişlerinde bellek temizliği yapmak
Sahne değiştirirken, eski sahnenin bıraktığı referanslar yüzünden varlıklar RAM’de kalabilir. Bu yüzden geçiş noktalarında yükleme-boşaltma disiplinini takip etmek gerekir: kullanılmayan UI’ları kapatmak, event aboneliklerini kaldırmak, havuzları sahne bazlı yönetmek gibi.
UI ve veri katmanını hafif tutmak
UI, mobilde performansı sinsice etkileyebilir. Çok sayıda Canvas, gereksiz layout rebuild ve pahalı mask/blur gibi efektler kare süresini artırabilir. Veri katmanında ise gereksiz JSON ayrıştırma veya büyük listeleri her kare güncellemek, CPU yükünü yükseltir.
Canvas yeniden çizimini azaltıp düzeni korumak
Tek bir dev Canvas yerine, sık değişen ve sabit kalan UI parçalarını ayırmak daha sağlıklıdır. LayoutGroup ve ContentSizeFitter gibi bileşenleri “sürekli değişen” alanlarda dikkatli kullanmak gerekir. Gereksiz animasyonlar ve alfa geçişleri de mobilde maliyet çıkarabilir.
Veri güncellemelerini aralıklı yapıp yükü azaltmak
Skor, sayaç, liste gibi alanlarda her kare güncellemek yerine, değişim olduğunda veya belirli aralıklarla güncellemek daha verimlidir. Bu, hem CPU’yu rahatlatır hem de GC tahsislerini azaltmaya yardım eder.
Build ayarlarını doğru seçip sonuç almak
Uygulama ayarları da performansın bir parçasıdır. Scripting backend seçimi, managed stripping seviyesi, texture import ayarları, kalite profilleri ve hedef API’ler bir araya gelerek gerçek cihaz davranışını belirler. Tek bir “en iyi ayar” yoktur; hedef cihaz kitlesine göre denge kurmak gerekir.
IL2CPP ve stripping seviyesini test ederek seçmek
IL2CPP çoğu senaryoda mobilde iyi sonuç verir; ancak stripping seviyeleri bazı reflection senaryolarında sorun çıkarabilir. Bu yüzden build ayarlarını değiştirince mutlaka cihaz testleriyle doğrulamak gerekir. Hedef, daha küçük build ve daha az bellek ile stabil çalışmaktır.
Kalite seviyelerini cihaz sınıflarına göre ayırmak
Tek kalite profiliyle herkese aynı yükü vermek yerine, cihaz sınıflarına göre kalite seviyeleri sunmak kullanıcı deneyimini güçlendirir. Örneğin düşük cihazlarda gölge, post-processing ve render scale düşürülüp; orta-üst cihazlarda daha yüksek kalite açılabilir. Böylece performans hedefi geniş kitlede korunur.
Kontrol listesi çıkarıp standardı sürdürülebilir kılmak
Optimizasyon bir defalık bir iş değil; süreçtir. Ekip büyüdükçe, yeni içerikler geldikçe bellek ve performans tekrar bozulabilir. Bu yüzden küçük bir kontrol listesi ve “kabul kriteri” belirlemek, kaliteyi sürekli korur.
Ölçüm kriterlerini netleştirip raporlamak
Aşağıdaki gibi somut kriterler belirlemek karar vermeyi kolaylaştırır:
- Hedef cihazda ortalama kare süresi (ms) ve en kötü %1 değerleri
- Uzun koşuda bellek trendi: 5–10 dakikada stabil kalmak
- GC allocation: kritik akışlarda sıfıra yakın tutmak
- Yükleme ekranı süreleri ve sahne geçişlerinde spike olmamak
Bu kriterler, hem teknik ekibin hem de karar vericilerin aynı tabloya bakmasını sağlar. Böylece “hissediyorum” yerine “ölçtüm” diyerek ilerlersiniz.






