ฉันจะย้ายตัวละครในเกม RPG ด้วย Bullet Physics / Ogre3D ได้อย่างไร


9

เมื่อเร็ว ๆ นี้ฉันมีปัญหากับการย้ายตัวละครในเกม Ogre3D ของฉัน โดยทั่วไปฉันกำลังเคลื่อนไหวตัวละครด้วยRigidBody->translate()ฟังก์ชั่นกระสุนแต่เมื่อทำเช่นนั้นและชนเข้ากับกำแพงฉันก็ผ่านมันไปเล็กน้อยแล้วก็เด้งกลับมา ฉันสงสัยว่ามีวิธีที่ดีอีกวิธีหนึ่งในการย้ายตัวละครของฉัน (ที่มีรูปร่างทรงกลมปะทะกัน) ไปรอบ ๆ ในโลกแบบเครื่องบินเรียบๆกับกำแพงหรือไม่?

ห้องสมุดที่ฉันใช้ซึ่งเกี่ยวข้องกับสิ่งนี้คือ 'Ogre3D' และ 'Bullet Physics'

คำตอบ:


9

แม้ว่าฉันจะไม่ได้ทำงานกับเอ็นจิ้นกระสุนปืนโดยเฉพาะ แต่ฉันก็ทำอะไรที่คล้ายกันมากในเอนจินฟิสิกส์อื่น วิธีที่ฉันแก้ไขมันคือการตั้งค่าความเร็วเชิงเส้นของร่างกายแข็งแทนที่จะแปลโดยตรง การเคลื่อนไหวและการชนนั้นถูกจัดการโดยอัตโนมัติโดยขั้นตอนการอัพเดทเครื่องยนต์ฟิสิกส์

ดูเหมือนว่าจะมีวิธีการที่คุณสามารถใช้จากเอกสารประกอบ btRigidBody::setLinearVelocityตัวอย่างเช่นหากคุณไม่ต้องการความเร่งใด ๆ ให้ตั้งค่าความเร็วเชิงเส้นเป็นค่าที่เหมาะสมเมื่อใดก็ตามที่ตัวละครกำลังเคลื่อนที่และตั้งค่ากลับเป็น (0,0,0) เมื่อตัวละครควรหยุด (เช่น เมื่อผู้เล่นออกกุญแจ)

สำหรับค่าที่จะใช้วิธีการปกติจะเริ่มต้นด้วยความเร็วที่ต้องการของตัวละครของคุณ (เช่นโฟลต / สเกลาร์) จากนั้นคูณด้วยเวกเตอร์ปกติที่ชี้ไปในทิศทางที่คุณต้องการย้าย จากสิ่งที่ฉันเห็นในbtVector3ชั้นเรียนมีวิธีการทั้งหมดนี้แล้ว

อีกทางหนึ่งคุณอาจพิจารณาว่าตัวละครเป็นวัตถุฟิสิกส์ที่สมบูรณ์และจัดการกับการเคลื่อนไหวโดยใช้วิธีการapplyForceหรือ applyImpulseสิ่งเหล่านี้จะส่งผลให้ร่างกายเร่งความเร็วดังนั้นตัวละครของคุณจะมีแรงผลักดันและผลลัพธ์อาจดูดีกว่าด้วยวิธีนี้ แต่คุณจำเป็นต้องใช้มาตรการพิเศษบางอย่างเช่นโดยการทำให้แน่ใจว่าความเร็วเชิงเส้นจะไม่เกินขีด จำกัด ที่แน่นอนไม่ว่าจะโดยการหนีบหรือเล่นรอบ ๆ ด้วยการทำให้หมาด ๆ / แรงเสียดทาน ดังนั้นมันจะยากขึ้นเล็กน้อยในการติดตั้งและปรับแต่ง

ทดลองกับทั้งสองวิธีแล้วเลือกวิธีที่ใกล้เคียงกับความต้องการของคุณมากที่สุด


เอาล่ะขอบคุณสำหรับคำตอบอย่างรวดเร็วฉันจะลองทำทันที
Molmasepic

เคล็ดลับ LinearVelocity ใช้งานได้ตามที่คาดหวังเช่นมีเสน่ห์! มีปัญหาเล็กน้อยที่ฉันต้องแก้ไข แต่ใช้งานได้ 100% ขอบคุณมากสำหรับคำตอบ!
Molmasepic

9

สำหรับบันทึกประสบการณ์ของฉันกับฟิสิกส์กำลังใช้ Chimpunk ในเครื่องมือเกม 2D แต่ฉันค่อนข้างมั่นใจว่าแนวคิดนี้แปลเป็น 3D ได้ดี

ฉันสมมติว่าตัวละครของคุณเป็นตัวฟิสิกส์ที่มีน้ำหนักและอย่างนั้น วิธีที่ดีที่สุดในการทำเช่นนี้คือการจำลองการเดินที่ง่ายขึ้น ลองคิดแบบนี้: ถ้าคุณยืนเท้าของคุณมีแรงเสียดทานมากมายดังนั้นคุณจึงไม่เพียงเลื่อนไปมา เมื่อคุณเคลื่อนไหวก็เท่ากับการเอาแรงเสียดทานนั้นออกมา (เนื่องจากคุณไม่ได้ต่อต้านการเคลื่อนไหวด้วยเท้าของคุณ) และใช้แรงทาง ฉันไม่ได้กำลังบอกว่าคุณควรจำลองเท้าแต่ละข้างที่กดลงบนพื้นทีละชิ้น - ร่างกายที่แข็งแรงคือสิ่งที่คุณต้องการ

  • เมื่อตัวละครของคุณไม่ได้พยายามเคลื่อนไหวให้ทำให้ความเร็วลดลงจนทำให้พวกเขาหยุดนิ่ง
  • เมื่อตัวละครของคุณเคลื่อนไหวลดความเร็วของพวกเขาลงและใช้แรงในทิศทางของการเคลื่อนไหว ตั้งค่าการหน่วงและแรงของคุณเพื่อให้ตัวละครเคลื่อนไหวด้วยความเร็วที่เหมาะสม
  • หากตัวละครอยู่ในอากาศให้ตั้งค่าการหน่วงมากต่ำมาก หากคุณต้องการให้เหมือนจริงอย่าปล่อยให้พวกเขาใช้กำลังใด ๆ ในการเปลี่ยนทิศทางขณะอยู่ในอากาศ คุณสามารถโจมตีสื่อที่มีความสุขได้ที่นี่โดยอนุญาตให้พวกเขาใช้แรงที่น้อยกว่ามากทำให้พวกเขามีความสามารถ จำกัด ในการปรับวิถีการเคลื่อนที่ของพวกเขาในขณะที่อากาศเกิดขึ้น

นี่คือสิ่งที่ได้รับซับซ้อนเล็กน้อย:

  • หากตัวละครนั้นเคลื่อนไหวแล้วและพวกเขาเปลี่ยนทิศทางคุณจะต้องชดเชยแรงผลักดันของคุณโดยการปรับทิศทางที่คุณบังคับใช้ ตัวอย่างเช่นหากตัวละครของคุณเคลื่อนไหวไปทางทิศเหนือและไปทางตะวันออกคุณต้องใช้กำลังของคุณในทิศทางที่ครึ่งทางระหว่างทิศทางตรงกันข้ามกับทิศทางการเดินทางของตัวละครในปัจจุบันและทิศทางการเดินทางที่ต้องการ เมื่อทิศทางของการเดินทางเปลี่ยนไปให้ปรับแรงเพื่อให้มันอยู่กึ่งกลางระหว่างทั้งสองเสมอและตัวละครของคุณจะเปลี่ยนทิศทางได้อย่างรวดเร็วและราบรื่น

หากคุณปรับกำลังและการหน่วงให้ถูกต้องการใช้แรงจะให้ผลลัพธ์ที่สมจริงที่สุดโดยเฉพาะอย่างยิ่งถ้าตัวละครนั้นกำลังผลักวัตถุไปมา การแปลจะเป็นวิธีที่เลวร้ายที่สุดในการทำเช่นนี้เนื่องจากเอ็นจิ้นฟิสิกส์ไม่ได้ถือว่าเป็นการเคลื่อนไหว การตั้งค่าความเร็วโดยตรงนั้นค่อนข้างดีกว่า แต่จากประสบการณ์ของฉันผลลัพธ์ที่ดีที่สุดสามารถทำได้โดยการใช้กำลังและการทำให้หมาด ๆ

หวังว่าฉันจะอธิบายเรื่องนี้ดีพอ อย่าลังเลที่จะถามหากคุณต้องการคำชี้แจง :)


0

สำหรับ bullet 2.87 ดูเหมือนว่าวิธีการที่เหมาะสมคือการติ๊กติ๊กที่ปรับปรุงอัตราการจำลองสถานการณ์ภายใน (อาจเป็น 100 Hz จำนวนมาก) และ setWorldTransform () บนเนื้อจลนศาสตร์จะทำการอัปเดตตำแหน่งได้อย่างราบรื่น:

ส่วนนี้อยู่ในคู่มือ:

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

ส่วนนี้ยากกว่าที่จะเข้าใจ:

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);

นี่เป็นเอกสารที่มีประโยชน์ใน btRigidBody.h https://github.com/bulletphysics/bullet3/blob/master/src/BulletDynamics/Dynamics/btRigidBody.h :

/// - C) วัตถุ Kinematic ซึ่งเป็นวัตถุที่ไม่มีมวล แต่ผู้ใช้สามารถเคลื่อนย้ายวัตถุเหล่านั้นได้ มีการโต้ตอบทางเดียวและ Bullet จะคำนวณความเร็วตามการประทับเวลาและการแปลงโลกก่อนหน้าและปัจจุบัน

setLinearVelocity () ไม่สามารถใช้ได้กับวัตถุจลน์ศาสตร์ (อาจเคยเป็นรุ่นก่อนหน้านี้หรือไม่) แต่โลกพลวัตจะเข้าใจ setWorldTransform () และการเรียกใช้ getLinearVelocity () บนวัตถุจลศาสตร์นั้นจะคืนค่าความเร็วที่กำหนดในการเรียกกลับเห็บ

https://github.com/bulletphysics/bullet3/issues/1204 - โปสเตอร์ปัญหามีความคิดที่ถูกต้อง แต่การตอบกลับไม่เป็นประโยชน์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.