Search Unity

CC gets pushed through terrain

Discussion in 'Physics' started by xVergilx, Aug 30, 2019.

  1. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    1,947
    So, I've got an issue: Character controller depenetrates under the terrain (clips it completely) if the collider is pushing it from the above.

    Tweaking terrain collider thickness does nothing.

    I've made vertical depenetration, and it works fine for this case, but completely breaks when moving in close spaces. E.g. when character controller penetrates static geometry and the ray is cast from the insides of it while moving. As a result causing a teleportation on top, which is undesirable.

    Back to original question, does anyone know how to depenetrate (or actually prevent depenetration) for dynamic objects that's crushing character controller towards terrain collider?

    This is what I've tried:

    Code (CSharp):
    1.       private void PostProcessDepenetration() {
    2.          Vector3 centerPos = Position;
    3.          float skinWidth = _characterController.skinWidth;
    4.  
    5.          Vector3 headPos = centerPos;
    6.          headPos.y += _ccHeight * 0.5f + skinWidth;
    7.  
    8.          // In case getting squished, controller needs to stay on top of the geometry,
    9.          // otherwise it may just clip through it
    10.  
    11.          if (Physics.Raycast(headPos,
    12.                              Vector3.down,
    13.                              out RaycastHit geomHit,
    14.                              _ccHeight + skinWidth,
    15.                              Masks.Environment)) {
    16.             // Compute penetration
    17.             Vector3 hitPos = geomHit.point;
    18.  
    19.             Vector3 depenetratedPos = hitPos;
    20.             depenetratedPos.y += skinWidth;
    21.  
    22.             // Pivot is located at the bottom of the CC, don't need to move it towards center
    23.             /*depenetratedPos.y += _ccHeight + skinWidth;
    24.             depenetratedPos -= _characterController.center;*/
    25.  
    26.             _transform.position = depenetratedPos;
    27.          }
    28.       }
     
  2. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    1,947
    So, I've figured that no, it actually resolved correctly.
    I've disabled the depenetration and figured out that the problem is CC being partially clipped into the geometry due to uncrouching.

    Workaround depenetration works, it just caught different case.
     
  3. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    1,964
    Not sure if it's relevant or will help in your case but wanted to highlight the following 3D physics method that may prove useful: Physics.ComputePenetration.
     
  4. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    1,947
    Yeah, it is useful, however, it simply does what actual character controller does already.

    Which is if something pushes controller downwards its probably going to resolve by clipping through downwards, instead of depenetrating in the opposite side (up) or not moving at all (preferrably).

    I don't know if this is a bug, or a feature, however this is true only for the thin colliders, such as terrain collider one.

    Terrain collider is another bag of surprises. Either its thickness is getting ignored, or idk at this point.


    I've managed to workaround this issue so far is by:
    1. Testing if the controller penetrates by casting from highest controller point to lowest.
    2. Testing if the penetration has been caused from above + by dynamic collider (static ones are ignored).
    3. Then, placing controller at the hit point plus some offset.

    Testing is done by using .OnControllerColliderHit(ControllerColliderHit) to track cplliders, and a custom .Static tag on all colliders (fortunately I have an automapper that attaches components to colliders if its static, lacking static property in runtime / build is another issue, but I'm okay with that)).

    Sounds like a lot of work for such simple thing, but its an edge case anyway.


    All this works like a charm (unless I find something that will horribly break this in the future).