Vsync makes character walk weirdly (Bullet Physics)

Started by
0 comments, last by LHLaurini 8 years, 5 months ago

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.

Advertisement

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.

This topic is closed to new replies.

Advertisement