瀏覽代碼

CancelVelocityTowardsSteepSlopes uses contact normal iso surface normal for better sliding (#423)

* Using contact normal instead of surface normal for sliding

* Ability to change character jump speed / speed
Ability to disable movement ontrols while in air
Jorrit Rouwe 2 年之前
父節點
當前提交
64fd3927e1

+ 2 - 1
Jolt/Physics/Character/CharacterVirtual.cpp

@@ -985,7 +985,8 @@ Vec3 CharacterVirtual::CancelVelocityTowardsSteepSlopes(Vec3Arg inDesiredVelocit
 		if (c.mHadCollision
 			&& IsSlopeTooSteep(c.mSurfaceNormal))
 		{
-			Vec3 normal = c.mSurfaceNormal;
+			// Note that we use the contact normal to allow for better sliding as the surface normal may be in the opposite direction of movement.
+			Vec3 normal = c.mContactNormal;
 
 			// Remove normal vertical component
 			normal -= normal.Dot(mUp) * mUp;

+ 9 - 0
Samples/Tests/Character/CharacterBaseTest.cpp

@@ -547,6 +547,15 @@ void CharacterBaseTest::CreateSettingsMenu(DebugUI *inUI, UIElement *inSubMenu)
 		inUI->ShowMenu(scene_name);
 	});
 
+	inUI->CreateTextButton(inSubMenu, "Character Movement Settings", [=]() {
+		UIElement *movement_settings = inUI->CreateMenu();
+
+		inUI->CreateCheckBox(movement_settings, "Control Movement During Jump", sControlMovementDuringJump, [](UICheckBox::EState inState) { sControlMovementDuringJump = inState == UICheckBox::STATE_CHECKED; });
+		inUI->CreateSlider(movement_settings, "Character Speed", sCharacterSpeed, 0.1f, 10.0f, 0.1f, [](float inValue) { sCharacterSpeed = inValue; });
+		inUI->CreateSlider(movement_settings, "Character Jump Speed", sJumpSpeed, 0.1f, 10.0f, 0.1f, [](float inValue) { sJumpSpeed = inValue; });
+		inUI->ShowMenu(movement_settings);
+	});
+
 	inUI->CreateTextButton(inSubMenu, "Configuration Settings", [=]() {
 		UIElement *configuration_settings = inUI->CreateMenu();
 

+ 5 - 2
Samples/Tests/Character/CharacterBaseTest.h

@@ -53,8 +53,11 @@ protected:
 	static constexpr float	cCharacterRadiusStanding = 0.3f;
 	static constexpr float	cCharacterHeightCrouching = 0.8f;
 	static constexpr float	cCharacterRadiusCrouching = 0.3f;
-	static constexpr float	cCharacterSpeed = 6.0f;
-	static constexpr float	cJumpSpeed = 4.0f;
+
+	// Character movement properties
+	inline static bool		sControlMovementDuringJump = true;					///< If false the character cannot change movement direction in mid air
+	inline static float		sCharacterSpeed = 6.0f;
+	inline static float		sJumpSpeed = 4.0f;
 
 	// The different stances for the character
 	RefConst<Shape>			mStandingShape;

+ 15 - 12
Samples/Tests/Character/CharacterTest.cpp

@@ -82,20 +82,23 @@ void CharacterTest::HandleInput(Vec3Arg inMovementDirection, bool inJump, bool i
 			inMovementDirection -= (dot * normal) / normal.LengthSq();
 	}
 
-	// Update velocity
-	Vec3 current_velocity = mCharacter->GetLinearVelocity();
-	Vec3 desired_velocity = cCharacterSpeed * inMovementDirection;
-	desired_velocity.SetY(current_velocity.GetY());
-	Vec3 new_velocity = 0.75f * current_velocity + 0.25f * desired_velocity;
-
 	// Stance switch
 	if (inSwitchStance)
 		mCharacter->SetShape(mCharacter->GetShape() == mStandingShape? mCrouchingShape : mStandingShape, 1.5f * mPhysicsSystem->GetPhysicsSettings().mPenetrationSlop);
 
-	// Jump
-	if (inJump && ground_state == Character::EGroundState::OnGround)
-		new_velocity += Vec3(0, cJumpSpeed, 0);
-
-	// Update the velocity
-	mCharacter->SetLinearVelocity(new_velocity);
+	if (sControlMovementDuringJump || mCharacter->IsSupported())
+	{
+		// Update velocity
+		Vec3 current_velocity = mCharacter->GetLinearVelocity();
+		Vec3 desired_velocity = sCharacterSpeed * inMovementDirection;
+		desired_velocity.SetY(current_velocity.GetY());
+		Vec3 new_velocity = 0.75f * current_velocity + 0.25f * desired_velocity;
+
+		// Jump
+		if (inJump && ground_state == Character::EGroundState::OnGround)
+			new_velocity += Vec3(0, sJumpSpeed, 0);
+
+		// Update the velocity
+		mCharacter->SetLinearVelocity(new_velocity);
+	}
 }

+ 25 - 7
Samples/Tests/Character/CharacterVirtualTest.cpp

@@ -89,11 +89,20 @@ void CharacterVirtualTest::PrePhysicsUpdate(const PreUpdateParams &inParams)
 
 void CharacterVirtualTest::HandleInput(Vec3Arg inMovementDirection, bool inJump, bool inSwitchStance, float inDeltaTime)
 {
-	// Smooth the player input
-	mDesiredVelocity = 0.25f * inMovementDirection * cCharacterSpeed + 0.75f * mDesiredVelocity;
+	bool player_controls_horizontal_velocity = sControlMovementDuringJump || mCharacter->IsSupported();
+	if (player_controls_horizontal_velocity)
+	{
+		// Smooth the player input
+		mDesiredVelocity = 0.25f * inMovementDirection * sCharacterSpeed + 0.75f * mDesiredVelocity;
 
-	// True if the player intended to move
-	mAllowSliding = !inMovementDirection.IsNearZero();
+		// True if the player intended to move
+		mAllowSliding = !inMovementDirection.IsNearZero();
+	}
+	else
+	{
+		// While in air we allow sliding
+		mAllowSliding = true;
+	}
 
 	// Update the character rotation and its up vector to match the up vector set by the user settings
 	Quat character_up_rotation = Quat::sEulerAngles(Vec3(sUpRotationX, 0, sUpRotationZ));
@@ -112,7 +121,7 @@ void CharacterVirtualTest::HandleInput(Vec3Arg inMovementDirection, bool inJump,
 
 		// Jump
 		if (inJump)
-			new_velocity += cJumpSpeed * mCharacter->GetUp();
+			new_velocity += sJumpSpeed * mCharacter->GetUp();
 	}
 	else
 		new_velocity = current_vertical_velocity;
@@ -120,8 +129,17 @@ void CharacterVirtualTest::HandleInput(Vec3Arg inMovementDirection, bool inJump,
 	// Gravity
 	new_velocity += (character_up_rotation * mPhysicsSystem->GetGravity()) * inDeltaTime;
 
-	// Player input
-	new_velocity += character_up_rotation * mDesiredVelocity;
+	if (player_controls_horizontal_velocity)
+	{
+		// Player input
+		new_velocity += character_up_rotation * mDesiredVelocity;
+	}
+	else
+	{
+		// Preserve horizontal velocity
+		Vec3 current_horizontal_velocity = mCharacter->GetLinearVelocity() - current_vertical_velocity;
+		new_velocity += current_horizontal_velocity;
+	}
 
 	// Update character velocity
 	mCharacter->SetLinearVelocity(new_velocity);