Bullet Physics / Ogre3D ile bir RPG'de bir karakteri nasıl hareket ettiririm?


9

son zamanlarda Ogre3D oyunumda karakterimi hareket ettirmede sorun yaşıyorum. Temelde karakteri merminin RigidBody->translate()işleviyle hareket ettiriyorum , ancak bunu yaparken ve bir duvara çarptığımda, hafifçe geçiyorum ve sonra geri sekiyorum. Duvarları olan basit bir Uçak tipi dünyada karakterimi (küre çarpışma şekli olan) hareket ettirmenin başka bir iyi yolu olup olmadığını merak ediyorum?

Buna göre kullandığım kütüphaneler 'Ogre3D' ve 'Bullet Physics'.

Yanıtlar:


9

Özellikle mermi fiziği motoruyla çalışmama rağmen, başka bir fizik motorunda çok benzer bir şey yaptım. Çözdüğüm yol, katı cismin doğrusal hızını doğrudan çevirmek yerine ayarlamaktı. Hareket ve çarpışmalar daha sonra fizik motoru güncelleme aşaması tarafından otomatik olarak ele alındı.

Gönderen belgelerine bir var gibi görünüyor btRigidBody::setLinearVelocitykendinizin kullanabileceği yöntem. Örneğin, herhangi bir hızlanma olmasını istemiyorsanız, karakter hareket ettiğinde doğrusal hızı uygun bir değere ayarlayın ve karakterin durması gerektiğinde (0,0,0) değerine geri ayarlayın (ör. oyuncu anahtarı bıraktığında).

Hangi değerlerin kullanılacağına gelince, genel yaklaşım karakterinizin istenen hızıyla (şamandıra / skaler olarak) başlamak ve daha sonra taşımak istediğiniz yönü işaret eden normalleştirilmiş bir vektörle çarpmak olacaktır. Gördüğüm kadarıyla btVector3sınıf zaten tüm bunlar için yöntemler var.

Alternatif olarak, karakteri eksiksiz bir fizik nesnesi olarak ele alabilir ve applyForceveya applyImpulseyöntemlerini kullanarak hareketi işleyebilirsiniz . Bunlar vücut hızlanmasına neden olur, bu yüzden karakterleriniz ivme kazanır ve sonuçlar muhtemelen bu şekilde daha güzel görünür. Ancak, örneğin, doğrusal hızın, kenetleyerek veya sönümleme / sürtünme ile oynayarak belirli bir sınırı aşmadığından emin olarak bazı ekstra önlemler almanız gerekir. Yani uygulamak ve ince ayar yapmak biraz daha zor olacak.

Her iki yaklaşımla da deney yapın ve ardından ihtiyaçlarınıza en yakın olanı seçin.


Pekala, hızlı cevap için teşekkürler, bunu hemen deneyeceğim.
Molmasepik

LinearVelocity hilesi beklendiği gibi bir cazibe gibi çalıştı! Düzeltmek zorunda kaldım birkaç karışıklığı vardı ama% 100 çalışıyor Cevap için çok teşekkürler!
Molmasepik

9

Kayıt için, fizik ile ilgili deneyimim Chimpunk'u bir 2D oyun motorunda kullanmaktır, ancak eminim bu konsept 3D'ye gayet iyi dönüşür.

Karakterinizin ağırlık ve benzeri bir fizik beden olduğunu varsayıyorum. Bunu yapmanın en iyi yolu, çok basit bir yürüme simülasyonu yapmaktır. Şöyle düşünün: Ayakta duruyorsanız, ayaklarınız çok fazla sürtünmeye sahiptir, bu yüzden sadece etrafta kaymazsınız. Hareket halindeyken, kabaca bu sürtünmeyi ortadan kaldırmak (ayaklarınızla harekete direnmediğiniz için) ve bir yön kuvveti uygulamakla eşdeğerdir. Ben değilim değil tek tek yere iterek her ayak taklit gerektiğini söyleyerek - rijit bir gövde istediğiniz şeydir.

  • Karakteriniz aktif olarak hareket etmeye çalışmadığında, durağan kalmaları için hızlarını sönümleyin.
  • Karakteriniz hareket ederken, hız sönümlemelerini düşürün ve hareket yönünde bir kuvvet uygulayın. Sönümlemenizi ve kuvvetinizi karakter makul bir hızda hareket edecek şekilde ayarlayın.
  • Karakter havadaysa, sönümlemeyi çok çok düşük bir değere ayarlayın. Gerçekçi olmak istiyorsanız, havadayken yönlerini değiştirmek için herhangi bir kuvvet uygulamalarına izin vermeyin. Burada çok daha küçük bir kuvvet uygulamalarına izin vererek mutlu bir ortama çarpabilir ve onlara hava doğuşu sırasında yörüngelerini ayarlama konusunda sınırlı bir yetenek kazandırabilirsiniz.

İşte burada biraz karmaşıklaşıyor:

  • Karakter zaten hareket ediyorsa ve yön değiştiriyorsa, kuvveti uyguladığınız yönü ayarlayarak momentumunuzu telafi etmeniz gerekir. Örneğin, karakteriniz kuzeye doğru hareket ediyor ve doğuya doğru dönüyorsa, gücünüzü karakterin mevcut seyahat yönünün tersi ile hedeflenen seyahat yönünün yarısı arasında bir yönde uygulamanız gerekir. Hareket yönü değiştikçe, kuvveti ikisi arasında daima yarıya gelecek şekilde ayarlayın ve karakteriniz yönleri hızlı ve sorunsuz bir şekilde değiştirecektir.

Gücünüzü ve sönümünüzü doğru bir şekilde ayarlarsanız, bir kuvvet uygulamak her zaman en gerçekçi sonucu verecektir, özellikle de karakter nesneleri itecekse. Çeviri yapmak en kötü yol olacak çünkü fizik motoru bunu hareket olarak görmüyor. Hızın doğrudan ayarlanması biraz daha iyidir, ancak deneyimlerime göre en iyi sonuçlar kuvvet ve sönümleme kullanılarak elde edilebilir.

Umarım bunu yeterince iyi açıklamıştım. Açıklamaya ihtiyacınız olup olmadığını sormaya çekinmeyin. :)


0

Madde 2.87 için, doğru yöntem, dahili simülasyon güncelleme hızında (muhtemelen 100 Hz'lik birçok) güncellenen bir kene geri çağrısına sahip olmak ve kinematik gövdelerdeki setWorldTransform () konumunu sorunsuz bir şekilde güncellemek gibi görünüyor:

Bu bölüm kılavuzdadır:

// set the rigid body as kinematic
rigid_body->setCollisionFlags(
    rigid_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
rigid_body->setActivationState(DISABLE_DEACTIVATION);
...

Bu kısmı anlamak daha zordu:

void externalTickCallback(btDynamicsWorld *world, btScalar timeStep)
{
  // get object passed into user data point
  Foo* foo = static_cast<Foo*>(world->getWorldUserInfo());
  ... loop through all the rigid bodies, maybe foo has them
  {
    if (rigid_body->getCollisionFlags() & btCollisionObject::CF_KINEMATIC_OBJECT)
    {
      btVector3 kinematic_linear_vel = ... // get velocity from somewhere
      btTransform trans;
      rigid_body->getMotionState()->getWorldTransform(trans);
      trans.setOrigin(trans.getOrigin() + kinematic_linear_vel * time_step);
      // TODO support angular velocity
      rigid_body_->getMotionState()->setWorldTransform(trans);
    }
  }
}
...
my_dynamics_world->setInternalTickCallback(tickCallback, static_cast<void*>(this), true);

Bu, btRigidBody.h https://github.com/bulletphysics/bullet3/blob/master/src/BulletDynamics/Dynamics/btRigidBody.h içindeki yararlı belgelerdi :

/// - C) Kinematik nesneler, bunlar kütlesiz nesnelerdir, ancak kullanıcı bunları hareket ettirebilir. Tek yönlü etkileşim vardır ve Bullet, zamana, önceki ve mevcut dünya dönüşümüne göre bir hız hesaplar.

setLinearVelocity (), kinematik nesneler için çalışmaz (belki daha önceki sürümlerde kullanılmıştı?). Ancak dinamik dünya setWorldTransform () 'ı anlayacak ve kinematik nesnede getLinearVelocity ()' e yapılan çağrılar, kene geri çağrısında ayarlanan hızı döndürecektir (bu hızlar dâhili keneden keneye değişecekse muhtemelen bir ortalama döndürür).

https://github.com/bulletphysics/bullet3/issues/1204 - Sorun posterinin doğru fikri var, ancak yanıt yardımcı olmadı.

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.