Sonsuz bir koşucuda aslında ne hareket ediyor?


107

Örneğin, ünlü Flappy Bird oyunu ya da gerçekten sıralanan herhangi bir şey oyuncu (bu durumda kuş ya da kamera hangisini tercih ederseniz) ileri doğru ya da tüm dünya geriye doğru hareket ediyor (kuş sadece Y konumunu değiştirir ve sabit X konumu)?


1
Bu sorudan ve cevaplarından pek çok konu dışı yorumu sildik. Ayrıca, bazı durumlarda tekrar tekrar sohbet etmek için birkaç makul tartışmaya geçtik. Buna rağmen, birkaç kullanıcı yorumların uzun tartışmalar için olmadığı ve devam ettiği gerçeğini görmezden gelme gereğini duymuşlardır. Bu nedenle, bu soru geçici olarak kilitlendi.
Josh

Yanıtlar:


146

Philipp'in cevabına biraz katılıyorum ; ya da en azından nasıl sunduğuyla. Dünyayı oyuncunun etrafında hareket ettirmenin daha iyi bir fikir olabileceği izlenimini veriyor; tam tersi olduğunda. Yani burada kendi cevabım ...


Her iki seçenek de işe yarayabilir, ancak genel olarak dünyayı dünyadaki oyuncu yerine oyuncu etrafında dolaştırarak “fiziği tersine çevirmek” kötü bir fikirdir.


Performans kaybı / atık:

Dünyada genellikle çok fazla nesne olacak; çoğu değilse, statik veya uyur. Müzikçalar bir veya nispeten az sayıda nesneye sahip olacak. Tüm dünyayı oyuncunun etrafında dolaştırmak, oyuncu dışındaki sahnede yer alan her şeyi taşımak anlamına gelir. Statik nesneler, uyku dinamik nesneleri, aktif dinamik nesneler, ışık kaynakları, ses kaynakları vb .; hepsinin taşınması gerekiyor.

Bu (tabii ki), yalnızca gerçekte hareket eden şeyi (oyuncu ve belki birkaç şey) hareket ettirmekten oldukça daha pahalı.


Bakım ve Genişletilebilirlik:

Dünyayı oyuncu etrafında hareket ettirmek dünyayı (ve içindeki her şeyi) olayların en aktif olarak gerçekleştiği nokta haline getirir. Sistemdeki herhangi bir hata veya değişiklik, potansiyel olarak her şeyin değiştiği anlamına gelir. Bu işleri yapmak için iyi bir yol değil; Hataların / değişikliklerin mümkün olduğunca izole olmasını istersiniz, böylece değişiklik yapmadığınız bir yerde beklenmeyen davranışlar elde edemezsiniz.

Bu yaklaşımla ilgili başka birçok problem var. Örneğin, işlerin motor içinde nasıl çalışması gerektiği ile ilgili birçok varsayımı kırıyor. RigidBodyÖrneğin, oynatıcıdan başka hiçbir şey için dinamik kullanamazsınız ; RigidBodykinematik ayarlanmamış bir nesnenin pozisyon / dönüş / ölçek (oyuncu hariç, sahnedeki her nesne için her kareyi yapıyor olacaksınız) ayarlarken beklenmedik şekilde davranacağından


Yani cevap sadece oyuncuyu hareket ettirmek!

Şey ... evet ve hayır . Philipp'in cevabında da belirtildiği gibi, sonsuz koşucu bir tür oyunda (ya da büyük ve kesintisiz bir keşfedilebilir alana sahip herhangi bir oyunda), başlangıç ​​noktasından çok uzağa gitmek sonunda farkedilir FPPE'leri ( Kayan Nokta Hassas Hataları ) ve daha sonra hala sonuçta ortaya çıkar. Sayısal türün üzerine taşarsanız ya oyununuzun çökmesine neden olur ya da temel olarak oyun dünyasında duman kırılmasına neden olur ... Steroidlerle! 😵 (çünkü bu noktada FPPE'ler oyunu zaten “normal” çatlakta yapacaktır)


Gerçek çözüm:

İkisini de yapmayın! Dünyayı sabit tutmalı ve oynatıcıyı onun etrafında hareket ettirmelisin. Ancak , oyuncu sahnenin kökünden (konumundan ) uzaklaşmaya başladığında, hem oyuncu hem de dünyayı “yeniden köklendirin” . [0, 0, 0]

Şeylerin göreceli pozisyonunu koruyorsanız (çevresindeki dünyaya oyuncu) ve bu işlemi tek bir kare güncellemesinde yaparsanız, (gerçek) oyuncu fark etmez!

Bunu yapmak için iki ana seçeneğiniz vardır:

  1. Oynatıcıyı sahnenin köküne taşıyın ve dünya topluluğunu oynatıcıya göre yeni konumuna getirin.
  2. Dünyayı bir ızgara gibi düşünün; oyuncunun içinde bulunduğu ızgara kısmını kök üzerine getirin ve oynatıcıyı ızgaraya o kısmına göre yeni konumuna getirin.

İşte bu sürecin bir örneği


Ancak, ne kadar uzakta?

Unity'nin kaynak koduna bakarsanız, 1e-5( 0.00001) nesnelerin konumlarından, [euler-] döndürmelerden ve ölçeklerden sorumlu veri türlerinin "eşit", içinde Vector2ve içindeki iki eşit nokta değerini göz önüne almak için temel olarak kullanırlar Vector3. Kayan nokta hassasiyet kaybı her iki şekilde de sıfırdan uzakta gerçekleştiğinden, sahne kökünün / kaynağının uzağındaki 1e+5( 100000) birimlerin altındaki her şeyin birlikte çalışmanın güvenli olduğunu varsaymak güvenlidir.

Fakat! Dan beri...

  1. Bu yeniden köklenme işlemlerini otomatik olarak yapacak bir sistem yapmak daha uygun olur.
  2. Oyununuz ne olursa olsun, dünyanın 100.000 birim (metre [?]) Genişliğinde bitişik bir "bölümünün" olmasına gerek yoktur.

... o zaman muhtemelen 100000 ünite işaretinden çok daha erken / daha sık köklendirme yapmak iyi bir fikirdir. Sağladığım örnek video, örneğin her 1000 birimde bir yapıyor gibi görünüyor.


2
Yorumlar uzun tartışmalar için değildir; bu konuşma sohbete taşındı . Lütfen daha fazla yorum yazmak yerine bu sohbeti kullanın.
Alexandre Vaillancourt

> Bu (tabii ki) hareket etmekten çok daha pahalı, aslında sadece hareket eden şeyi mi? Oluştururken, kameranın kimliğine sabitlenmiş olması bu şekilde daha az pahalı olacaksa, yine de tüm nesnelerde kamera matrisi ile bir matris çarpımı yapmanız gerekecektir .
Matsemann

Oyun geliştirme birliğin gelişimi olduğu o an ...
LJ ᛃ

@Matsemann - Sohbete başlamış olsaydınız, bunun yeni bir nokta olmadığını fark etmişsinizdir. Daha önce açıklandığı gibi, NOT-EQUALS sahnesini yaratın; farklı ve neredeyse tamamen bağımsız konular ve boru hatları var. Nesnelerin konumlandırılmış şekilde bir referans çerçevesi tersine çevrilmesi, sadece renderden ziyade her iki uçta da daha ağır bir işlem yapacağınız anlamına gelir . --- Ayrıca, performans olsa dahi iddia eşit-işlem gören tüm diğer inversiyon ile ilgili sorunlar olurdu hala bu yaklaşımı yapma, çözülemeyen hala birini yeniden köklendirme daha kötü.
XenoRo

@ LJ question Soru özellikle birlik hakkında yapıldı (bkz. OP’nin D. Everhard’ın [IMHO’nın tahrif ettiği] düzenlemelerinden önceki etiketleri), ve böylece cevap bunu yansıtmak için tasarlandı . --- Ama işte en iyi bölüm: Birlik Olun, Unreal, CryEngine, Source, vb ... En iyi ve / veya en popüler motorlar bu şekilde çalışır (ve bir sebeple yaparlar), bu yüzden cevap sadece Genel olarak mükemmel geçerlidir , ancak yapılan noktalar hala doğruluk zirvesinde . Genel olarak konuşursak, fiziğin referans çerçevesini tersine çevirirseniz, özellikle dinamik nesnelerde problemlerle karşılaşmayı bekleyebilirsiniz.
XenoRo

89

Her iki seçenek de çalışır.

Ancak, sonsuz koşucunun gerçekten sonsuz olmasını istiyorsanız, oyuncuyu sabit tutmanız ve dünyayı hareket ettirmeniz gerekecektir. Aksi halde, X konumunu saklamak için kullandığınız değişkenlerin sınırlarına varacaksınız. Bir tam sayı sonunda taşar ve kayan nokta değişkeni giderek daha az doğru olur ve bu da oyunun bir süre sonra aksaklığına neden olur. Ancak, bu problemi, hiç kimsenin bir seansta düşünülebileceği bir zaman diliminde bu problemlerle kimsenin karşılamayacağı kadar büyük bir tip kullanarak (bir oyuncu saniyede 1000 piksel hareket ettiğinde, bir 32 bit tamsayı 49 gün sonra taşacaktır) kullanarak önleyebilirsiniz.

Öyleyse, kavramsal olarak size daha sezgisel olarak hissettiren her şeyi yapın.


Yorumlar uzun tartışmalar için değildir; bu konuşma sohbete taşındı .
Josh

1
Bunun bir şeyi çözdüğünü sanmıyorum. Oyuncunun (ve kameranın) konumunu korumak yerine, dünyanın kaydırma pozisyonunu korursunuz - bu nasıl farklı olabilir?
Ajan_L

1
@Agent_L Genel olarak, dünyalar parça parça üretilir ve her bir parçanın X / Y konumu vardır. Parça oyuncunun arkasından yeterince geride kaldığında (örneğin ekran dışı), silinir ve önceden yalnızca belirli bir miktar oluşturulur, bu nedenle her zaman nispeten küçük bir aralık içinde olurlar - yaptığım bir oyun asla daha büyük bir koordinat almadı sonsuz, rastgele oluşturulmuş bir koşucu olmasına rağmen ~ 1000 veya 0'dan küçük, çünkü - her oyuncunun pozisyonunu ve her bir grubun dizideki sırasını izledim.
Nic Hartley

"Değişken taşma" kavramını satın almıyorum. Eğer oyuncu hareket etmiyorsa, "arka plan", oyuncu hareket halindeyken ofsetle aynı miktarda negatif olarak dengelenir. Her iki durumda da aynı sorunla karşılaşacaksınız (ters yönlerde) ve her ikisi de taşma sınırlarında özel işlem gerektirecektir.
spender

2
saniyede 1000 piksel hızında, 64 bit bir tamsayı geçmesi 586 milyon yıldan fazla sürecek. Bu, yalnızca 16 bit tamsayı gibi küçük türler kullanıyorsanız, gerçekten bir sorundur.
Lyndon White

38

Off Bina XenoRo cevabı yerine onlar açıklamak yeniden köklenme yöntemin, bir aşağıdakileri yapabilirsiniz:

Sonsuz haritanızın oluşturduğu parçaların dairesel bir tamponunu oluşturun, karakteriniz modulo aritmetik ile güncellenmiş pozisyonda ilerler (böylece sadece dairesel tamponun etrafında koşarsınız). Karakteriniz parçadan çıkar çıkmaz tamponunuzun parçalarını değiştirmeye başlayın. Oyuncular güncelleme denklemi gibi bir şey olurdu:

player.position = (player.position + player.velocity) % worldBuffer.width;

İşte neden bahsettiğimin bir resimsel örneği:

görüntü tanımını buraya girin

İşte sonunda sarmalamada olanlara bir örnek.

görüntü tanımını buraya girin

Bu yöntemle, hiç bir zaman hassas hatalarla karşılaşmazsınız, ancak bunu çok uzak görüş mesafesiyle 3B olarak yapmayı düşünüyorsanız çok daha büyük bir arabellek yapmanız gerekebilir (çünkü yine de kendinizin önünde görmeniz gerekebilir) ). Flappy kuşu ise, yığın boyutunuz muhtemelen yalnızca tek bir ekran için tek bir sahne tutması gerektiği kadar büyük olacaktır ve tamponunuz çok küçük olabilir.

Birlikte sonuçlar tekrar elde etmek için başlangıç unutmayın BİR PRNG ve PRNG nesil olmayan tekrarlayan dizilerinin maksimum sayısı ile, (bitlerin sayısı dahili olarak kullanılan 2) POW uzunluğu tipik olarak daha az twister merzenne bu değil 2.5k dahili durum kullandığı için, bir problemin çoğunu kullanıyorsanız, ancak küçük varyantı kullanıyorsanız, tekrarlamadan önce en fazla 2 ^ 127-1 yineleme yaparsınız (veya daha kötüsü), bu yine de astronomik olarak büyük bir sayıdır . PRNG'niz tohum için iyi çığ karıştırma fonksiyonları ( kısa süreli eklediğiniz gibi) art arda çağı karıştırma fonksiyonları ile kısa bir süre olsa bile tekrar eden dönem sorunlarını çözebilirsiniz .


Yorumlar uzun tartışmalar için değildir; bu konuşma sohbete taşındı .
Josh

15

Daha önce sorulduğu ve kabul edildiği gibi, oyununuzun kapsamına ve tarzına bağlıdır, ancak bahsedilmediğinden beri: FlappyBird dünyadaki oyuncu yerine ekranın karşısındaki engeli hareket ettirir.

Bir yumurtacı, Vector2.leftyönünde sabit bir hızla nesnelerden ekranları başlatıyor .


3
Bu FlappyBird için çalışıyor çünkü çok basit bir oyundur. Cevabımda belirtildiği gibi, aynı teknik hala mümkün olsa da , Metro Surfer gibi daha karmaşık her şeyde (daha fazla dünya nesnesi / detayıyla) çok sorunlu olurdu .
XenoRo

15
Katılıyorum ve cevabınız çok ayrıntılı. Çırpma kuşunun gerçekte hangi yöntemi kullandığını söyleyen hiç kimseyi görmedim, bu yüzden ekleyeceğimi düşündüm.
Stephan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.