- Home /
Forcing a Character Controller to slide down?
Hello, I'm using a Character Controller on my third-person character, which works pretty well, except in one case: When the character steps just beyond the edge of a cliff but the base of the capsule-shaped character controller still touches the edge of the cliff.
The result is the character magically floats in the air instead of falling. Is there a way of "forcing the character down" so that it'll slide and fall even if a tiny part of its controller's base is in contact with something?
Answer by Nervous Nerve · Jan 27, 2013 at 08:31 PM
Bumping, since I'm having the same issue.
I'm thinking it happens because CharacterController is using the CollisionFlags returned by the Move function to determine if it 'isGrounded'. Since the edge is touching the bottom part of the capsule, CollisionFlags.Below is true and therefore we are grounded.
Anyone been able to solve this?
Well I haven't. And yes, I also think it happens because the tiniest part of the character controller is still in contact with something...
I have a similar problem. $$anonymous$$y player model is wider than the other side, so the character controller radius is much bigger in one direction. So the character is always floating, if seen from side, on an edge or cliff. How can we overcome this problem?
I have since come to the conclusion that there is no good solution to this problem that still uses the built-in character controller. Its behavior is hard-coded, and made so that if another collider touches the spherical bottom of its capsule, it decides that it is on ground and will not try to fall any further.
I had some ideas of checking when the $$anonymous$$ove function returns CollisionFlags.Below, and if the point of the collision is far enough from the character's central y-axis, I would call $$anonymous$$ove again with a direction pointing away from the collision. This might work in some cases, but I don't know how you would differentiate between standing on an edge and a slope, and that would probably cause the character to slide down slopes when it shouldn't.
The best thing to do, I think, is to write your own controller from scratch, using a rigidbody and a capsule collider. It may not be the easiest thing to do, but you'll get a lot better control over its behavior.
Thanks for your inquiries, NervousNerve. It seems you put a lot of thoughts into this. How about this: When you detect the collision flags and find out that only an off-center bottom point is in contact with the ground, how about just firing a Physics.Ray down from the capsule's opposite side?
That way, if you don't get any hit on a distance of let's say 50cm, then you'd know for sure that the player is not standing on a slope, but on an edge ins$$anonymous$$d. Does that make sense?
Answer by Polinator · Mar 08, 2013 at 10:35 PM
The messy and dirty way I did something similar to this is that I made triggers of when they are at the edge. You can then AddForce, or MoveForward, or SetVelocity forward just a little bit, so that then the character controller does go off the cliff.
Again, it's dirty but that's what I've used. If there's any other options I'd like to know as well.
Answer by Marsupilami · Sep 30, 2013 at 08:30 AM
If your character controller parent game object has children with colliders (primitive or mesh) they will cause problems with the character controller's ability to handle collision. Try removing colliders from any children.
I spent an hour messing with slope, skin and step offset until I tried removing the collider from my head mesh then adjusting my body collider to also cover the head. Cleared my issue right up and I was able to put my slope, skin and step offsets back to realistic values without any issues. Makes calculating headshots a little more tricky, but I'll probably just replace the character controller with a custom one eventually.
Answer by sadjigfdsigfwk · Jun 11, 2015 at 09:01 AM
Add the following to your code: // Making sure that when the player is not colliding with any object, he is suspended in air must handle aerial movement
bool m_IsColliding;
void OnCollisionStay () {
m_IsColliding = true;
}
void OnCollisionExit () {
m_IsColliding = false;
}
// Inside the Move function replace:
if (m_IsGrounded)
{
HandleGroundedMovement(crouch, jump);
}
else
{
HandleAirborneMovement();
}
// with:
if (m_IsGrounded) {
HandleGroundedMovement (crouch, jump);
}
else if (m_Animator.GetCurrentAnimatorStateInfo (0).IsName ("Grounded") && !m_IsGrounded && m_Animator.GetBool("OnGround") && m_IsColliding) {
m_IsGrounded = true;
}
else
{
HandleAirborneMovement();
}
// replace HandleGroundedMovement function with:
void HandleGroundedMovement(bool crouch, bool jump)
{
// check whether conditions are right to allow a jump:
if (jump && !crouch && m_Animator.GetBool("OnGround") )
{
// jump!
m_Rigidbody.velocity = new Vector3(m_Rigidbody.velocity.x, m_JumpPower, m_Rigidbody.velocity.z);
m_IsGrounded = false;
m_Animator.SetBool("OnGround", m_IsGrounded);
m_Animator.applyRootMotion = false;
m_GroundCheckDistance = 0.1f;
}
}
Hi, once I do the code changes according to your script, player just keep jumping forever, I guess there must be something wrong, somewhere. BTW, Im on Unity 5.1.2 using ethan controller. Regards,
Answer by ndruha · Jan 23, 2021 at 01:32 AM
It's simple to fix with CharacterController:
// Somewhere in your update
if (_controller.isGrounded && IsOnTheEdge()) {
_controller.Move(transform.forward * 2f * Time.deltaTime);
}
...
// Function to check if the character is on the edge
private bool IsOnTheEdge() {
if (Physics.Raycast(transform.position, Vector3.down, out var hit)) {
return !hit.collider.isTrigger && Vector3.Distance(hit.point, transform.position) > 0.2f;
}
return true;
}
Your answer
Follow this Question
Related Questions
Character controller problem 0 Answers
CharacterController gets stuck on stairs. 2 Answers
Character stuck climbing 0 Answers
Starter Asset Capsule gets stuck on corners 0 Answers
Memory Leak Help 2 Answers