Prevent colliders from intersecting and then popping back out on collision

I’m trying to recreate the CharacterController but retain the ability to receive some physics so I’m using a CapsuleCollider + RigidBody. I’ve got nearly everything working, but I ran into an extremely basic problem that there doesn’t seem to be any solution to.

Test Scenario: Rigidbody “character” jumps and lands.
What happens: When the rigidbody hits the ground landing from a jump (it impacts the floor collider), for a brief frame or two the rigidbody penetrates the ground surface, and then immediately pops back up to ground level.
Additional issue: When landing on a hill slope, the rigidbody doesn’t just pop back up but it pops down the hill significantly with each land.

I’ve tried all combinations of max penetration for penalty, bounce settings, rigidbody collision detection modes and interpolation modes, but without fail every time the jarring penetration and pop-out on landing happens.

This will even happen with a very simple default sphere collider + rigidbody. Drop it from a height on play and when it lands you will see it penetrate and pop out of the floor. Is this just expected behavior with rigidbodies? It’s very jarring, especially when used on a player with the camera following him.

Unfortunately this sort of problem seems to be fairly inherent in Unity’s physics implementations.

Reducing Fixed Timestep value will help at a performance cost. I find the default value to be far too slow for any kind of semi-realistic simulation. It may even have to be faster than your target frame rate. Performance will suffer considerably.

I have noticed that the potential for collider penetration is affected quite heavily by the friction values of both materials, for some reason. Try playing with those values, if you are able to.
This combined with reducing bounce values to zero helped me. Friction and Bounce seem to interact with one another as far as collider penetration goes, so try various combinations.

That’s what I was afraid of. Indeed, halving the fixed timestep made a huge difference. I doubt I’ll be able to get away with that because of the huge penalty though as you said :frowning: Though it reduced but didn’t totally solve the problem where jumping in place on a hill slowly pops the character lower and lower each time (even when zeroing the velocity each frame.) Also, my bounce and friction values are already zero.

That’s very unfortunate. I guess its back to the drawing board for my character controller yet again. It’s hard to find a working balance between physics and all its idiosyncrasies and the predictable nature of CharacterController. Frankly, I’m not sure it can really be done without essentially writing your own physics engine to get more control over things.

I just wanted to post an update for anyone who might stumble upon this thread.

So the solution was to reduce the fixed update timestep to 0.01 (100 fps) as dasbin suggested. To help reduce the performance hit some from the now doubled fixed update framerate, I implemented a frame skip system in my FixedUpdate calls so that my game logic that runs in FixedUpdate would only update at 50 fps still, while the physics itself runs at 100 fps. It caused a few minor issues such as all Debug.Draw calls requiring a duration equal to frameSkip * fixedDeltaTime to keep the debug lines lines from flickering. Otherwise it seems to work. Physics will take twice the processing power to handle, but at least I won’t be doing double the raycasting, etc. making the performance hit even worse.

@guavaman

I think the push out action of Rigidbody works in a separated thread controlled by physic engine. I think it is very hard and expensive to produce a predictable push out time by using Rigidbody. I tried this solution a little bit. When I realized that it is hard to get what I want, I gave up.

But I chose to use another solution. That is use Unity Character Controller to do push out only. I mean only use Unity Character Controller’s push out function without using its other unreliable functions like isGrounded. For example, you can attach both a Kinematic Rigidbody and Unity Character Controller to a capsule player. You then move the player in any way you want. After each movement, you call UnityCharacterController.Move(verySmallMoveVector) to trigger a push out action provided by Unity Character Controller.