I want my player to be able to walk up a steep slope. Just using a No Friction physics material is not good enough, he's still getting stuck.
To make the player "stick" to the surface and move smoothly, I want his "forward" vector to match the ground's normal direction.
So a raycast is shot down, determines the ground's normal direction, and sets the player's forward direction based on that.
The difference is that a player moving with transform.forward who runs into a slope, is colliding with the slope and physics pushing him up. On the contrary, I want to move the player in the direction of the ground below him
I see that SetMoveDirectionAsForward() from line 1551 of Char.cs is being called, which is setting the moveDirection to tranform.forward.
Instead, I want to set this to a cross of the ground's normal direction:
if (Physics.Raycast(transform.position + new Vector3(0f, 0.1f, 0f), Vector3.down, out hit, 1f, raycastCollisionMask)) {
forward = Vector3.Cross(transform.right, hit.normal);
}
else {
forward = transform.forward;
}
I can Debug.DrawRay and see the Vector is fine, and matches the slope of the ground. However, when my player walks up a slope, he "Flies" up into the air. I have a hard time understanding how gravity is applied.
I see that in MoveRigidbody() line 1057 Char.cs, a Force is calculated that uses _rigidbody.velocity.y. This is why my character flies into the sky, because the slope gives him a positive velocity and then the CalcForce() function keep sending him up.
Any suggestion how I can implement this "Raycast for ground, and set player's forward vector based on ground's normal" system without sending the player to the sky?
Comments
Unless you have a specific need for a Rigidbody, you do have the option of using a Character Controller component instead of the Rigidbody + Capsule Collider. That features a "Slope limit" field that gives better control over slopes.
The suggestion you've posted might work for your character and scale, but wouldn't be transferrable without introducing a lot more variables that the user has to tweak. The amount of lift may need changing according to the steepness of the slope, or be negative when travelling downwards, etc.
I feel the fine tuning necessary makes this best suited to custom script delegation, IMO, similar to the way inputs can be overridden.
I'll PM you a test package with updated Char/Enum scripts along with a new "CustomController" example script that hooks into an experimental SetMovementDirectionDelegate, which is called automatically whenever the moveDirection is updated. This way, you can tweak the vector as necessary, and return it back, any way you like without having to modify AC's script or rely on a totally custom motion controller.