Sign in to follow this  
LHLaurini

Vsync makes character walk weirdly (Bullet Physics)

Recommended Posts

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.

Share this post


Link to post
Share on other sites

Solved it. The problem was that I was calling a SetPosition function inside void ThirdPersonCharacter::CharacterMotionState::setWorldTransform(const btTransform& WorldTransform) which updated the graphics position, but also called SetWorldTransform. So I just split that function in two and used the graphics update version.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this