[SOLVED] CharacterController sliding up hills when jumping

This isn’t a question but rather a tip in case anyone had the same problem as me.

It seems the CharacterController doesn’t think it’s grounded if it detects a collision where the moveDirection.y < 0…
It kind of makes sense, until you see that moveDirection.y=0 even when you collide with a gentle incline, not just when you bump into a vertical wall. One of the results is that if you allow the character to accelerate while in the air (like during a jump) you could climb inclines without being grounded… which means if any other scripts depend on grounded, like the locomotion system for example, they wont function. You end up with your character sliding around your terrain!

The CharacterMotor script doesn’t help any, because it seems to be using the exact same or a very similar test to see if you are grounded. I determined this by just watching the CharacterMotor.grounded property and the CharacterController.isGrounded property which indeed seemed to be always in-sync.

Here is the offending code in the CharacterMotor script:

function OnControllerColliderHit (hit : ControllerColliderHit) {
	[B]if (hit.normal.y > 0  hit.normal.y > groundNormal.y  [I]hit.moveDirection.y < 0[/I]) {[/B]
		if ((hit.point - movement.lastHitPoint).sqrMagnitude > 0.001 || lastGroundNormal == Vector3.zero)
			groundNormal = hit.normal;
		else
			groundNormal = lastGroundNormal;
		
		movingPlatform.hitPlatform = hit.collider.transform;
		movement.hitPoint = hit.point;
		movement.frameVelocity = Vector3.zero;
	}
}

The solution to this problem turned out to be replacing that bolded if statement above with this:

if (hit.normal.y > 0f  hit.normal.y > groundNormal.y  [B](hit.moveDirection.y < 0f || (hit.moveDirection.y == 0f  hit.normal.y > (1-Mathf.Cos(Mathf.Deg2Rad*controller.slopeLimit))))[/B])

hit.moveDirection.y == 0 it means that either we hit a wall while we were falling/jumping, or possibly we just hit some slope which we could climb up. To tell the difference we measure the hit.normal.y against our controller.slopeLimit. The result is that if the point we landed on is too steep for us to walk on, we dont get grounded. No more slipping!

Thanks for this fix, I’ve been wondering about the behaviour you describe too. Another thing I also need to find out is how to get entirely rid of the possibility to cheat by jumping up too steep surfaces using the auto repeat of the space bar. Jumping shouldn’t be allowed when sliding. Your fix partially corrects this side effect, but there’s something still in the original script which still triggers it occasionally.