slippery slopes

Now “Slippery Slopes” may sound like a game, but in fact its an issue I’m having currently in a platform game.

The current character controller checks the steepness, but it doesn’t make the character slide down the slope until it reaches a not-so-steep part.

The problem is that I need to move the character in opposite direction of the “steepness”. How do I determin, using the character controller, which direction the player should fall to?

thanks

OnControllerColliderHit provides you with a structure that contains the colliding normal and hit point. You can use that to enable sliding down on steep hills.

http://unity3d.com/Documentation/ScriptReference/CharacterController.OnControllerColliderHit.html

Hi!

I am currently using it to determin the ‘steepness’
but I am not sure if normal.y is in fact the correct steepness.

But the real question: Now I have the normal, how can
I determin the direction for the character to fall to
and not make it ‘stick’ to the mesh?

46696--1703--$untitled_1_163.jpg

function OnControllerColliderHit (hit : ControllerColliderHit)
{
	var angle = Vector3.Angle(hit.normal, Vector3.up);
	if (angle > 20)
	{
		var slideDir = hit.normal;
		slideDir.y = 0;
		slideDir = slideDir.normalized;

		Debug.DrawRay(hit.point, slideDir * 2);			
	}
}

That worked! The implementation was hard, because it can work against you playability wise. Thanks!

Actually i am very interested in the code you wrote to make it work in practice.
When I tried it one of the game play problems is actually how to differentiate small bumps and large slopes. Because based on the slope you can run over a tiny bump and you get pushed back?

Did you find a good way to solve that?

Hi Joachim,

Exactly! That was the problem.
I solved it (partially!) by looking at the moveDirection.y.
If you are jumping it is y>0. Then I simply ignore the ‘bounce back’.

The code got real complicated in logic (lots of if/thens).
I also use a coroutine that does this when bumping:

maywalk = false;
yield new WaitForSeconds(0.5);
maywalk = true;

I can send you the whole (messy) code but it is really specific to this particular
game (not a generic solution).

Is it possible to measure the length of the vertex you are colliding with and only engage the slide motion if the vertex is greater than a certain length?

we solved this by calculating the actual slope angle, and slide direction, and figuring out the component gravity.
It should look roughly like this I think

if(groundSlopeAngle > 45){
slideVal += groundSlopeDir*Time.deltaTime*gravity*Mathf.Sin(groundSlopeAngle*Mathf.Deg2Rad)
}
else{
slideVal = slideVal*.95f;
}
motionDirection = inputMotion;

motionDirection += slideVal;

You can then add this to your normal target position the same way you add gravity.

Over a small ‘bump’ if you run over it, your running speed will overwhelm the effects of sliding. However if you try to run up a hill, you will only make it so far before the cumulative effect of sliding overpowers it.

Add some conditions to determine when you are sliding, and how it falls off.

we solved this by calculating the actual slope angle, and slide direction, and figuring out the component gravity.
It should look roughly like this I think

if(groundSlopeAngle > 45){
slideVal += groundSlopeDir*Time.deltaTime*gravity*Mathf.Sin(groundSlopeAngle*Mathf.Deg2Rad)
}
else{
slideVal = slideVal*.95f;
}
motionDirection = inputMotion;

motionDirection += slideVal;

You can then add this to your normal target position the same way you add gravity.

Over a small ‘bump’ if you run over it, your running speed will overwhelm the effects of sliding. However if you try to run up a hill, you will only make it so far before the cumulative effect of sliding overpowers it.

Add some conditions to determine when you are sliding, and how it falls off.

Here is how we got the angles needed

	void OnControllerColliderHit (ControllerColliderHit hit){
		Vector3 temp = Vector3.Cross(hit.normal, Vector3.down);
		groundSlopeDir = Vector3.Cross(temp, hit.normal);
		groundSlopeAngle =  Vector3.Angle(hit.normal,Vector3.up);
	}

Hey Brian, sorry for posting in an old post, but I am trying to get your example working, but I don’t think I’m implementing it correctly . . .

So im trying to get the function, “OnControllerColliderHit” working, but when I use the code, it gives me these errors:

‘;’ expected. Insert a semicolon at the end.
BCE0043: Unexpected token: )
BCE0044: expecting :, found ‘temp’.

I’m in the process of learning unity, so certain things aren’t as obvious to me yet as they should be, but could you or someone else explain to me the proper way to use this code?

Should I add your code to a script and attach it to the object and it should just go? I’m a little confused.

Wait, nevermind. I figured it out :lol: Thanks for posting the code! I had to tweak it a bit to work with my scene but all is well now. It works great!

No problem. Look for that bit of code appearing in our upcoming iPhone game :).

Hey Fishypants, I know that this post is WAAAAAAYY old by now, but I’m also trying to implement this, and I am getting the same error messages.
Like you (at the time of your post) am relatively new to Unity javascript, and I have been cracking my brain on this.
You wouldn’t happen to remember what your fix was do you?
Error: ‘;’ expected. Insert a semicolon at the end.

and its talking about the line:

Vector3 temp = Vector3.Cross(hit.normal, Vector3.down);

of code:

function OnControllerColliderHit (hit: ControllerColliderHit)
	{
	Vector3 temp = Vector3.Cross(hit.normal, Vector3.down);
    groundSlopeDir = Vector3.Cross(temp, hit.normal);
    groundSlopeAngle =  Vector3.Angle(hit.normal,Vector3.up);
	
	}

Nevermind… Also figured it out

Very cool! I thought I was the only one on the planet that preferred their braces have the same indentation as the code block they go with. Thank you for letting me know I’m not alone! :slight_smile: