- Home /
Grounded state problems when sliding
Dear all,
I got a problem with grounded state. I'am using a charater controller with the "isGrounded" feature.
In my game the controller have to slide along a slope (slope can down and up).
= > When i am in "air" i apply a gravity value. When grounded gravity.y = 0 (Lerped from -9.8 to 0 to avoid bouncyness on character controller).
The problem is that my grounded state swing between true and false even if visually the character controller is sliding on floor.
So character controller can't jump. I tried to use raycast instead of "isGrounded"'s character controller method. It's quite better for controlling the grounded state.
Here is my script with raycast:
public class Capsule_3 : MonoBehaviour {
protected Vector3 _gravity = Vector3.zero;//-9.8f /3;
protected Vector3 _dir = Vector3.zero;
protected Vector3 _jump = Vector3.zero;
protected Vector3 GRAVITY = new Vector3(0, -9.81f, 0);
protected Vector3 velocity = Vector3.zero;
protected CollisionFlags collisionFlags;
protected CharacterController controller;
protected RaycastHit hit;
protected float amountOfMotion = 0.0f;
protected bool grounded;
void Awake () {
// Getting CharacterController
controller = GetComponent<CharacterController>();
}
void Start () {
}
void Update () {
InputListener ();
handleDirection ();
handleJump ();
handleGravity ();
Vector3 vectorSum = _gravity +
_dir +
_jump;
collisionFlags = controller.Move(vectorSum * Time.deltaTime);
}
void handleGravity () {
if (isGrounded()) {
_gravity = Vector3.SmoothDamp(_gravity, Vector3.zero, ref velocity, 0.5f); // Gradually reduce gravity overtime: avoid character controller boucyness
} else {
_gravity = _gravity + GRAVITY * Time.deltaTime;
}
}
void handleDirection () {
Vector3 rayDir = -Vector3.up * 5;
float slopeAngle = 0;
float slopeSign = 0;
Vector3 orthogonalizedNormal = Vector3.zero;
if (Physics.Raycast(transform.position, rayDir, out hit)) {
slopeAngle = (Vector3.Angle(Vector3.up, hit.normal)); // Retreive the slope angle
slopeSign = Mathf.Sign(hit.normal.z) * -1;
orthogonalizedNormal = Quaternion.Euler(90, 0, 0) * hit.normal;
if(hit.distance > 1.2f) {
grounded = false;
} else {
grounded = true;
}
}
if(isGrounded()){
float variationToApplyFromSlope = GRAVITY.y * Mathf.Cos(slopeAngle * Mathf.Deg2Rad) * slopeSign * Time.deltaTime;
amountOfMotion = amountOfMotion + variationToApplyFromSlope;
_dir = orthogonalizedNormal * amountOfMotion; // On prend la direction de l'orthogonale à la surface
}
_dir = transform.TransformDirection(_dir); // Convert local to world space
}
void handleJump () {
if(_jump.y > 0 && isGrounded()) {
_jump = _jump + GRAVITY * Time.deltaTime;
}
}
void InputListener() {
if (Input.GetKeyUp("space"))
{
_jump = Vector3.up * -2.0f * GRAVITY.y;
}
}
public bool isGrounded () {
return grounded;
//return (collisionFlags & CollisionFlags.CollidedBelow) != 0;
}
}
As you can see the direction where to go is orthogonalized (90 degree) with the normal of the surface. I have done that to have my character controller sticked on the slope (and avoid bouncyness effect when direction is z+ and y-).
However my character must not stick to the slope when there is a jump. it's easy to do that with character controller (isGrounded function), but with raycast it is not accurate.
My problem is that i need "isGrounded" function from character controller to be able to handle jumps on the slope correctly but this function is not accurate on ground state.
That's the opposite for raycasting...
I need the cons of the two... Or maybe i am on wrong way and there is another solution... :s
Thanks for your support,
Cheers !
Your answer
![](https://koobas.hobune.stream/wayback/20220613020218im_/https://answers.unity.com/themes/thub/images/avi.jpg)