JoltPhysics icon indicating copy to clipboard operation
JoltPhysics copied to clipboard

Jitter when CharacterVirtual is standing on a diagonally downwards moving platform

Open Ono-Sendai opened this issue 9 months ago • 7 comments

Hi Jorrit, there's an issue when a CharacterVirtual is standing on a platform that is moving downwards but also sideways. See the following video:

https://github.com/user-attachments/assets/09d93b68-c998-4552-b910-fdf03bc35207

Note that everything works fine as the platform moves up, but when moving down the avatar jitters sideways relative to the ground.

Patch to repro is to change line 630 of Samples\Tests\Character\CharacterBaseTest.cpp to

mBodyInterface->MoveKinematic(mReversingVerticallyMovingBody, pos + Vec3(0, mReversingVerticallyMovingVelocity * 1.0f * inParams.mDeltaTime, mReversingVerticallyMovingVelocity * inParams.mDeltaTime), cReversingVerticallyMovingOrientation, inParams.mDeltaTime);

Cheers, Nick

Ono-Sendai avatar Feb 16 '25 11:02 Ono-Sendai

It is caused by PhysicsSystem::Update and CharacterVirtual::Update being called at different times. The physics update will move the platform away from the character. This means that at the beginning of the character update the world state is:

Image

The red line indicates the platform velocity, which is what the character will inherit:

https://github.com/jrouwe/JoltPhysics/blob/c1bdc5aee24ba08359b539efc5dc3b23f8e3bdbc/Samples/Tests/Character/CharacterVirtualTest.cpp#L144

It will currently, unconditionally, add gravity to that velocity (green):

https://github.com/jrouwe/JoltPhysics/blob/c1bdc5aee24ba08359b539efc5dc3b23f8e3bdbc/Samples/Tests/Character/CharacterVirtualTest.cpp#L163

So the resulting velocity will be the blue arrow. This means that the character will hit the platform slightly to the right of where it used to be standing and shift a little bit to the right.

I can fix this particular case by moving the gravity calculation in the else clause like this:

if (...)
{
	// Assume velocity of ground when on ground
	new_velocity = ground_velocity;

	// Jump
	if (inJump && moving_towards_ground)
		new_velocity += sJumpSpeed * mCharacter->GetUp();
}
else
{
	new_velocity = current_vertical_velocity;

	// Gravity
	new_velocity += (character_up_rotation * mPhysicsSystem->GetGravity()) * inDeltaTime;
}

which has the disadvantage that it takes 1 frame longer before gravity will kick in after the platform changes direction. This will make the scene look like this:

https://github.com/user-attachments/assets/38ee5016-bd1a-4d24-9999-c6a395c7ba18

You can probably add some extra logic to detect platform velocity changes to get rid of the hops, but I really consider this 'game code' as everybody can make their own choices how this should behave.

jrouwe avatar Feb 16 '25 19:02 jrouwe

Thanks for the reply. Will try it out soon.

Ono-Sendai avatar Feb 17 '25 13:02 Ono-Sendai

Unfortunately that approach has its own problems - the character becoming unsupported from the ground in some situations on moving (and rotating) platforms.

Ono-Sendai avatar Feb 20 '25 11:02 Ono-Sendai

Are you using the 'stick to floor' feature?

jrouwe avatar Feb 21 '25 12:02 jrouwe

yeah

Ono-Sendai avatar Feb 22 '25 04:02 Ono-Sendai

Are you able to create a repro in the Samples app? The mRotatingAndTranslatingBody body in the samples moves and rotates at the same time and doesn't seem to have issues.

jrouwe avatar Feb 23 '25 16:02 jrouwe

Here's an example of problems when gravity is only applied with character is not supported: https://youtu.be/UCLnK43sRJA

It seems like something to do with interacting with complicated mesh geometry. I don't really want to try and make a repro in the samples app.

Ono-Sendai avatar Mar 03 '25 10:03 Ono-Sendai