Rigidbody FPS Controller using hit.normal problem

Hello Unity users, I’m making an FPS so I would like to achieve the best FPS controller that handles smooth slopes limit, anti-slope sliding, ect… So I wrote this script : (see gifs below)
using UnityEngine;
using System.Collections;

[RequireComponent (typeof (Rigidbody))]
public class Player_Movement: MonoBehaviour {
	[Header("Components")]
	public Rigidbody rb;
	[Header("Stats")]
	public float speed;
	public float runFactor;
	public bool grounded;
	[Header("Offsets")]
	public LayerMask layers;
	public float speedScale;
	[Header("Run-Time values")]
	public Vector2 rawAxis;
	public Vector3 normalizedAxis;
	public Vector3 smoothedAxis;
	public Vector3 localAxis;
	RaycastHit hit;
	public Vector3 force;


	void Start (){
		
	}

	void Update (){
		rawAxis = new Vector2 (Input.GetAxisRaw ("Horizontal"), Input.GetAxisRaw ("Vertical"));
		normalizedAxis = new Vector3 (rawAxis.x, 0f, rawAxis.y).normalized;
		smoothedAxis = new Vector3 (Mathf.SmoothStep (smoothedAxis.x, normalizedAxis.x, Time.deltaTime * 15f), 0f, Mathf.SmoothStep (smoothedAxis.z, normalizedAxis.z, Time.deltaTime * 15f));
		localAxis = transform.TransformDirection (smoothedAxis);
	}

	void FixedUpdate () {
		float totalSpeed = speed * speedScale;

		var draggedVel = Vector3.zero;
		draggedVel.x = rb.velocity.x * 0.75f;
		draggedVel.y = rb.velocity.y;
		draggedVel.z = rb.velocity.z * 0.75f;

		rb.velocity = draggedVel;

		Debug.DrawRay (transform.position, Vector3.down * 1f);
		if(Physics.Raycast(transform.position, Vector3.down, out hit, 100f, layers)){
			Debug.DrawRay (hit.point, hit.normal * 0.5f, Color.magenta, 2f);
		}

		force = Vector3.Cross (Vector3.Cross (hit.normal, localAxis), hit.normal) * totalSpeed;

		rb.AddForce (force, ForceMode.VelocityChange);
	}

	void OnDrawGizmos(){
		Gizmos.color = Color.green;
		Gizmos.DrawSphere (hit.point + force, 0.3f);
	}
}

When I’m walking down slopes, it’s working like a charm, but I go up a slope it’s doing a weird thing, and I don’t know why.
If you don't see me right click on me then press open in another tab
If you don't see me right click on me then press open in another tab_
The green sphere is the result of “hit.point + force”.

If someone could help me it would be appreciable,
yours sincerely,
Tom.

I tested it in my Unity and fixed it.

The problem is actually a subtle one. Your math is fine (I think – I replaced the vector triple product with a quaternion.fromtorotation), your work is fine. Your mistake is subtle – your force vector is a global variable, and so is your raycasthit.

As you move up a slope, any time when your rigidbody loses connection with the terrain (This will happen CONSTANTLY, because of computational errors) , you just keep applying that force. You keep applying the same force vector again and again forever, causing your character to fly in the direction of the last force vector it had when it lost contact with the ground.

Making the problem worse, is the choice of 100f as a raycast distance, causing your raycast to keep updating as if you were still on the ground. I cannot think of a good reason to have a raycast to get a floor normal be greater than your character’s height.

To fix it, I did the following:

Defined a boolean airborne, defaulted to false.
In FixedUpdate(), only add a force to the rigidbody if airborne is false. Also, set the raycasthit to 2f.
Added the following below FixedUpdate():

void OnCollisionEnter(Collision asdf)
{
	airborne = false;
}

void OnCollisionEnd(Collision asdf)
{
	airborne = true;
}

This causes the rigidbody to stop applying a force, so the player moves up the slope just fine.

Word of warning: You are going down a dark path with a rigid body character controller. The Unity character controller can be extended to work with most games. If you MUST use a rigid body character controller (I had to make one because, and only because, my game is set on a space station and gravity is not a constant, but changes based on position), be wary. First, your method of dealing with slopes works great for terrain, but test it on hard edges (e.g ramps) before you get too excited. Second… steps. Steps. With rigid bodies. Should be easy, right?

Welcome to hell.