I have this first person movement script that I have been using for a while and I’ve just discovered an issue that I can’t seem to find a fix for.
When I set the CharacterControllers skin width to 0.1 the player doesn’t bounce down slopes which is what I want, but if I set the skinwidth to 0.1 gravity when falling off of slopes is extremely fast. Setting the skinwidth to 0.01 stops the gravity issue but the player starts bouncing down slopes again.
Is their anything in my script that I can do to prevent this?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[Header("Assignables")]
public CharacterController controller;
public Transform GroundCheck;
public LayerMask GroundMask;
[Header("Movement")]
public float WalkSpeed = 0f;
public float RunSpeed = 0f;
public bool IsSprinting = false;
public bool CanSprint = true;
float PlayerSpeed;
[Header("Gravity")]
public float gravity = -9.81f;
public float GroundDistance = 0.4f;
Vector3 velocity;
bool isGrounded;
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.LeftShift) && Input.GetKey(KeyCode.W) && CanSprint || Input.GetKey(KeyCode.LeftShift) && Input.GetKey(KeyCode.A) && CanSprint || Input.GetKey(KeyCode.LeftShift) && Input.GetKey(KeyCode.S) && CanSprint || Input.GetKey(KeyCode.LeftShift) && Input.GetKey(KeyCode.D) && CanSprint)
{
PlayerSpeed = RunSpeed;
IsSprinting = true;
}
else
{
PlayerSpeed = WalkSpeed;
IsSprinting = false;
}
isGrounded = Physics.CheckSphere(GroundCheck.position, GroundDistance, GroundMask);
if (isGrounded)
{
// Only reset the vertical velocity if the player is grounded
velocity.y = -2f;
}
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
Vector3 move = transform.right * x + transform.forward * z;
if (move.magnitude > 1)
move /= move.magnitude;
// Adjust velocity for slopes
velocity = AdjustVelocityToSlope(velocity, move);
// Finally, apply gravity
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
private Vector3 AdjustVelocityToSlope(Vector3 velocity, Vector3 moveDirection)
{
var slopeRay = new Ray(transform.position, Vector3.down);
if (Physics.Raycast(slopeRay, out RaycastHit hitInfo, GroundDistance + 0.1f, GroundMask))
{
// Calculate the slope angle
float slopeAngle = Vector3.Angle(hitInfo.normal, Vector3.up);
if (slopeAngle > controller.slopeLimit)
{
// Calculate the slope adjustment to the movement
Vector3 slopeDirection = Vector3.Cross(Vector3.Cross(Vector3.up, hitInfo.normal), hitInfo.normal).normalized;
moveDirection = Quaternion.FromToRotation(moveDirection, slopeDirection) * moveDirection;
// Apply slope velocity to counteract gravity
float slopeVelocity = Mathf.Tan(Mathf.Deg2Rad * slopeAngle) * PlayerSpeed;
velocity.y = -slopeVelocity;
}
}
return moveDirection * PlayerSpeed + Vector3.up * velocity.y;
}
}