1 puan yazan GN⁺ 2023-09-18 | 1 yorum | WhatsApp'ta paylaş
  • ‘Caves of Qud’, uzun süredir devam eden Unity bağımlılığını ortadan kaldırmak için oyun çekirdeğini Godot üzerinde derleyip başlatmaya yönelik bir teknik doğrulama yürüttü; ilk hedef, modern VFX veya UI olmadan ASCII+tile modunda çalıştırmak
  • Çalışma; tile varlıklarını içe aktarma, temel C# assembly’lerini taşıma ve render/input düzenini kurma olarak üçe ayrıldı; eski BMP tile dosyaları PNG’ye dönüştürülerek Godot’ya yüklendi
  • İlk derlemedeki 5.641 hata; GeneratedCode, ConsoleLib, Genkit, Language, HistoryKit, Newtonsoft JSON, CodeDom vb. taşınarak azaltıldı ve UnityEngine bağımlılık yüzeyi stub’larla daraltıldı
  • Unity’nin Color, GameObject, AudioSource, Debug.Log, Screen kullanım noktaları UnityEngineReplacer ve alternatif sınıflarla ele alındı; PlayFab ve Unity UI’a yakın chargen/presentation katmanları geçici olarak kaldırıldı veya glue modüllerine ayrılacak adaylar olarak bırakıldı
  • Sonuçta yaklaşık 500 bin satırlık C# oyun çekirdeği Godot’ta başlatılıp frame üretecek ve input bekleyecek aşamaya geldi; ancak renderer/input harness’i ile VFX, ses ve UI bağlama işleri hâlâ duruyor

Unity’den Godot’ya taşıma çalışmasının kapsamı

  • Taşıma çalışması üç kola ayrılıyor
    • Varlıkları içe aktarma: tile varlıklarını Godot projesine koyma işi
    • Temel assembly’leri taşıma: Unity olmayan ana oyun motoru XRL Application ile motor tarafındaki GameManagerı taşıma işi
    • Render düzenini kurma: çekirdek başlatıldıktan sonra ekran çıktısını ve input’u bağlama işi
  • Godot “mobile” projesi oluşturuldu ve Qud’un texture içeriği proje kök klasörüne kopyalandı
  • Godot eski .bmp dosyalarını işleyemediği için ASCII tile’ları da içeren dosyalar topluca PNG’ye dönüştürüldü
  • Dönüştürmeden sonra varlıklar yüklendi, ancak içe aktarma ilerleme göstergesinin belirmesi yaklaşık 30 saniye sürdü

Derleme hatalarını azaltarak çekirdek assembly’yi taşıma

  • XRL Application kopyalandıktan sonra Godot’ta C# projesi ve solution oluşturuldu; ilk durumda 5.641 hata ortaya çıktı
  • ConsoleLib ve Genkit gibi genel amaçlı kütüphaneler olduğu gibi taşındı; eski sprite/atlaslama çözümü Kobold ise dosya bazında gerekli olup olmadığı kontrol edilerek içe aktarılacak şekilde ele alındı
  • KoboldJSON, basit bir JSON serileştirme kütüphanesi olduğu için olduğu gibi taşındı
  • Color kullanılan 85 nokta genel değiştirme ile ele alınınca hata sayısı 4.700’e düştü
  • Eksik olan GeneratedCode klasörü eklenince olay bazlı sınıf kodu üretim çıktıları dahil oldu ve hata sayısı 1.557’ye kadar azaldı
    • Caves of Qud, boilerplate’i fazla olan olay bazlı sınıfları kod üreterek oluşturuyor; böylece performans ve güçlü tipli bir event yüzeyi elde eden bir yapıya sahip

Unity bağımlılığı ve glue katmanını düzenleme

  • Embark Builder ve karakter oluşturma chargen’inde çok fazla Unity UI kodu olduğu için ilk ASCII teknik doğrulamasında kaldırıldı
    • Console sürümü henüz yok, ancak ilk doğrulama kayıtlı oyun yükleme veya rastgele başlangıç ile test edilebiliyor
  • Game klasörü çoğunlukla Unity ile oyun arasındaki glue olsa da CodeGeneration gibi glue olmayan klasörler de bulunduğundan, bunları ayrı bir root’a veya Platform klasörüne taşıma yönü seçildi
  • Language ve HistoryKit kütüphaneleri taşınınca hata sayısı 454’e kadar düştü; kusursuz olmasa da game/glue ayrımının yapılmış olması yardımcı oldu
  • Geriye kalan büyük hata kategorileri CodeDom/Roslyn, PlayFab, Harmony, bazı derleyiciyle ilgili sorunlar ve oyun katmanına sızmış UnityEngine yüzeyi idi
  • PlayFab ile ilgili kod geçici olarak yorum satırına alındı ve glue modülüne çıkarılacak aday olarak bırakıldı

Unity API yedek stub’ları ve Godot C# farkları

  • Color32, byte tabanlı bir renk tipi olduğu için hızlıca alternatif bir implementasyon yazıldı
  • UnityEngineReplacer klasörü oluşturuldu; Unity dokümanlarına veya kod referanslarına bakmadan, derleme hatalarına göre yalnızca gerekli yüzey uygulandı
  • GameObject stub’ı oluşturulunca “GameObject bilinmiyor” hataları, gerçekten gerekli alan ve metot hatalarına dönüştü; böylece oyunun kullandığı interface yüzeyi anlaşılabildi
  • AudioSource için de hata listesine bakılarak erişilen member’lar tek tek eklendi ve oyunun gerçekten kullandığı tüm AudioSource port interface’i tamamlandı
  • Bunun dışında ele alınan yüzeyler şunlardı
    • Debug.Log yerine geçen shim
    • Screen alternatif implementasyonu
    • IsNullOrEmpty extension method kütüphanesinin taşınması
    • Math referansları ve PI/Pi farkının ele alınması
    • Godot’nun X, Y büyük harfli koordinat adları farkının ele alınması
    • System.Drawing.Color, System.Numerics.Vector3 öğelerinin IDE tarafından yanlış import edilmesi sorunlarının temizlenmesi
  • Newtonsoft JSON, Visual Studio’da NuGet paketi eklenerek çözüldü; CodeDom da CodeDom NuGet paketiyle çözüldü

Godot’ta tam başlatmaya kadar

  • Hata sayısı 11’e düştüğünde kalan sorun, mod management’ın dinamik C# derlemesiyle ilgili koduydu; zorunlu değildi ama karmaşık olduğu için sona kaldı
  • Ardından link aşaması ve stub field hataları ele alınarak yaklaşık 500 bin satırlık C# kod derlendi
  • Sonraki adım, küçük bir renderer ve input harness’i yaparak çekirdek assembly’yi başlatmaktı; hedef, oyunu ASCII+tile modunda çalıştırılabilir hâle getirmekti
  • Godot’ta boş bir scene oluşturulup temel node’a GameManager.cs eklendi; GameManager, Nodedan miras aldı ve partial kod gerektirdi
  • Godot’nun _Ready metodu Unity’nin Awakeine, _Process metodu ise Unity’nin Updateine karşılık gelecek şekilde kullanıldı
  • Başlatma sürecinde load path ve mod management taşındı; type resolver’ın tipe adla ulaşamama sorunu printf yöntemiyle izlendi
  • Neden dynamic assembly işleme biçimiydi
    • mod assembly dynamic olduğu için main assembly kontrolünde dynamic assembly’ler hariç tutuluyordu
    • Godot editor’da main game assembly de dynamic olduğundan tip arama hedeflerinin dışında kalıyordu
  • Düzeltmeden sonra tam başlatma başarılı oldu ve 500kloc oyun çekirdeği frame üretip input bekler hâle geldi
  • Kalan işler “just work” diye ifade edilse de gerçekte VFX, ses ve UI bağlama tarafında ciddi miktarda iş duruyor

1 yorum

 
GN⁺ 2023-09-18
Hacker News yorumları
  • Bu oyun neredeyse tamamen kendi motorunu kullanıyor gibi; Unity ise yalnızca donanım soyutlama katmanı ve portlama için bir iskelet olarak kullanılıyor. Bu yüzden portlama zorluğu açısından en iyi senaryolardan birine yakın görünüyor
    Bu tür oyunlar şaşırtıcı derecede çok, ama elbette çoğu Unity yapımını temsil etmiyor

    • Doğru. Bir röportajda Qud’un o dönemde Unity içinde bir konsol uygulaması gibi çalıştığı söylenmişti
      Arayüz yenilemesinden sonra hâlâ böyle mi bilmiyorum; öyleyse MonoGame’e portlayıp maliyetten tasarruf etmemiş olmaları bana hep garip gelmişti
    • Bunun, Unity’nin varsayılan bileşenlerinin uzun vadede neredeyse tamamının işe yaramaz hale gelmesiyle sonuçlandığını düşünüyorum
      Android de benzer; işletim sistemi kamera algılama ya da şifreleme gibi şeylerin yerini alan kütüphaneleri yüklemek için kullanılmaya başlanıyor, sonra bir gün işletim sisteminin aslında ince bir metal katman ve bootloader’dan ibaret olduğu fark ediliyor
  • https://nitter.net/unormal/status/1703163364229161236

  • Vay, gerçekten harika. Bu portlama sürecini adım adım görebilmek de güzel; harcanan sürenin de oldukça makul olmasına şaşırdım

    • Godot’nun özellikleri çok daha az, ama öğrenmesinin gerçekten kolay olduğunu düşünüyorum
    • Caves of Qud’a özgü görsel atmosferin Godot’da nasıl uygulandığını görmek isterim
  • Özel kod bu kadar fazlaysa ve editör özelliklerini daha az kullanan bir yapı varsa, motor yerine bir rendering kütüphanesi de kullanılabilir gibi

    • Oyunu aynı anda birden fazla platforma çıkarmak istiyorsanız, platforma özel rendering, ses ve giriş kodlarıyla doğrudan uğraşmak kısa sürede bıktırır
      Altta bir motor olunca bunları bedavaya elde edersiniz. Unity ise buna ücret ekleyebilir
    • Zaten bir rendering kütüphanesi kullanıyorlar. Adı “Unity”
  • Brian’ın ne düşündüğünü merak ediyorsanız şu videoya bakabilirsiniz: https://www.youtube.com/watch?v=U03XXzcThGU
    Eskiden buradan çok şey öğrenmiştim

  • DHH’nin son TypeScript tartışması aklıma geldi
    Statik tipler olmadan böyle bir portlama yaptığınızı hayal edin: Her değişiklikte derleyip çalıştırmanız ve çökmeleri bulmanız gerekir. Böyle zamanlarda refactoring’i kolay bir dille ve iyi bir mimariyle hazırlanmış olmak gerçekten kıymetli geliyor

  • Twitter hesabım yok; ne oluyor?