Problem with Rigidbody control script! (collision with perpendicular walls problem)

HI,
Im using the FPS walker script to control my character in my project right now but I am having a problem with the collision check for grounded boolean variable. When the character is touch both a perpindicular wall and the ground, he has the ability to stick, as if he were grounded, and if i attempt to jump while touching the wall, he will jump 3-4 times higher. Any insight into this problem would be greatly appreciated!
Here is the Script:

using UnityEngine;
using System.Collections;

[RequireComponent (typeof (Rigidbody))]
[RequireComponent (typeof (CapsuleCollider))]

public class rigidBodyController : MonoBehaviour {

public float speed = 10.0f;
public float gravity = 10.0f;
public float maxVelocityChange = 10.0f;
public bool canJump = true;
public float jumpHeight = 2.0f;
private bool grounded = false;



void Awake () {
    rigidbody.freezeRotation = true;
    rigidbody.useGravity = false;
}

void FixedUpdate () {
    if (grounded) {
        // Calculate how fast we should be moving
        Vector3 targetVelocity = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
        targetVelocity = transform.TransformDirection(targetVelocity);
        targetVelocity *= speed;

        // Apply a force that attempts to reach our target velocity
        Vector3 velocity = rigidbody.velocity;
        Vector3 velocityChange = (targetVelocity - velocity);
        velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
        velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
        velocityChange.y = 0;
        rigidbody.AddForce(velocityChange, ForceMode.VelocityChange);

        // Jump
        if (canJump && Input.GetButton("Jump")) {
            rigidbody.velocity = new Vector3(velocity.x, CalculateJumpVerticalSpeed(), velocity.z);
        }
    }

    // We apply gravity manually for more tuning control
    rigidbody.AddForce(new Vector3 (0, -gravity * rigidbody.mass, 0));

    grounded = false;
}

void OnCollisionStay () {
    grounded = true;    
}

float CalculateJumpVerticalSpeed () {
    // From the jump height and gravity we deduce the upwards speed 
    // for the character to reach at the apex.
    return Mathf.Sqrt(2 * jumpHeight * gravity);
}

}

How you solve this problem will depend on your game. Your problem is here:

void OnCollisionStay () {
    grounded = true;    
}

Your code assumes that you are grounded if you are colliding with anything…that includes walls. So you are going to have to be more discriminating. If walls are your only problem (and if they are tagged as ‘Wall’), you could do something like this:

void OnCollisionStay(Collision collision) {
   if (collision.collider != 'Wall')
      grounded = true;
}

Other ideas:

  • if you game lives on a plane, you could also check the ‘Y’ height of your character.
  • You could compare the normal of the contact points with Vector3.up and only set ‘grounded = true’ if the angle between all the contacts and up is within a threshold.
  • You could cast a ray down to see how far it is to the surface and only set ‘grounded = true’ if the distance is below some threshold.