- Home /
Moving Character Down a Ramp
I'm having this odd problem with my side-scroller game.
I'm using CharacterController and I have a 20degree ramp made of a plane. When I move down the ramp my character "bumps" down as if he's going down stairs. When I go up the ramp everything is fine. The problem is that while he is "bumping" he loses ground contact and loses the ability to jump. If I increase the gravity substantially (from 30 to 150) the bumping goes away, but I need the lower gravity for my gameplay.
Any work arounds you can think of?
Answer by Matthew Gatland · May 10, 2013 at 04:12 AM
Here's what I do.
This makes the CharacterController 'snap' down onto the ground when they are just above it.
I use this in the Update() method on a script that's attached to the CharacterController object.
CharacterController controller = GetComponent<CharacterController>();
float snapDistance = 1.1f; //Adjust this based on the CharacterController's height and the slopes you want to handle - my CharacterController's height is 1.8
RaycastHit hitInfo = new RaycastHit();
if (Physics.Raycast(new Ray(transform.position, Vector3.down), out hitInfo, snapDistance)) {
isGrounded = true;
transform.position = hitInfo.point;
transform.position = new Vector3(hitInfo.point.x, hitInfo.point.y + controller.height / 2, hitInfo.point.z);
} else {
isGrounded = false;
}
I keep an isGrounded variable to keep track of whether the character was snapped to the ground or not - I use this instead of the normal controller.isGrounded for controlling animations and whether or not the character may jump.
Beautiful, thanks!
I've modified it a bit so that you can continue to use the Character Controller's isGrounded flag. If the Controller says it is not grounded, I cast the ray using the snap distance. I then use the Character Controller's $$anonymous$$ove() function to move towards the Ray collision. The $$anonymous$$ove() command will physically move the controller, stopping when it collides. That also updates the built in isGrounded variable.
float snapDistance = 0.4f;
if (_controller.isGrounded == false)
{
RaycastHit hitInfo = new RaycastHit();
if (Physics.Raycast(new Ray(transform.position, Vector3.down), out hitInfo, snapDistance))
_controller.$$anonymous$$ove(hitInfo.point - transform.position);
}
Of course anyone implementing this code will want to create some temporary variables in the class and reuse those ins$$anonymous$$d of using new.
Hi, thanks a lot for your tip, it worked!! i came up with the same conclusion, but i was chaging the transform.position it worked, the character stays grounded, but its look extremely chpppy, but this works smooth, thanks!
Answer by Clunk · May 29, 2012 at 11:54 PM
Sounds like maybe you have a box collider / rigidbody character? Try using a CharacterContoller instead, and adjust the slope limit. If you insist on a rigidbody, try using a capsule collider, and adjust the angular drag so he doesn't fall over. You can also use rigidbody constraints. You could also increase the ray distance, if you are using a raycast to detect if the player is grounded. So if you have, persay, Physics.Raycast(transform.position, down, hit, 1), try (Physics.Raycast(transform.position, down, hit, 5)... Of course experiment with amounts. Hope this helps. If it doesn't, you should post your code so I can check it out and go from there.
I'm using CharacterController
Its also using a Capsule Collider. I'm not using Physics Raycast. $$anonymous$$y movement script is fairly simple:
CharacterController controller = GetComponent<CharacterController>();
if (pOverride == false){
moveDirection.x = Input.GetAxis("Horizontal") * speed;
moveDirection.y -= gravity * Time.deltaTime;
if (controller.isGrounded){
moveDirection.y = -gravity * Time.deltaTime;
if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.Space)){
StartCoroutine(Jump());
}
}
controller.$$anonymous$$ove(moveDirection * Time.deltaTime);
}
Answer by badiba · Dec 13, 2018 at 11:43 AM
Hey, it's a very old post but I thought I could help people who encounter this problem.
If your "Game Object" has "Rigidbody" component and behaves abnormally, you should probably check your script to see if you are changing the values of "velocity" or "transform.position".
Note that if you want "Physics" to work perfectly you should always work with "AddForce". (Or ignore AddForce completely and find other ways to implement a solution. There are very cool tools to use in Unity. Such as Vector2.Lerp/Vector3.Lerp, Vector2.MoveTowards/Vector3.MoveTowards. See documents.)
Your answer
Follow this Question
Related Questions
Let Character Controller jump. 0 Answers
Let Character Controller jump. 1 Answer
Prioritizing Player Animations 0 Answers
Click on an object and then edit the speed of my player? 1 Answer
Character Flying around uncontrollably 2 Answers