Bullet Physics / Ogre3D가있는 RPG에서 캐릭터를 어떻게 이동합니까?


9

최근에 저는 Ogre3D 게임에서 캐릭터를 옮기는 데 문제가있었습니다. 기본적으로 나는 총알의 RigidBody->translate()기능으로 캐릭터를 움직이고 있지만, 그렇게하고 벽에 부딪 칠 때 약간 통과 한 다음 되돌아옵니다. 벽이있는 단순한 평면 형 세계에서 캐릭터 (구 충돌 모양을 가진 사람)를 움직일 수있는 또 다른 좋은 방법이 있는지 궁금합니다.

내가 사용하는 라이브러리는 'Ogre3D'와 'Bullet Physics'입니다.

답변:


9

총알 물리 엔진으로 특별히 작업하지는 않았지만 다른 물리 엔진에서 매우 비슷한 작업을 수행했습니다. 내가 해결 한 방법은 강체의 선형 속도를 직접 변환하는 대신 설정하는 것이 었습니다. 그런 다음 물리 엔진 업데이트 단계에서 이동 및 충돌을 자동으로 처리했습니다.

로부터 문서 있을 것 같습니다 btRigidBody::setLinearVelocity당신이 사용할 수있는 방법. 예를 들어, 가속이 일어나지 않게하려면 캐릭터가 움직일 때마다 선형 속도를 적절한 값으로 설정하고 캐릭터가 정지해야 할 때 다시 (0,0,0)으로 설정하십시오. 플레이어가 키를 놓을 때).

어떤 값을 사용할 지에 대한 일반적인 접근 방식은 원하는 캐릭터 속도 (float / scalar)로 시작한 다음 이동하려는 방향을 가리키는 정규화 된 벡터를 곱하는 것입니다. 내가 볼 수 있듯이 btVector3클래스에는 이미이 모든 방법이 있습니다.

또는 캐릭터를 완전한 물리 객체로 취급하고 applyForce또는 applyImpulse메소드를 사용하여 움직임을 처리하는 것을 고려할 수 있습니다 . 이로 인해 신체 가속이 발생하므로 캐릭터의 추진력이 높아지고 결과는 아마도 이런 식으로 더 좋아 보일 것입니다. 그러나 선형 속도가 클램핑되거나 댐핑 / 마찰로 놀아서 특정 제한을 초과하지 않도록하는 등의 추가 조치를 취해야합니다. 따라서 구현하고 미세 조정하기가 조금 더 어려울 것입니다.

두 가지 접근 방식을 모두 실험 한 다음 필요에 가장 가까운 방식을 선택하십시오.


알겠습니다, 빠른 답변 감사합니다. Im 바로 시도해 보겠습니다.
Molmasepic

LinearVelocity 트릭은 매력처럼 예상대로 작동했습니다! 내가 고쳐야 할 몇 가지 꼬임이 있었지만 작동하는 100 % 답변에 너무 감사합니다!
Molmasepic

9

실제로 물리학에 대한 경험은 2D 게임 엔진에서 Chimpunk를 사용하고 있지만이 개념이 3D로 잘 해석 될 것입니다.

나는 당신의 성격이 무게와 같은 물리 몸이라고 가정합니다. 가장 좋은 방법은 걷기의 시뮬레이션을 단순화하는 것입니다. 이것을 다음과 같이 생각하십시오. 서 있으면 발에 마찰이 많이 발생하므로 미끄러지지 않습니다. 움직일 때는 마찰을 제거하고 (발로 움직임에 저항하지 않기 때문에) 방향 힘을 가하는 것과 거의 같습니다. 나는 당신이 각 발을지면에서 밀고있는 것을 개별적으로 시뮬레이션해야한다는 것을 말하는 것이 아닙니다 .

  • 캐릭터가 적극적으로 움직이려고하지 않을 때는 속도를 댐핑하여 고정 상태를 유지하십시오.
  • 캐릭터가 움직일 때 속도 댐핑을 낮추고 움직임 방향으로 힘을가하십시오. 캐릭터가 적당한 속도로 움직 이도록 댐핑과 힘을 설정하십시오.
  • 캐릭터가 공중에 있으면 댐핑을 매우 낮게 설정하십시오. 현실감을 원한다면 공중에서 방향을 바꾸기 위해 힘을 가하지 마십시오. 당신은 그들이 훨씬 작은 힘을 가할 수있게함으로써 공허한 매체를 공격 할 수 있습니다.

get이 조금 복잡 해지는 곳은 다음과 같습니다.

  • 캐릭터가 이미 움직이고 방향이 바뀌면 힘을 가하는 방향을 조정하여 운동량을 보정해야합니다. 예를 들어, 캐릭터가 북쪽으로 이동하고 동쪽으로 회전하는 경우 캐릭터의 현재 이동 방향의 반대 방향과 의도 한 이동 방향 사이의 절반 방향으로 힘을 가해 야합니다. 이동 방향이 변함에 따라 항상 둘 사이의 반이되도록 힘을 조정하면 캐릭터가 빠르고 부드럽게 방향을 바꿀 수 있습니다.

힘과 댐핑을 정확하게 조정하면, 힘이 가해지면 특히 캐릭터가 물체를 밀고있을 때 가장 현실적인 결과를 얻을 수 있습니다. 물리 엔진은 실제로 그것을 이동이라고 생각하지 않기 때문에 번역은 최악의 방법입니다. 속도를 직접 설정하는 것이 다소 좋지만 내 경험상 힘과 댐핑을 사용하여 최상의 결과를 얻을 수 있습니다.

잘만되면 나는 이것을 충분히 설명했다. 설명이 필요한지 언제든지 문의하십시오. :)


0

글 머리 기호 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) 운동 학적 객체. 질량이없는 객체이지만 사용자는 이동할 수 있습니다. 단방향 상호 작용이 있으며 Bullet은 시간 간격과 이전 및 현재 월드 변환을 기반으로 속도를 계산합니다.

운동 학적 객체에는 setLinearVelocity ()가 작동하지 않습니다 (이전 버전에서는 사용 했었 을까요?). 그러나 역학 세계는 setWorldTransform ()을 이해하고 운동학 객체에서 getLinearVelocity ()를 호출하면 틱 콜백에 설정된 속도를 반환합니다 (속도가 내부 틱에서 틱으로 변경되면 평균을 반환합니다).

https://github.com/bulletphysics/bullet3/issues/1204- 문제 포스터에 올바른 아이디어가 있지만 응답이 도움이되지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.