我目前正在使用子弹物理来模拟我的世界中的物理现象。现在,我有一个可控制的播放器,可以通过 ApplyForce 移动,但它还没有旋转的能力。
但是,我将角度运动锁定到Y轴(俯仰),但它似乎不起作用:
初始化时:
// Player.cpp
m_physicsBodyComp->LockRotation({0.f, 1.f, 0.f});
// PhysicsBodyComponent.cpp
void tse::PhysicsBodyComponent::LockRotation(const TSVector3 & a_axis) {
if(m_rigidBody)
m_rigidBody->setAngularFactor(btVector3(a_axis.GetX(), a_axis.GetY(), a_axis.GetZ()));
}
另外,也可能导致问题:在物理模拟之前,我将刚体的变换设置为变换组件的变换,在物理模拟之后,我将变换组件的变换设置为刚体变换。
// Before physics simulation
void tse::PhysicsBodyComponent::UpdateTransformComponent() {
if(m_rigidBody) {
if(m_transformComponent->m_wasDirty && m_transformComponent->IsValid()) {
btQuaternion _quat;
_quat.setEuler(m_transformComponent->m_rotation.GetY(), m_transformComponent->m_rotation.GetX(), m_transformComponent->m_rotation.GetZ());
btTransform _trans;
_trans.setRotation(_quat);
_trans.setOrigin(m_transformComponent->m_position.GetVecBt());
m_rigidBody->setWorldTransform(_trans);
m_transformComponent->m_wasDirty = false;
Activate();
}
}
}
// After physics simulation
void tse::PhysicsBodyComponent::Update(float a_deltaTime) {
if(m_rigidBody) {
if(m_bodyType == PhysicsBodyType::DYNAMIC) {
btTransform & _trans = m_rigidBody->getWorldTransform();
DirectX::XMVECTOR _rotation;
btQuaternion _quat = _trans.getRotation();
_rotation.m128_f32[0] = _quat.getX();
_rotation.m128_f32[1] = _quat.getY();
_rotation.m128_f32[2] = _quat.getZ();
m_transformComponent->SetPosition(TSVector3(_trans.getOrigin()));
m_transformComponent->SetRotation(_rotation);
}
}
}
所以,问题是我锁定了x轴和z轴的旋转,但它仍然改变了x轴和z轴的旋转(问题的GIF如下所示)。正如我之前所说,我还没有轮换球员。您在下面的 GIF 中看到的每一次旋转都完全由 BulletPhysics 完成。我只用 AddForce 移动玩家。
我做的事情是完全错误的还是这是 Bullet 物理中的一个已知错误?预先感谢..!
您是否为您的玩家创建动态或运动学刚体?
运动刚体只能由用户移动/设置动画,动态对象也可以通过所有其他对象移动...请参阅项目符号用户手册第 14 页。 19+20
因此,如果您的玩家只能使用 addForce() 等移动,请创建一个运动体。
我如何创建运动学刚体: (C#中的例子,C++应该类似)
// Create rigid Body
float mass = 0.0f; // kinematic bodies have no mass
RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, new DefaultMotionState(), collisionShape);
RigidBody rigidBody = new RigidBody(rbInfo);
rbInfo.Dispose();
// Mass=0 -> static/kinematic possible -> use flag distinguish
rigidBody.CollisionFlags = CollisionFlags.KinematicObject;
我遇到了同样的问题,但是如果你在每一帧调用 setAngularFactor() ,它应该可以工作