Valve’ın efsanevi oyunu Half-Life 2, piyasaya sürüldüğünde çığır açan fizik motoruyla tanınıyordu. Ancak fizik tabanlı oyunların en büyük düşmanı, en kusursuz teknolojide bile gizlenen beklenmedik hatalardır. Eski Valve geliştiricisi Tom Forsyth, Mastodon üzerindeki bir paylaşım dizisinde (thread) bu gerçeği kanıtlayan, akıllara zarar bir hatayı anlattı
VR sürümünde kilitlenme: Kimse anlamadı
Hikaye, 2013 yılına, Valve’ın Half-Life 2’nin VR sürümü üzerinde çalıştığı döneme dayanıyor. Forsyth ve ekibi, oyunun VR’a kolay adapte olduğunu düşünüyordu (Örneğin, Portal’daki perspektif hileleri VR’da anında mide bulantısı yaratmıştı, HL2 daha güvenliydi).
Ancak oyunun açılış sahnesinde, bir Metro polisinin (NPC) kapıyı açıp oyuncuyu içeri alması gereken yerde oyun kilitleniyordu. Kapı açılmıyor, gerekli hikaye tetiklenmiyor ve oyuncu öylece kalıyordu. Ne Forsyth ne de orijinal HL2’de çalışmış diğer tecrübeli mühendisler nedenini anlayamadı, zira ilgili kodlarda hiçbir değişiklik yapılmamıştı.
Tek bir parmağın inanılmaz gücü
Uzun süren araştırmalar sonucunda ekip, hatanın kaynağını buldu: Kapının arkasında duran bir NPC, kapı yolunun dış kenarıyla milimetrik bir şekilde kesişiyordu.
İşte olanlar:
- Kapı açılmaya başlıyor.
- Kapı, polisin ayağının “sınırlayıcı kutusuna” (bounding box) hafifçe çarpıyor.
- Oyun, kapının bir nesnenin içinden geçmesine izin vermediği için, kapı geri sekerek otomatik olarak kilitleniyor.
- Oyun donuyor.
Hatanın kökü zaman yolculuğu yapan kod
Basitçe NPC’yi yerinden oynatarak hata giderildi, ancak Forsyth ve ekip, bu hatanın neden sadece yeni VR sürümünde ortaya çıktığını anlamak için daha derin kazı yapmak zorundaydı. Daha da tuhafı, sorunun sadece VR sürümünde değil, orijinal HL2 kodunun yeni bir derleyiciyle (compiler) tekrar derlenmiş halinde de bulunduğunu fark ettiler; yani hata “zamanda yolculuk etmişti”.
Nihai Cevap: Kayan Nokta Hassasiyeti (Floating Point Precision)
Hatanın asıl nedeni, oyun motorunun fizik hesaplamasında kullandığı “Kayan Nokta” hassasiyetindeki minicik farktı.
- Eski Kod (x87): O dönemin işlemcileri için varsayılan olan eski x87 komut setini kullanıyordu. Bu hesaplama, kapı çarptığında NPC’yi kapı yolundan tamamen çıkacak kadar döndürüyordu.
- Yeni Kod (SSE): 2013’te kullanılan modern SSE komut setini kullanıyordu. Bu set, hesaplamaları mikroskobik olarak farklı yaptığı için, kapı çarptığında NPC’yi sadece biraz daha az döndürüyordu.
Sonuç: Yeni sürümde polisin ayağının parmak ucu hala kapının açılma yolunda kalıyordu ve çarpışma çözümlenemeyince kapı geri sekip kilitleniyordu. Bir oyunun akışını, kodun hesapladığı bir ondalık sayının küçücük bir farkı durdurabiliyordu. Bu olay, geliştiriciler için basit görünen hataların bile ne kadar karmaşık olabileceğinin mükemmel bir kanıtıdır.