Advertisement

Character controller pushing through rigid body

Started by May 03, 2021 10:33 PM
3 comments, last by Gnollrunner 3 years, 6 months ago

I decided to experiment a bit with my existing character controller (bullet physics). The way it was prior it was a capsule sliding across the ground which I did a ton of tweaks to to implement things like jumping, crouching, stepping, etc. However for anything more than flat surfaces or ramps sliding a capsule rigid body around on the ground doesn't really cut it (gliding when falling issue since only gravity pulls you down, random stutters when colliding with certain geometry edges, etc).

So after a bit of research and some pondering, I decided to attempt an implementation where a rigid body capsule rides on top of a ray. To my surprise, this works out much better than I was thinking it would. I know there will be a ton of edge cases I'll need to work out, but for just overwriting the capsule's Y origin component with the position of the ray cast hit plus an offset, seems to work pretty well.

With that being said, I was running around my test scene and noticed that I was getting stuck when walking under ramps:

This would appear to be happening because I'm shoving the capsule up every tick even if the amount that I'm shoving it puts it through existing geometry, then bullet attempts to resolve this by pushing it back out, but the amount I'm shoving it back up on the next tick overpowers the amount that bullet is attempting to correct it…then we eventually wind up stuck inside the ramp object.

I'm currently trying to think of a creative way to handle this situation, and wanted to post it to see if any one else had any ideas, or if maybe there's a simple solution that I'm just over thinking?

float distanceBetweenCapsuleOriginAndCapsuleBottom = this->realCapsuleHeight / 2.0f;
float offset = this->getFootYPos() + this->stepHeight;
float newCapsuleOriginY = distanceBetweenCapsuleOriginAndCapsuleBottom + offset;
this->capsuleActor->getRigidBody()->getWorldTransform().getOrigin().setY(newCapsuleOriginY);

// where this->getFootYPos() returns raycast hit Y value

whitwhoa said:
but for just overwriting the capsule's Y origin component with the position of the ray cast hit plus an offset, seems to work pretty well.

If you modify the position of a rigid body, physics engine has no chance to do its job.

It's even a sin to modify velocity, usually.

What you should do is controlling it with external force / torque. This way the engine can solve for velocity respecting contacts or or other constraints.

It's just, remembering my experience with bullet, it jitters still no matter how hard you try : / But maybe at least it does no longer get stuck under the ramp after the change.

Advertisement

JoeJ said:

If you modify the position of a rigid body, physics engine has no chance to do its job.

It's even a sin to modify velocity, usually.

What you should do is controlling it with external force / torque. This way the engine can solve for velocity respecting contacts or or other constraints.

It's just, remembering my experience with bullet, it jitters still no matter how hard you try : / But maybe at least it does no longer get stuck under the ramp after the change.

That makes total sense! Thank you. I'll give that a go and see where I land ?

I've never played with an actual physics engine, however If I remember right most physics engines try to move and then correct their position when they find you are passing though something (someone correctly me if I'm wrong on this).

Alternatively you can also do the basic sweep sphere algorithm which can be extended to be a pill. When you sweep the sphere it guarantees it never enters any geometry so you don't have to worry about any corrections. Also it doesn't matter how fast you are going, You will never pass though thin walls or anything because it's looking for collisions before you get to them. I believe the down side is it's not suitable for general physics but for a character capsule it's perfect. It's also a bit more CPU intensive but this may not be a problem if you are working on something with a single player and in any case with modern CPUs it's not bad.

I implemented this in C++ some years back and it worked great. I could slide over any random procedurally generated geometry and push up steep mountains. One thing I discovered is you have to check for double plane collisions or you do get this situation where one plane is pushing you into another, while the other is pushing you back into the first. What I ended up doing is taking the cross product of every pair of collisions touching the pill. Then you pick the best one that matches the direction you are trying to go (using a dot product) and use that one for your response path. The normal case is there is only one touching plane, line or point. In that case you just do the standard response. After I got all this working there was no jittering and everything was smooth as glass. I believe this is how most games handle player character movement, at least before physics engines became popular.

This topic is closed to new replies.

Advertisement