- Home /
How to make my character stop stuttering when walking down a slope?
Skill Level :kinda new (can understand some basics in unityscript).
I am using a 3rd person character controller for my 2d platformer and i've been having trouble with slopes. The thing is when i walk down a slope that is approximately 24 degrees it is fine and goes down smoothly, but running down the slope makes it stutter. While not changing any animation (because i lack a fall animation) it signifcantly slows down the player than what it should be.
Now I read that maybe using a raycast thing (i haven't used these before) would work by shooting a ray a small distance bellow and if it hits than it will say the player is grounded so it wont stutter. Knowing basic logic i don't think this will work but maybe using the raycast to check the distance bellow the character's feet will?
If there is anyway to make a smooth walk down any or most slopes please help.
Check your colliders. That stutter usually happens when your player's box collider goes "inside" the terrain. Try switching it to mesh or capsule collider.
it is a capsule It seems to act like walking down a stair where when it walks over the edge of one it would fall down first losing its horizontal speed.
This is what I put defaultGravity=0 gravity=20 in the if(controller.isGrounded)
` defaultGravity = -9.81 (gravity); gravity -= 9.81 Time.deltaTime; controller.$$anonymous$$ove( Vector3(transform.postion.x, gravity, transform.postion.z) ); `
Answer by Garth-Smith · Sep 17, 2013 at 05:58 PM
I ran into this problem and Googling for an answer brought up this page. I thought I'd share my answer. The biggest problem I was having is that the player cannot jump mid-air and so would be unable to jump when "hopping" down a slope.
Here is the basic idea:
Apply gravity. In my example, gravity has already been applied.
Run horizontal movement first.
If the player was going to move downward, but not down enough to stick to the slope, then force the player down to just touch the slope.
This means the player will never move completely horizontally off a cliff! But that effect is only for a single frame since I only run this "SafeMove" when walking/running, not when in freefall.
The steepest down slope experienced in our game is a 45 degree angle. If you have shallower or steeper slopes, you will need to change the if statement and what you force the Y movement to be.
/// Walk down slopes safely. Prevents Player from "hopping" down hills.
/// Apply gravity before running this. Should only be used if Player
/// was touching ground on the previous frame.
void SafeMove(Vector2 velocity) {
// X and Z first. We don't want the sloped ground to prevent
// Player from falling enough to touch the ground.
Vector3 displacement;
displacement.x = velocity.x * Time.deltaTime;
displacement.y = 0;
displacement.z = -characterController.transform.position.z;
characterController.Move(displacement);
// Now Y
displacement.y = velocity.y * Time.deltaTime;
// Our steepest down slope is 45 degrees. Force Player to fall at least
// that much so he stays in contact with the ground.
if (-Mathf.Abs(displacement.x) < displacement.y && displacement.y < 0) {
displacement.y = -Mathf.Abs(displacement.x) - 0.001f;
}
displacement.z = 0;
displacement.x = 0;
characterController.Move(displacement);
}
Hey even though this is almost a year old and I haven't worked with Unity for almost the same amount of time, I respect that you still replied to this problem (which I'm not sure is solved or not). I really wish I had the rep to give you a thumbs up, so I guess I'll just have to settle with the checkmark.
Thanks! It seems like this is a problem for everyone who works on 2D platformers has to solve at some point. I figure Google will point some other people to this page. =)
if (-$$anonymous$$athf.Abs(displacement.x) < displacement.y && displacement.y < 0) {
displacement.y = -$$anonymous$$athf.Abs(displacement.x) - 0.001f;
}
This piece of code is what really worked for me. It took some tooling around--but I recommend anyone else follow this path despite others arguing against using a $$anonymous$$ove() function more than once in a single Update.
Some suggestions: -make sure there are the ONLY two $$anonymous$$ove() functions in your update loop
use Time.deltaTime within the move function rather than through individual x/y/z e.g.
characterController.$$anonymous$$ove(displacement * Time.deltaTime);
-----I've found this helps alleviate a lot of problems when controller code starts getting more complex and if you have a couple deltaTime's laying around--it could practically stop your character from moving or cause erratic effects when you start modifying speeds e.g. if my character speed is 20 * deltaTime and later in the loop I change the speed to 10--but forget to add deltaTime--the character will practically teleport when it's supposed to move slower. $$anonymous$$eeping the deltaTime to the $$anonymous$$ove() function helps keep the movement fluidity consistent on all axes and the code logic a little more organized.
--another pitfall I dealt with was keeping "displacement = new Vector3.zero" at the beginning of the update loop to reset values--it worked for old code logic and I've seen some tutorials that do that--if you are doing that, move that code to the Awake() or Start() function and this new code logic should maintain your values for you without any upkeep.
Answer by Loius · Oct 21, 2012 at 04:16 PM
Increase your 'default gravity'.
if ( controller.isGrounded ) gravity = -9.81 * (defaultGravity);
gravity -= 9.81 * Time.deltaTime;
controller.Move( Vector3(x, gravity, z) );
Do you mean increase the default gravity when on the slope or just in general?
You could do it just on the slope but it'd be more work for you. Essentially that's saying "this character should remain glued to the ground unless it slopes by more than defaultGravity*9.81 units per unit." If you keep defaultGravity low enough, the player will never notice the slight hiccup when they walk off a ledge.
I tried putting the code you put in at the top in the controller.isGrounded but I could not move the character and I could not jump. Im pretty sure this is javascript right?
Did you change 'x' and 'z' to the variables you have already, and do you alter 'gravity' to jump? I use that exact code myself, so it works, you just have to adapt it to your script.
This is what i put in for if (controller.isGrounded) default Gravity=0 gravity=20
defaultGravity = -9.81 (gravity); gravity -= 9.81 Time.deltaTime; controller.$$anonymous$$ove( Vector3(transform.postion.x, gravity, transform.postion.z) );
sorry for late reply i thought i already uploaded this but apparently didnt.
Your answer
Follow this Question
Related Questions
Another Double Jump Question 0 Answers
2D Platformer Ai Movement Decision Making Problems 0 Answers
Rigidbody Platform Character Movement 0 Answers
Why do I double jump? This isn't supposed to happen... 2 Answers