- Home /
3D Character Controller slowing down the higher the slope angle (both up and down)
Hi everyone :) I am trying to make a 3D character controller but ran into an issue where my player would slow down going up slopes and would bounce going down. I have come up with a solution I was happy with but it seems to slow down the player any time they move up or down a slope. Basically, rather than driving my player towards transform.forward, I am getting the forward direction based on the current ground normal.
forwardDir = Vector3.ProjectOnPlane(transform.forward, groundNormal);
if (rayGrounded)
{
targetSpeed = (((isRunning) ? runSpeed : walkSpeed) * inputDir.magnitude);
currentSpeed = Mathf.SmoothDamp(currentSpeed, targetSpeed, ref speedSmoothVelocity, GetModifiedSmoothTime(speedSmoothTime));
velocityY += Time.deltaTime * gravity;
velocity = ((forwardDir) * currentSpeed) + (Vector3.up * velocityY) + dashVelocity;
}
else
{
targetSpeed = (((isRunning) ? runSpeed : walkSpeed) * inputDir.magnitude);
currentSpeed = Mathf.SmoothDamp(currentSpeed, targetSpeed, ref speedSmoothVelocity, GetModifiedSmoothTime(speedSmoothTime));
velocityY += Time.deltaTime * gravity;
velocity = ((forwardDir) * currentSpeed) + (Vector3.up * velocityY) + dashVelocity;
}
playerController.Move((velocity * Time.deltaTime));
Any help would be appreciated! This issue has been bugging me all day and im sure its a simple fix.
Answer by Bunny83 · Jan 11, 2020 at 11:35 PM
The method ProjectOnPlane does not rotate the given vector parallel to the plane but project it onto the plane:
As you can see the steeper the angle the shorter the projected vector. Think about the shadow of a pole with light coming parallel from the normal direction. If the "pole" points in the same direction as the normal the shadow would completely disappear. If the pole is parallel to the plane the projected shadow will have the same length as the pole. What you get from ProjectOnPlane is the read arrow. What you probably want is the green arrow. The green arrow has the same length as the blue arrow.
All you have to do to get the green arrow is to normalize your projected vector.
forwardDir = Vector3.ProjectOnPlane(transform.forward, groundNormal).normalized;
Hey! Thanks for the reply. That makes a lot of sense, but I still cant seem to fix the issue im having. I tried your fix and the result is the same, is there anything else that may be an issue?
Actually, now that I think about it, the issue could have something to do with the fact that im setting my Y velocity to be -0.1f every frame if the player is grounded. If the normal is titled more towards the Y axis, the player is slowed down. What can I do to combat this, while still maintaining my gravity?
Im not actually sure if this is the issue now. I have tried troubleshooting this problem for a while today with no results. Any idea what I could be doing wrong? I just wanted my player to move based on the ground normal to avoid bouncing and losing velocity but this seems to be causing more issues than before :L