Làm cách nào để di chuyển một nhân vật Trong một game nhập vai với Bullet Vật lý / Ogre3D?


9

Gần đây tôi đã gặp vấn đề với việc di chuyển nhân vật của mình trong trò chơi Ogre3D. Về cơ bản, tôi đang di chuyển nhân vật với RigidBody->translate()chức năng của viên đạn , nhưng khi làm như vậy và va vào một bức tường, tôi đi nhẹ qua nó và sau đó bị bật trở lại. Tôi tự hỏi liệu có cách nào khác để di chuyển nhân vật của tôi (người có hình dạng va chạm hình cầu) xung quanh trong một thế giới kiểu Máy bay đơn giản với những bức tường không?

Các thư viện tôi đang sử dụng có liên quan đến điều này là 'Ogre3D' và 'Bullet Vật lý'.

Câu trả lời:


9

Mặc dù tôi đã không làm việc với động cơ vật lý đạn đặc biệt, tôi đã làm một cái gì đó rất giống với động cơ vật lý khác. Cách mà tôi giải quyết là thiết lập vận tốc tuyến tính của cơ thể cứng nhắc thay vì dịch trực tiếp. Chuyển động và va chạm sau đó được tự động xử lý bởi giai đoạn cập nhật động cơ vật lý.

Từ các tài liệu dường như có một btRigidBody::setLinearVelocityphương pháp mà bạn có thể sử dụng. Vì vậy, ví dụ, nếu bạn không muốn bất kỳ gia tốc nào xảy ra, chỉ cần đặt vận tốc tuyến tính thành một giá trị phù hợp bất cứ khi nào nhân vật di chuyển và đặt nó trở lại (0,0,0) khi nhân vật được cho là dừng lại (nghĩa là khi người chơi nhả chìa khóa).

Đối với những giá trị nào sẽ sử dụng, cách tiếp cận thông thường sẽ là bắt đầu với tốc độ mong muốn của nhân vật của bạn (dưới dạng float / vô hướng) và sau đó nhân nó với một vectơ chuẩn hóa đang chỉ theo hướng bạn muốn di chuyển. Từ những gì tôi có thể thấy btVector3lớp đã có các phương thức cho tất cả điều này.

Ngoài ra, bạn có thể coi việc coi nhân vật là một đối tượng vật lý hoàn chỉnh và xử lý chuyển động bằng cách sử dụng applyForcehoặc applyImpulsephương thức. Những điều này sẽ dẫn đến việc tăng tốc cơ thể, vì vậy các nhân vật của bạn sẽ có động lực và kết quả có thể sẽ đẹp hơn theo cách này. Nhưng bạn cần phải thực hiện một số biện pháp bổ sung, ví dụ, bằng cách đảm bảo vận tốc tuyến tính không bao giờ vượt quá một giới hạn nhất định, bằng cách kẹp nó hoặc chơi xung quanh với giảm xóc / ma sát. Vì vậy, nó sẽ khó hơn một chút để thực hiện và finetune.

Thử nghiệm với cả hai phương pháp và sau đó chọn phương pháp ứng xử gần nhất với nhu cầu của bạn.


Được rồi, cảm ơn vì câu trả lời nhanh chóng, tôi sẽ thử ngay lập tức.
Molmasepic

Thủ thuật linearVelocity hoạt động đúng như mong đợi! Có một vài nút thắt mà tôi phải sửa nhưng nó hoạt động 100% Cảm ơn rất nhiều vì câu trả lời!
Molmasepic

9

Để ghi lại, trải nghiệm của tôi với vật lý là sử dụng Chimpunk trong công cụ trò chơi 2D, nhưng tôi khá chắc chắn khái niệm này chuyển thành 3D tốt.

Tôi cho rằng nhân vật của bạn là một cơ thể vật lý có trọng lượng và như vậy. Cách tốt nhất để làm điều này là thực hiện một mô phỏng đi bộ rất đơn giản. Hãy nghĩ về nó như thế này: Nếu bạn đang đứng, đôi chân của bạn có nhiều ma sát, vì vậy bạn không chỉ trượt xung quanh. Khi bạn di chuyển, nó gần tương đương với việc loại bỏ ma sát đó (vì bạn không chống lại chuyển động bằng chân) và tác dụng lực hướng. Tôi không nói rằng bạn nên mô phỏng riêng từng chân đẩy trên mặt đất - một cơ thể cứng nhắc là những gì bạn muốn.

  • Khi nhân vật của bạn không chủ động cố gắng di chuyển, hãy làm cho vận tốc của họ giảm xuống cao để họ đứng yên.
  • Khi nhân vật của bạn đang di chuyển, hãy giảm tốc độ giảm xóc của họ và tác dụng một lực theo hướng chuyển động. Đặt giảm xóc và lực của bạn để nhân vật di chuyển với tốc độ hợp lý.
  • Nếu nhân vật ở trên không, hãy đặt giảm xóc rất, rất thấp. Nếu bạn muốn thực tế, đừng cho phép họ áp dụng bất kỳ lực nào để thay đổi hướng của họ khi ở trên không. Bạn có thể tấn công một phương tiện hạnh phúc ở đây bằng cách cho phép chúng áp dụng một lực nhỏ hơn nhiều, cho chúng một số khả năng hạn chế để điều chỉnh quỹ đạo của chúng trong khi không khí.

Đây là nơi có được một chút phức tạp:

  • Nếu nhân vật đã di chuyển và họ thay đổi hướng, bạn sẽ cần phải bù cho động lượng của mình bằng cách điều chỉnh hướng mà bạn áp dụng lực. Ví dụ, nếu nhân vật của bạn di chuyển theo hướng bắc và quay về hướng đông, bạn cần áp dụng lực của mình theo hướng nằm giữa nửa đường đối diện với hướng di chuyển hiện tại của nhân vật và hướng di chuyển dự định của họ. Khi hướng di chuyển thay đổi, hãy điều chỉnh lực sao cho nó luôn ở giữa hai bên và nhân vật của bạn sẽ thay đổi hướng nhanh chóng và thuận lợi.

Nếu bạn điều chỉnh lực của mình và giảm xóc một cách chính xác, áp dụng một lực sẽ luôn mang lại cho bạn kết quả thực tế nhất, đặc biệt nếu nhân vật sẽ đẩy các vật xung quanh. Dịch thuật sẽ là cách tồi tệ nhất để làm điều đó, vì động cơ vật lý không thực sự coi đó là chuyển động. Đặt vận tốc trực tiếp có phần tốt hơn, nhưng theo kinh nghiệm của tôi, kết quả tốt nhất có thể đạt được bằng cách sử dụng lực và giảm xóc.

Hy vọng tôi đã giải thích điều này đủ tốt. Hãy hỏi nếu bạn cần làm rõ. :)


0

Đối với viên đạn 2.87, có vẻ như phương pháp thích hợp là có một cuộc gọi lại đánh dấu cập nhật ở tốc độ cập nhật mô phỏng bên trong (có thể là 100 Hz) và setWorldTransform () trên các thân động học sẽ cập nhật vị trí một cách trơn tru:

Phần này có trong hướng dẫn:

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

Phần này khó hơn để tìm ra:

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

Đây là tài liệu hữu ích trong btRigidBody.h https://github.com/bONSphysics/bONS3/blob/master/src/BONSDoperics/DOUNDics/btRigidBody.h :

/// - C) Các đối tượng động học, là các đối tượng không có khối lượng, nhưng người dùng có thể di chuyển chúng. Có tương tác một chiều và Bullet tính toán vận tốc dựa trên dấu thời gian và biến đổi thế giới trước đó và hiện tại.

setLinearVelocity () không hoạt động cho các đối tượng động học (có thể nó được sử dụng trong các phiên bản trước?). Nhưng thế giới động lực sẽ hiểu setWorldTransform () và gọi tới getLinearVelocity () trên đối tượng động học sẽ trả về vận tốc được đặt trong cuộc gọi lại đánh dấu (có thể trả về mức trung bình nếu các vận tốc đó thay đổi từ đánh dấu nội bộ sang đánh dấu).

https://github.com/bONSphysics/bONS3/issues/1204 - poster vấn đề có ý tưởng đúng nhưng phản hồi không hữu ích.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.