Roblox Fiziği: Daha İyi Bir Uyku Sistemi Oluşturmak

Fizik motorundaki "uyku" kavramından bahsedelim.
Uyku sisteminin amacı, hareket etmeyen cisimler üzerinde işlem yapmayı durdurmak ve hareket etmeye başladıklarında işlem yapmaya başlamaktır. Buradaki zorluk, bu durumlar arasında geçiş yapmak için en iyi sezgisel yöntemi seçmektir. Diğer motorlarda yaygın olarak kullanılan bir yaklaşım, cismin hızını izlemek ve hızın birkaç kare boyunca belirli bir eşiğin altında kalması durumunda cismi uyku moduna almaktır. Cisim, uyanık bir cisimle çarpışarak veya başka birkaç olayla tekrar uyanabilir. Yakın zamana kadar Roblox da bu yöntemin bir varyasyonunu kullanıyordu.
Bu yöntemle ilgili bilinen bazı sorunlar, bir cismin birkaç kare boyunca hızının sıfıra yakın olduğu, ancak mevcut yörüngesini tamamlamadığı fiziksel etkileşimlerdir. Bir topun kendi momentumuyla eğimli bir düzlemde yukarı doğru yuvarlandığı basit bir durumu düşünebiliriz. Sonunda topun kinetik enerjisi biter ve yörüngesinin tepesine ulaşır (eğimi yukarı iterek tüm enerjisini potansiyel enerjiye dönüştürmüş olur) ve eğimden aşağı yuvarlanır. Ancak yeterince yavaşsa, top tekrar aşağı yuvarlanmadan önce yörüngesinin zirvesinde eğimde uykuya dalar.
Bir geliştirici oyununda bu tür bir sınır durumla karşılaşırsa, motor genellikle bir geçici çözüm sunar. Tüm etkileşimlerde performanstan ödün vererek, bir nesnenin ne zaman uyku moduna geçeceği eşiklerini ayarlayabilirler. Ya da belki belirli bir nesne üzerinde uyku modunu tamamen devre dışı bırakabilirler. Belki de bir nesne üzerinde uyku durumunu yalnızca belirli bir süre için devre dışı bırakmak isterler. Her halükarda, karşılaşılan uyku kenar durumlarını tespit etmek ve çözüm bulmak geliştiricinin sorumluluğundadır. Roblox'ta, bu olumsuz durumları tamamen önleyerek geliştiricilerin iş yükünü azaltmanın bir yolunu bulmak istedik. Hedefimiz, geliştiricilerin endişelenmesine gerek kalmayacak bir uyku sistemi oluşturmaktır.
Roblox motorunda, katı cisimler "montajlar" olarak adlandırılır. Bu, bir veya daha fazla katı bir şekilde birbirine bağlı temel cisimden veya "parçadan" oluşan bir koleksiyondur, ancak uyanık veya uyku modunda olan nesne budur.

Montajlar, menteşeler veya halatlar gibi simüle edilmiş bağlantılar aracılığıyla diğer montajlara bağlanabilir ve bu da "mekanizma" olarak adlandırılan yapıyı oluşturur. Bu önemlidir çünkü montajlar, mekanizmalarındaki diğer montajların durumuna göre kendi uyku durumlarını tahmin edebilirler; bu konuyu daha sonra ele alacağız.
Diğer motorlar gibi, Roblox da cisimlerin ne zaman uykuya dalacağını belirlemek için geleneksel bir sezgisel yöntem kullanıyordu. Her montaj, geçmiş konum ve yönelimlerinin bir "geçmişini" tutar ve ortalama konumdan sapma eşik değerinin içinde kaldığı sürece montaj uyanık kalır. Esasen, hız birkaç kare boyunca belirlenen bir değerin altında kalırsa, montaj uykuya dalar. Bu değere hız eşiği diyeceğim.

Yukarıdaki örnek, daha önce anlatıldığı gibi topun bir rampada sıkışmasını göstermektedir. Burada, dönen bir parça silindiri tepeye doğru iter ve silindiri bir süre hareketsiz tutar. Silindirin hızı, uykuya dalmak için yeterince uzun bir süre boyunca hız eşiğinin altına düşer. Bu durum, düşük yerçekiminde zıplayan ve havada uykuya dalan bir top veya yerine devrilen ve yere değmeden uykuya dalan uzun bir blok gibi çeşitli örneklerle gösterilebilir.
Amacımız, bir montajın uyku durumuna geçip geçmeyeceğini belirlemek için son birkaç karedeki konum değişikliğinden daha iyi bir bilgi olup olmadığını görmekti. Neden hareketin en temel yasalarından birini takip etmiyoruz? “Bir nesne, üzerine bir kuvvet etki etmedikçe ya hareketsiz kalır ya da sabit bir hızla hareket etmeye devam eder.” Yerçekiminin silindire etki ettiğini ve silindirin yuvarlanmaya devam etmesi gerektiğini biliyoruz. Nesnenin sabit bir hızda hareket ederken veya üzerine dengesiz bir kuvvet etki ederken uyanık olmasını istiyoruz. Bu durumlardan herhangi biri geçerliyse, nesne uyanık kalmalıdır. Fizik çözücüsünden bir montajın son impuls değerlerini alabilir ve bunları ayrı bir impuls eşiğiyle karşılaştırabiliriz.

Aynı örneği tekrar ziyaret ettiğimizde, silindirin eğimden doğru bir şekilde yuvarlandığını görüyoruz. Şimdi, bir montajın dengesiz bir kuvvetin etkisi altındayken uykuya dalması imkansızdır. Bir montajın uykuya dalabilmesi için, hem hız eşiğinin hem de impuls eşiğinin altında olması gerekir.
Aynı mantığı montajların uyanması için kullanmaya çalıştığımızda, küçük bir sorunla karşılaşırız. Uyuyan bir montajın son impuls değerini kontrol edemeyiz, çünkü bir şeyin uykuda olmasının asıl amacı, çözücüde olmamasıdır. Bunun için hala temaslara ve özellik değişikliği olaylarına güvenmemiz gerekir. Ancak, mekanizma ilişkisi çeşitli durumlarda yardımcı olabilir. Aslında, bir montajın geçmişi, aynı mekanizmadaki diğer montajların ne zaman uyanması gerektiğini belirlemeye yardımcı olmak için de kullanılır.
Bir mekanizmada uyanık bir montaj varsa, o montajın tüm hemen komşuları (eğer onlar da uyanık değilse) "kontrol" durumuna geçirilir. "Kontrol" durumundaki montajlar hala uykudadır, ancak her karede uyanık montajın geçmişini kontrol ederler ve sapması başka bir daha büyük eşik değerinin üzerindeyse, "kontrol" durumundaki montajın da uyanması gerektiğine karar veririz. Buna komşu hız eşiği denir.

Bu montajlardan biri yoğun hareket halindeyse, diğer montajların da uyanık ve hareket halinde olması gerektiğini varsayıyoruz. Bu her zaman doğru olmadığı için, sonuçta gereğinden biraz daha agresif bir durum ortaya çıkıyor. Örneğin, iki montajdan oluşan bir yel değirmeniniz olduğunu varsayalım: dönen kanatlar ve taban. İdeal olarak, dönen kanatlar uyanık olmalı, taban ise hareket etmediği için uykuda kalmalıdır. Ancak, dönen kanatlar komşu hız eşiğinin üzerinde bir hızda hareket ettiği sürece, taban yanlış bir şekilde uyanık kalacaktır.
Bu ideal davranış, diğer tür mekanizmalarda sorunlara neden olabilir. Uyanık kalacak kadar hızlı, ancak komşularını uyku kontrol durumunda tutacak kadar yavaş hareket eden bir montajınız olabilir. Uyanık olan montaj, uyuyan komşusunun da hareket etmesini gerektirecek bir noktaya gelirse, ikisi de takılır ve sonunda uykuya dalar.
İşte bu durumun bir gösterimi. Sıfır yerçekiminde bir ip ile birbirine bağlı iki blok var. Büyük blok uyanık ve hareket halindeyken, sabit kalan kısım "uyku kontrol" durumundadır. Büyük blok, ipin gerilmesine yetecek kadar uzağa hareket edene kadar bu durum doğrudur.

Uyku kontrol düzeneğinin ipin gerildiğini bilmesinin bir yolu yoktur; ona göre komşusu, güvenli bir şekilde uykuda kalabilecek kadar yavaş hareket etmektedir. Hareket eden blok ipi çeker ancak artık hareket edemez, bu yüzden durur ve uykuya dalar.
Tahmin edebileceğiniz gibi, yeni bir komşu dürtü eşiği, uyuyan komşuları da uyandırmak için kullanılabilir. Bu ip örneğinde, ip gerilir gerilmez bloğun net kuvvetinde büyük bir değişiklik olduğunu biliyoruz. Bu kuvvet değişikliğini, "kontrol" düzeneğini uyandırmak için bir olay olarak kullanırız. Örnekte, ip gerilir gerilmez uyuyan parçanın uyandığını görüyoruz. Tüm bunlar, uyuyan parçanın kendisi üzerinde ek hesaplamalar yapılmasına gerek kalmadan gerçekleşir.

Bu, uyuyan derlemeleri uyandırmak için kullanılabileceği gibi, onları daha uzun süre uyutmak için de kullanılabilir. Artık, uyanık komşusu oldukça hızlı hareket ediyor diye bir derlemenin uyanması gerektiğini varsaymamıza gerek yok.
Sonuç olarak, sadece birkaç küçük değişiklikle motorun uyku sistemini büyük ölçüde iyileştirdik. Dikkatle ayarlanmış hız eşikleri kullanmak yerine, Newton'un Birinci Yasası doğrudan uygulanır. Artık kuvvetlere bakıyoruz ve cisimler gerçekten hareketsiz olduklarında onları uyku moduna alıyoruz. Tonlarca sınır durumu artık motor tarafından doğru bir şekilde ele alınmakta ve geliştiricilerin bunları bağımsız olarak bulup düzeltme ihtiyacını ortadan kaldırmaktadır. Bazen fizik sorunlarına fizik temellerine geri dönerek yaklaşmak, sonunda işe yarayabilir.
Ne Roblox Corporation ne de bu blog, herhangi bir şirketi veya hizmeti onaylamakta veya desteklemektedir. Ayrıca, bu blogda yer alan bilgilerin doğruluğu, güvenilirliği veya eksiksizliği konusunda hiçbir garanti veya taahhüt verilmemektedir.
Bu blog yazısı ilk olarak Roblox Tech Blog'da yayınlanmıştır.


