Tarayıcıda açık dünya geliştirmek, bölüm 17: Yeniden hedefleme gerektirmeyen animasyonlar ve canlı varlık araması
Cinevva CTO'su ve Kurucu Ortağı Oleg Sidorkin tarafından
Burada yeni misiniz? Seri rehberini kullanın. Rehber, spike'ın ne olduğunu açıklıyor ve tüm bölümlere bağlantı veriyor.
Bölüm 16, içine nesneler yerleştirebildiğiniz bir dünya sundu. Bu bölümse oyuncuya o dünyada yapabileceği daha iyi şeyler veriyor: savaş kalitesinde bir animasyon seti ve arama yazarak binlerce CC0 modelden herhangi birini dünyaya aktarmanın bir yolu.
262 klip, tek iskelet, üç yeniden hedefleme düzeltmesi
Spike 35'i yeni sekmede aç ↗ · Kaynak kodunu görüntüle
Oyuncu iskeleti, 80'den fazla kemikten oluşan bir yüz iskeleti ve eksiksiz parmak eklemleri dâhil toplam 213 kemiğe sahip, CC4 tarzı bir 3MIKE iskeleti. Animasyon kaynakları bununla eşleşmiyor. İlk sürümde elle seçilmiş Mixamo savaş klipleri yeniden hedeflendi, ancak kaynak havuzu yetersizdi ve hareket animasyonları Mixamo ile birkaç Kimodo BVH bekleme animasyonu arasında kullanışsız biçimde bölünmüştü. Asıl kazanım, kaynak kütüphanesini Quaternius'un iki Universal Animation Library paketine geçirdiğimizde geldi: tek ve tutarlı, UE5 tarzı 65 kemikli bir manken üzerinde toplam 262 klip; kılıç komboları, okçuluk, tırmanma, duvarda koşma, sıyrılmalar, darbe tepkileri, ifadeler ve çok daha temiz bir hareket seti.
Bu, ortak kemik adları, T-pozu yönelimleri veya uzuv oranları bulunmayan 65 kemikli bir kaynaktan 213 kemikli bir hedefe aktarım demek. Her klip üç adımda yeniden eşleniyor: bir kemik adı eşlemesi, iki iskeletin ortak bir referans yönelimini paylaşmasını sağlayan bağlama pozu hizalaması ve daha kısa kaynak iskeletin karakteri dizlerine kadar zemine gömmemesi için konum izi ölçeklendirmesi. Bunu doğru yapmak, her biri bize belirli bir şey öğreten bir dizi hatanın peşine düşmek anlamına geldi.
Karakter aşırı burulmuş görünüyordu; her omuz ve dirsek yaklaşık 30° fazla dönüyordu. Bunun nedeni bir poz uyuşmazlığıydı: UAL kaynağı gerçek bir T-pozuyla geliyor, CC4'ün bağlama pozuysa A-pozu ve yeniden hedefleyici iki iskeletin de eşleşen referans pozlarında durduğunu varsayıyordu. Bu nedenle A'dan T'ye olan fark, kare başına her deltaya ekleniyordu. Düzeltme, bağlama pozunu yakalamak için CC4'ün kol zincirini gerçek bir T-pozuna zorluyor, ardından yeniden hedefleme yapıyor; böylece deltalar küçük kalıyor.
Ardından gövde ötelemesi durdu. Geri savrulmalarda üst gövde tepki veriyor, ancak ayaklar yere sabit kalıyordu. UAL, yer değiştirmeyi pelvis yerine root kemiğine koyuyor; bu nedenle pelvis konumunu okumak sıfıra yakın hareket veriyordu. Düzeltme, root.position ile pelvis.position değerlerini topluyor, yatay kısmı ölçeklendiriyor ve tek bir kalça konumu izi yazıyor. Bunu yaparken dikey ofsetlerin yaklaşık %12 hatalı olduğunu keşfettik; çünkü pelvis yüksekliği için kalçadan zemine oran gerekirken Y ekseninde genel uzuv oranını kullanmıştık. İki oran, iki eksen: Y için RL_BoneRoot.position NaN uyarıları akışının nedeni, UAL'ın root kemiğinin (
En küçük düzeltme, izlemesi en tatmin edici olandı. Kemik eşlemesinde parmak girdileri bulunmadığı ve yeniden hedefleyici yalnızca eşlenmiş kemikler için iz yazdığı için karakter kılıcı gevşek, bağlama pozundaki parmaklarla tutuyordu. 30 parmak kemiği eklemek (beş parmak, üç segment, iki el; UAL'ın deformasyon yapmayan dördüncü uç yardımcı kemiğini hariç tutarak) elin kabzayı kavrarken kapanmasını ve bırakırken açılmasını sağladı.
262 klibi, 262 klibi izlemeden doğrulamak
262 kliplik bir kütüphaneyi gözle doğrulayamazsınız; bu nedenle çevrimdışı bir yörünge eşlik testi geliştirdik: Her paketi yükleyen, kaynak iskeleti 60 Hz'de örnekleyen, yeniden hedefleme işlem hattını çalıştıran ve ölçeklendirmeden sonra kemik başına dünya konumlarıyla dönüşlerini kaynakla karşılaştıran başsız bir Node betiği. Pelvisin Y eksenindeki maksimum sapması 0,003 m oldu. Ellerde başlangıçta “parmaklar takip etmiyor” şeklinde yorumlanan sabit 2,5°'lik bir ofset vardı; ancak sabit ofset, düz UAL eli ile CC4'ün hafifçe çukurlaştırılmış bağlama pozu arasındaki bağlama deltasıdır ve klip boyunca değişmez. Gerçek animasyon hataları, kareden kareye değişen sapmalar olarak ortaya çıkar. Bu netleştiğinde test, tek seferlik bir regresyon kontrolüne dönüştü: Bir klibin sapması bu sabit taban çizgisini korumayı bırakırsa yakın tarihli bir değişiklik yeniden hedeflemeyi bozmuş demektir.
Yan yana gösterilen bir referans manken, hata ayıklamanın görsel tarafını belirleyici hâle getirdi. Ters eğik çizgi tuşuna basıldığında geçerli klibin sahibi olan kaynak iskelet oyuncunun yanında gösteriliyor; böylece “omuz neden burulmuş?” sorusu “burulma kaynakta mı, yoksa yeniden hedefleme mi ekledi?” sorusuna dönüşüyor. Sayısal testler regresyonları yakalıyor, görsel referans sayıların ortaya çıkarmadığı bağlama pozu hatalarını buluyor ve ikisi birlikte tahmin oyununa son veriyor.
İşlem hattı sağlamlaştıktan sonra WASD/zıplama/yüzme temelini Mixamo'dan UAL'a geçirmek yalnızca ince bir takma ad eşlemesi gerektirdi: FSM hâlâ idle ve walk gibi genel durum adlarını kullanıyor ve bunlar oynatma sırasında UAL klip adlarına çözümleniyor. Serbest stil ve su üstünde durma pozları pelvisi farklı anatomik yüksekliklere sabitlediği için yüzmede klip başına iskelet ofsetleri gerekti. Bu nedenle aktif yüzme sırasında iskeleti yarım metre, su üstünde dururken daha derine batırıyor ve aralarında yumuşak bir 5 Hz geçiş yapıyoruz.
Bir kelime yazın, bir model alın
Spike 36'yı yeni sekmede aç ↗ · Kaynak kodunu görüntüle
Spike 34, elle seçilmiş bir CC0 paketi hazırlamak için bir gün harcadı. Uzun vadeli çözüm bir arama kutusu. Polyhaven, izin verici bir JSON API'si ve deterministik bir CDN üzerinden yaklaşık 1.100 CC0 model yayımlıyor. Bu spike, sorgu, küçük resimler, yükleme ve görüntülemeden oluşan tüm yolu; derleme adımı bulunmayan statik bir sayfada, yaklaşık 300 satır sade JS ve three.js ile bağlıyor.
Başlangıçta yaklaşık 600 KB büyüklüğündeki kataloğun tamamı bir kez getiriliyor. Arama, 120 ms gecikmeli, tamamen istemci taraflı puanlama kullanıyor (ad, kimlikten; kimlik, kategoriden; kategori de etiketten üstün) ve en yüksek puanlı 60 kartı oluşturuyor. Küçük resimler bir IntersectionObserver üzerinden tembel yükleniyor; böylece yazı yazmak aynı anda 60 istek başlatmıyor. İlginç kısım yükleme. Polyhaven'ın dosya uç noktası GLB değil, çok dosyalı glTF sunuyor; dokular çözünürlükler arasında paylaşılıyor ve ayrı dosyalara bölünüyor. Ayrıca göreli yollardan mutlak CDN URL'lerine uzanan bir include eşlemesi döndürüyor. JSON'u kendimiz indirip yamamak yerine bu eşlemeyi LoadingManager.setURLModifier üzerinden geçiriyoruz. Bu, yükleyicinin ihtiyaç duyduğu her bağımlılık (.bin ve her doku) için çalışıyor ve bunları CDN üzerinden çözümlüyor. Tek tıklama, görünürde tek dosya. Hem API hem de CDN izin verici CORS başlıkları sunuyor; bu durum herhangi bir istemci kodu yazılmadan önce curl ile doğrulandı, dolayısıyla proxy gerekmiyor. PBR malzemeleri, RoomEnvironment ve varsayılan ACES ton eşleme ayarlarıyla varlık başına düzeltme gerektirmeden doğru görüntüleniyor. 1k dokular da tipik bir modeli 4k'daki 20 ila 40 MB yerine 2 ila 5 MB arasında tutuyor.
Bir meshoptimizer WASM geçişi, sistemi tahribatsız bir azaltıcıyla tamamlıyor: Her mesh, özgün geometrisinin bir kopyasını saklıyor ve oran değiştiğinde kümülatif olarak sadeleştirmek yerine bu kopyadan yeni bir indeks arabelleği oluşturuyor. Çok malzemeli geometri, grup başına sadeleştiriliyor ve malzeme yuvalarının birleşmemesi için geometry.groups yeniden oluşturuluyor. Bir koltuk, tam ayrıntıda 5.626 üçgenden yarı ayrıntıda 2.812 üçgene düşüyor.
Bu bölümde değinilen teknolojiler
Bağlama pozu hizalamasıyla iskelet yeniden hedefleme. Animasyonu farklı kemik adlarına, oranlara ve referans pozlarına sahip bir iskeletten diğerine eşlemek üç düzeltme gerektirir: bir kemik adı eşlemesi, iki iskeletin ortak bir referans yönelimini paylaşmasını sağlayan bağlama pozu hizalaması (hedefin A-pozu kol zincirini kaynağın T-pozuna zorlayarak) ve konum izi ölçeklendirmesi. Poz uyuşmazlığı, A'dan T'ye dönüşü kare başına her deltaya ekleyerek eklem dönüşünü ikiye katlar. Eşlenmemiş yardımcı kemikler çıkarılmalıdır; çünkü
Tek iskelet için iki ölçek oranı. Yatay yer değiştirme genel uzuv oranını, yani iskeletin genel boyutunu kullanır; ancak dikey pelvis ofseti, iskeletlerin bacak-gövde oranları farklı olduğu için kalçadan zemine root kemiğinde bulunduğundan, geri savrulma, tırmanma ve hareket kliplerinde hareketi korumak için ikisi de tek bir kalça konumu izinde toplanmalıdır.
Çevrimdışı yörünge eşlik testi. Başsız bir betik kaynak iskeleti 60 Hz'de örnekler, yeniden hedefleme işlem hattını çalıştırır ve kemik başına dünya dönüşümlerini kaynakla karşılaştırır. Kare başına sabit bir ofset zararsız bağlama deltasıyken, kareden kareye değişen sapma gerçek bir hatadır. Böylece test, bir değişiklik bir izi kaldırdığında veya bozduğunda tetiklenen bir regresyon kontrolüne dönüşür. Paket başına GLB yalıtımı (her seferinde yeni yükleme ve bir sonrakinden önce serbest bırakma), taramanın tamamında önbellek çekişmesini önler.
CDN glTF grafikleri için LoadingManager.setURLModifier. Bir CDN, glTF'yi beraberindeki bir include eşlemesiyle (göreli yoldan mutlak URL'ye) göreli URI grafiği olarak sunduğunda setURLModifier, JSON'u yeniden yazmadan yükleyicinin istediği her bağımlılığı CDN üzerinden çözümler. Bu, çok dosyalı ve çok çözünürlüklü bir dağıtımı tek tıklamayla yüklenebilir hâle getirir. Bir sonraki model yüklenmeden önce önceki modelin geometrisini, malzemelerini ve doku haritalarını serbest bırakmak, gezinme oturumu boyunca yüzlerce MB GPU belleğinin birikmesini önler.
Tahribatsız mesh sadeleştirme. Her mesh'in özgün geometrisinin bir kopyasını saklamak ve her sadeleştirme oranında yalnızca indeks arabelleğini yeniden oluşturmak, değişiklikleri hızlı tutar ve tekrarlanan sadeleştirmenin yol açtığı kümülatif hasarı önler. İşlemi her geometry.groups dilimi için ayrı yürütmek ve grupları yeniden oluşturmak, çoklu malzeme atamalarını korur. Bunun mesafeye dayalı LOD'a nasıl aktarıldığını görmek için LOD ve meshoptimizer bölümüne bakın.
29 bölümün 17.'si. Önceki: Bölüm 16 - Büyümeye devam eden bir dünya için yapı Sonraki: Bölüm 18 - Yapay zekâ yerleştirmiş hissi veren bir dağıtma fırçası Seri rehberi: /tr/blog/2026-02-25-open-world-browser-series-guide