I've made a character controller for Bullet from scratch. It's kinda simple, but works fine, except for when Vsync is on. I can't post the entire code because it would take about 200 lines, but it works like this:
- It is a normal btRigidBody, NOT kinematic.
- Gravity pulls it down like any btRigidBody
- Movement is made by btRigidBody::setLinearVelocity
This is the "core" function (it's not very organized, but does the trick):
void ThirdPersonCharacter::ProcessInputInternal(XMFLOAT2& Move, XMFLOAT2& Look, bool Jump, bool Sprint)
{
XMFLOAT3 Focus;
XMStoreFloat3(&Focus, CharacterCamera.FocusPosition);
CharacterCamera.SetCamera(Focus, CameraDistance, CharacterCamera.Rotation + XMFLOAT3(Look.y, Look.x, 0.0f));
if (CharacterBody->getLinearVelocity().getY() <= 0)
{
CharacterState = OnGround ? Resting : Falling;
}
btScalar Friction(0), Damping(0);
if (OnGround)
{
State LastCharacterState = CharacterState;
btVector3 Velocity(0, 0, 0);
Friction = 1000;
Damping = LastCharacterState == Jumping ? 0 : 1;
if (CharacterState != Jumping)
CharacterState = Resting;
if ((Move != XMFLOAT2(0, 0)) && (LastCharacterState != Jumping))
{
Friction = 1.0f;
Damping = 0.0f;
Velocity = btVector3(Move.x, 0, Move.y).rotate(btVector3(0, 1, 0), CharacterCamera.Rotation.y).normalize()
* (Sprint ? 5 : 2.5);
MeshRotation = CharacterCamera.Rotation.y;
CharacterState = Walking;
}
if (Jump)
{
Friction = 1.0f;
Damping = 0.0f;
Velocity.setY(Velocity.getY() + 5);
CharacterState = Jumping;
}
if (Velocity != btVector3(0, 0, 0))
CharacterBody->setLinearVelocity(Velocity);
}
CharacterBody->setFriction(Friction);
CharacterBody->setDamping(Damping, 0);
}
[hr]
When Vsync is off everything seems to be fine. But when it's on, the problem varies (or doesn't happens) based on a single line of code. When...
DynamicsWorld.stepSimulation(FrameTime, 10);
Walking velocity is normal at the start, then it gets slower and slower until it stops and goes back to normal (and it goes on over again...)
[hr]
When...
DynamicsWorld.stepSimulation(FrameTime, 0);
It works perfectly fine, but I don't know if it's safe to do this. The docs say it disables the fixed timestep and uses the actual timestep, but I think that would be bad if the framerate drops (some objects could pass through others). Am I wrong?
[hr]
When...
DynamicsWorld.stepSimulation(1.f / 60.f);
This would not be a good thing, but I tried it only for testing purposes. It seems that whenever timeStep is equal to fixedTimeStep my character doesn't move at all (doesn't walk nor fall)
[hr]
I'm very confused. These changes only seem to affect the character itself. Can someone help me? Please ask for more details if you need more. I can upload a video if you think it would help.