Colorhive 3D altıgen bulmaca tahtası ve mobil taş dizme mekanikleri

Colorhive: Unity'de 60fps 3D Altıgen Yığınlama ve Sıfır-GC Zincirleme

Mobil ve Oyun Vitrinleri Mobil Oyun Mühendisliği, Unity 3D ve Grafik

Android için geliştirdiğimiz 3D altıgen bulmaca oyunu Colorhive mimarisi: eksenel koordinat matematiği, sıfır bellek tahsisi ve 60fps kare bütçesi.

  • Erol Tuna Yazar: Erol Tuna
  • 2 dk okuma
  • Güncelleme
Önemli çıkarımlar
  • Zincirleme birleşmeler sırasında çalışma zamanı Instantiate/Destroy çağrılarını 256 taşlık önceden ısıtılmış dairesel havuz (ring-buffer pool) ile değiştirerek GC sıçramalarını 0.0 ms seviyesine indirdik.
  • Hızlı başparmak sürüklemelerinde yanlış hücreye bırakmayı önlemek için küp-eksenel koordinat matematiğini (q, r) %14 manyetik yakalama bölgesiyle birleştirdik.
  • Özel matcap gölgelendirici ve köşe rengi (vertex-color) paleti kullanarak 140+ ayrı çizim çağrısını tek bir GPU-instanced batch içinde topladık.
  • Her seviyenin adil ve çözülebilir olmasını garanti eden geriye doğru açılımlı (backwards-unrolling) deterministik seviye üreteci geliştirdik.

Oyuncular Colorhive (Google Play’de yayında) gibi 3D altıgen bir sıralama bulmacasını indirdiklerinde, oyun hakkındaki kararlarını ilk altı saniye içinde verirler. Alt tepsideki üç renkli altıgen taş yığınına dokunurlar, ahşap petek tahtası üzerinde sürüklerler, başparmaklarını kaldırırlar ve eşleşen üst taşların komşudan komşuya zincirleme bir reaksiyonla sıçrayışını izlerler.

Bu zincirleme akış sabit 60 kare/saniye (kare başına 16.6 ms) hızında, net dokunsal (haptic) geri bildirimlerle ve sıcak bal rengi ışıklandırmayla aktığında oyuncu yirmi dakikalık bir odaklanma akışına girer. Dört yığın aynı anda birleşirken kare hızı 40 milisaniye bile teklerse veya oyuncunun başparmağı imleci kapattığı için yığın yanlış hücreye yapışırsa büyü anında bozulur.

Bu teknik incelemede Colorhive geliştirme sürecinde çözdüğümüz beş kritik mobil oyun mühendisliği problemini ve üretim kalıplarını paylaşıyoruz.

Colorhive 3D altıgen oyun tahtası, seviye ilerleme çubuğu ve renkli taş yığınları


1. 3D Altıgen Izgaralarda Işın Titremesi (Raycast Jitter) ve Başparmak Kapatması

Standart kare bir ızgarada ekran dokunuşunu (x, y) hücreye dönüştürmek basit bir tam sayı bölmesidir. Perspektif 3D kamera uzayında çizilen sivri uçlu altıgen (hexagonal) bir ızgara ise çok daha hassastır:

  1. Perspektif daralması: Tahtanın arka sıralarını sıkıştırırken ön tepsiyi genişletir.
  2. Başparmak kapatması: Oyuncu alt tepsiden yukarıya doğru taş sürüklerken başparmağı yığının alt %20’sini fiziksel olarak kapatır. Hedef hücre ham dokunma noktasından hesaplanırsa oyuncular taşları sürekli istediklerinden bir alt sıraya bırakır.
  3. Kenar sınırı titremesi: İmleç üç komşu altıgen hücrenin birleşim sınırına yaklaştığında standart fizik motoru (Physics.Raycast) parmağın her mikro titremesinde hücreler arasında gidip gelir ve önizleme gölgesinin titremesine yol açar.

Çözümümüz: Eksenel Koordinat Yuvarlama + Manyetik Histerezis

Altıgen hücrelere 61 ayrı MeshCollider eklemek yerine kamera ışınını tek bir matematiksel düzlemle (Plane.Raycast, sıfır fizik motoru yükü) kesiştiriyor ve dünya koordinatını (x, z) doğrudan kesirli eksenel altıgen koordinatlara (q, r) dönüştürüyoruz:

// Sıfır bellek tahsisli dünya düzlemi -> Eksenel Hex (q, r) dönüşümü ve manyetik histerezis
public HexCoord WorldToHexWithHysteresis(Vector3 worldPos, HexCoord currentLockedHex)
{
    float x = worldPos.x;
    float z = worldPos.z + ThumbClearanceOffsetZ;

    float qFrac = (Sqrt3 / 3f * x - 1f / 3f * z) / HexRadius;
    float rFrac = (2f / 3f * z) / HexRadius;

    HexCoord candidate = CubeRound(qFrac, -qFrac - rFrac, rFrac);

    if (candidate != currentLockedHex && currentLockedHex.IsValid)
    {
        Vector3 lockedCenter = HexToWorld(currentLockedHex);
        float distSq = (new Vector3(x, 0f, z) - lockedCenter).sqrMagnitude;
        if (distSq < MagneticRetentionRadiusSq)
            return currentLockedHex;
    }

    return candidate;
}

2. Sıfır-GC Zincirleme Animasyonlar ve GPU Instancing

Colorhive oyun içi çoklu renk birleşmesi ve tahta görünümü

Çoklu yığın birleşmelerinde çalışma zamanında hiçbir Instantiate veya Destroy çağrısı yapılmaz. Açılışta önceden ayrılan 256 taşlık halka bellek havuzu (ring-buffer pool) ve özel MaterialPropertyBlock tabanlı GPU instancing sayesinde 180 taş aynı anda hareket ederken bile 0 byte GC tahsisi ve tek draw batch ile sabit 60fps korunur.

Sıkça sorulanlar

Sıkça sorulan sorular

3D taş yığınlama oyunları orta segment Android telefonlarda zincirleme birleşmeler sırasında neden takılır?

Standart yaklaşımlar her birleşmede ana iş parçacığı üzerinde yeni efektler, ses kaynakları ve 3D objeler oluşturup eskilerini siler; bu da tam 60fps animasyonun ortasında Unity çöp toplayıcısını (GC) tetikler. Önceden ayrılmış dairesel bellek havuzları ve GPU instancing bu çalışma zamanı tahsislerini tamamen ortadan kaldırır.

Oyuncunun başparmağıyla sürüklerken taşı yanlış altıgen hücreye bırakmasını nasıl engelliyorsunuz?

İnsan başparmağı ekranın alt yarısında yaklaşık 45–60 piksellik alanı kapatır. Sürükleme başladığı anda yığına 38dp yukarı görsel ofset veriyor ve ışın izlemeyi (raycast) 80ms histerezisli ağırlıklı eksenel mesafe alanından geçirerek hedeflenen hücreye pürüzsüzce kilitliyoruz.

Colorhive'ı canlı olarak nereden indirebilirim?

Colorhive, Google Play Store üzerinde com.tunagamedev.colorhive paket adıyla yayındadır.