Як би я перемістив персонажа в RPG з Bullet Physics / Ogre3D?


9

останнім часом у мене в грі Ogre3D виникли проблеми з переміщенням персонажа. В основному я рухаю персонажа з RigidBody->translate()функцією кулі , але, роблячи це і натикаючись на стіну, я трохи проходжу його, а потім відбиваюся назад. Мені цікаво, чи є ще один хороший спосіб перемістити мого персонажа (який має форму зіткнення кулі) навколо простого світу типу "Площини" зі стінами?

Бібліотеки, які я використовую, відносно цього є "Ogre3D" і "Фізика кулі".

Відповіді:


9

Хоча я спеціально не працював з двигуном фізики кулі, я зробив щось дуже схоже в іншому двигуні фізики. Я вирішив це шляхом встановлення лінійної швидкості жорсткого тіла замість того, щоб перекладати його безпосередньо. Потім рух і зіткнення автоматично оброблялися на етапі оновлення фізичного двигуна.

З документації , здається, існує btRigidBody::setLinearVelocityметод, який ви можете використовувати. Наприклад, якщо ви не хочете, щоб якісь прискорення відбувалися, просто встановіть лінійну швидкість на відповідне значення кожного разу, коли персонаж рухається, і встановіть його назад (0,0,0), коли символ повинен зупинитися (тобто коли гравець відпустить ключ).

Що стосується того, які значення використовувати, звичайним підходом було б починати з бажаної швидкості вашого персонажа (як поплавок / скаляр), а потім помножувати його на нормалізований вектор, який спрямований у напрямку, в якому ви хочете рухатися. З того, що я бачуbtVector3 класі вже є методи для всього цього.

Крім того, ви можете розглянути характер для персонажа як повного об'єкта фізики та керувати рухом за допомогою applyForceабо applyImpulseметодів. Це призведе до прискорення тіла, тому ваші персонажі матимуть силу і результати, ймовірно, виглядатимуть приємніше. Але вам потрібно вжити деяких додаткових заходів, наприклад, переконавшись, що лінійна швидкість ніколи не перевищує певну межу, або затискаючи її, або граючи навколо демпфування / тертя. Так це буде трохи складніше здійснити і фінітувати.

Експериментуйте з обома підходами, а потім виберіть той, який поводиться найближче до ваших потреб.


Добре, дякую за швидку відповідь, я зараз спробую це спробувати.
Молмасепік

Трюк LinearVelocity працював так само, як і очікувалося, як шарм! Було кілька кінок, які мені довелося виправити, але це працює 100%. Дякую за відповідь!
Молмасепік

9

На приклад, мій досвід фізики використовує Chimpunk у 2D ігровому двигуні, але я впевнений, що ця концепція перетворюється на 3D просто.

Я припускаю, що ваш персонаж - це фізичне тіло з вагою і таке. Найкращий спосіб зробити це - зробити дуже спрощене моделювання ходьби. Подумайте про це так: Якщо ви стоїте, ноги мають сильне тертя, тому ви не просто ковзаєте. Коли ви рухаєтесь, це приблизно рівно, як зняти це тертя (оскільки ви не чините опір руху ногами) і застосувати напрямну силу. Я не кажу, що вам слід індивідуально імітувати кожну ступню, натиснувши на землю - жорстке тіло - це те, що ви хочете.

  • Коли ваш персонаж не намагається активно рухатися, зробіть їх швидкість амортизацією високою, щоб вони залишалися нерухомими.
  • Коли ваш персонаж рухається, опустіть їх демпфірування швидкості і застосуйте силу в напрямку руху. Встановіть гасіння і силу так, щоб персонаж рухався з розумною швидкістю.
  • Якщо персонаж знаходиться в повітрі, встановіть гасіння дуже, дуже низько. Якщо ви хочете бути реалістичними, не дозволяйте їм застосовувати будь-яку силу, щоб змінити напрямок, перебуваючи в повітрі. Тут можна вразити щасливе середовище, дозволяючи їм застосовувати набагато меншу силу, надаючи їм деяку обмежену здатність коригувати свою траєкторію під час народження.

Ось де отримати складність:

  • Якщо персонаж вже рухається і вони змінюють напрямок, вам потрібно буде компенсувати свій імпульс, регулюючи напрямок, у якому ви застосовуєте силу. Наприклад, якщо ваш персонаж рухається на північ і повертає на схід, вам потрібно застосувати свою силу в напрямку, що знаходиться на півдорозі між протилежним поточному напрямку подорожі персонажа та його наміченому напрямку подорожі. У міру зміни напрямку руху відрегулюйте силу так, щоб вона завжди була на півдорозі між ними, і ваш персонаж швидко і плавно змінить напрямки.

Якщо ви правильно налаштували силу і загасили, застосування сили завжди дасть найреальніший результат, особливо якщо персонаж буде штовхати предмети навколо. Переклад буде найгіршим способом зробити це, оскільки фізичний двигун насправді не вважає це рухом. Встановлення швидкості безпосередньо дещо краще, але, на мій досвід, найкращі результати можна отримати, використовуючи силу та демпфірування.

Сподіваюся, я це досить добре пояснив. Сміливо запитайте, чи потрібні вам пояснення. :)


0

Для кулі 2.87 правильним методом є зворотний дзвінок, який оновлюється зі швидкістю оновлення внутрішньої симуляції (можливо, багато 100 Гц), а встановлення WorldTransform () на кінематичні тіла плавно оновлює позицію:

Ця частина знаходиться в посібнику:

// 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) Кінематичні об'єкти, які є об'єктами без маси, але користувач може їх переміщувати. Існує одностороння взаємодія, і Куля обчислює швидкість на основі часового кроку та попереднього та поточного перетворення світу.

setLinearVelocity () не працює для кінематичних об'єктів (можливо, це було раніше в попередніх версіях?). Але світ динаміки зрозуміє setWorldTransform () і виклики getLinearVelocity () на кінематичний об'єкт поверне швидкість, встановлену у зворотному виклику галочки (вона, ймовірно, повертає середню величину, якщо ці швидкості повинні були змінитися з внутрішнього галочки на галочку).

https://github.com/bulletphysics/bullet3/isissue/1204 - плакат видання має правильну ідею, але відповідь не корисна.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.