Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Capsule collider getting stuck on low objects

Discussion in 'Physics' started by dgoyette, Jan 11, 2019.

  1. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,193
    I'm having an issue where my player is getting stuck on objects that are fairly low to the ground. I'm walking up to a box collider that's 0.2 units tall, which collide's with a portion of the curved part of the player's capsule collider:

    upload_2019-1-10_22-30-27.png

    The result is that I get pretty well stuck on it. I'm using a rigidbody controller, and moving backwards or forwards applies force to the player's rigidbody. When I get "stuck", I can still see that the same amount of force as usual is being applied to the rigidbody, but the player hardly moves. If I keep holding the input for 10-15 seconds, I eventually break free. And I can see the player is moving a very small amount during this time.

    So, I've confirmed I'm still applying plenty of force to the player, the Rigidbody is Continuous Dynamic, and I freeze all rotations. The exact height of the obstacle doesn't seem to matter: pretty much any low object like this causes me to get stuck.

    Does anyone have any suggestions as to what might be causing this to happen?
     
  2. SparrowGS

    SparrowGS

    Joined:
    Apr 6, 2017
    Posts:
    2,536
    Try to fiddle with the variables "shellOffset" and "groundCheckDist" (they might have a slightly different name, i've made so much changes to the built-in controller)

    I had the same issue, the value for me right now are .1 for the shellOffset and .11 for the groundCheckDist.

    take a peek in the code, i think they commented on this variables. (I might have added it and forgot, but i doubt it)

    Code (CSharp):
    1.     [Tooltip("set it to 0.1 or more if you get stuck in wall")]public float shellOffset;
    2.     [SerializeField]float groundCheckDistance = 0.01f; // distance for checking if the controller is grounded ( 0.01f seems to work best for this )
    3.  
    4.  
     
  3. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,193
    Interesting. I'll take a look. I'm using my own character controller, but comparing it to the 'RigidbodyFirstPersonController' from StandardAssets, it does seem I'm doing things pretty similarly.
     
  4. SparrowGS

    SparrowGS

    Joined:
    Apr 6, 2017
    Posts:
    2,536
    I was under the impression you're using the build in one for some reason.
     
  5. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,193
    It doesn't seem very likely that someone else would stumble upon this thread, experiencing the same problem that I was experiencing, but I figured out the problem that was occurring. I haven't decided how to fix it yet, but I at least know what's going on.

    When I test whether the player is "grounded", I use a spherecast instead of a raycast in order to avoid cases where the player can get stuck on a crack between two objects. And I use the raycastHit.normal to inform the controller what the slope is of the surface the player is walking on. This allows me to redirect the force parallel to sloped surfaces if the player is going up or down a slope.

    The problem with my approach is that if the spherecast hits some collider at a weird angle like in the screenshot I showed, the "normal" of the collision is a bit weird. Instead of a normal like (0, 1, 0), pointing up, for flat ground, hitting the edge of the low object results in normals like (-0.8, 0.6, 0). This causes my controller to think the character is walking up a really steep ramp, and reduces the character's movement force significantly.

    So I'll have to rethink the way I get the surface normal to avoid this kind of behavior. But I thought I'd wrap this up by explaining the source of the issue.
     
  6. SparrowGS

    SparrowGS

    Joined:
    Apr 6, 2017
    Posts:
    2,536
    You can compare the angle between the normal and Vector3.up to see if it's above some threshold apply normal force(?)
     
  7. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,193
    That could probably work. Though it would probably mean that at some point the player could still get stuck on some edges if the normal of that edge is just below the threshold.

    My approach to my Ground Check script tried to handle various cases that complicate things. I started with a simple raycast going "down" to see if I hit the floor. That works pretty well, but the problem is if the player walks over a crack in the ground, they're no longer considered grounded.

    So I switched to the spherecast approach, so that if the player is over a crack in the ground, the spherecast will still hit the ground. Great. Until I ran into this issue of getting stuck on small blocks.

    I then tried a hybrid approach: Raycast first, and if that doesn't hit, try the spherecast. That "fixes" the small block problem, as the raycast hits the floor instead of the small block. But now I can't go up ramps very well, because the raycast pointing "down" doesn't hit the ramp until the player is fully over the ramp. As they approach the ramp, the ground normal is still up, so starting forward movement up the ramp is difficult.

    My current approach: Do a very small SphereCast first. This is unlikely to hit any small blocks, but it will hit ramps if I'm right next to them. If the small spherecast fails, because I'm over a crack, do a larger spherecast the radius of the capsule.

    We'll see how long this approach works until I find another shortcoming :)