Sticking to walls whilst jumping (BetterCharacterControl)

Hey, So I’m in a situation where my character control needs to have long, low gravity style jumps, whilst also retaining the ability to move from left to right in mid-air. Whilst jumping and moving either right or left into the side of one of the blocks that makes up my world, the character sticks to the side of the block, instead of falling downwards like I want him to, until the left or right arrow key is released. This changes the game mechanic in a somewhat significant way, does anybody know of a solution? I left an image to demonstrate what I am talking about, I am not great at explanations.

So, physically this makes sense.

Imagine you have a jet pack strapped to your back that lets you move in mid air while jumping. (ie: this is what allows your character to move during jumps)

Now imagine you jump against a wall with your jetpack fully on into the wall. Friction will keep you there as long as the jetpack is running.

…and that’s what is happening here, too. Friction of being rammed into the wall is preventing the character from falling. You can either detect this case and disengage the jetpack… or find a way to turn off friction (I have no idea as I’ve never used bullet).

2 Likes

As Paul said, it’s 'cause the force is constantly being applied, so we need to keep that force from being applied when something is in front of it… I would suggest doing a sweep test of your capsule collision shape forward; if it doesn’t collide, apply the force; if it does, don’t apply the force, or lower the force.
Just do a modified form of this code for your character controller (called during the physics tick)(canForward is a bool that states whether you can forward):

[java]protected void checkInFront() {
TempVars vars = TempVars.get();
Vector3f loc = vars.vect1;
Vector3f dirVector = vars.vect2;
loc.set(location).addLocal(localUp);
dirVector.set(location).addLocal(localForward);
List<PhysicsSweepTestResult> results = space.sweepTest(getSweepShape(), new Transform(loc), new Transform(dirVector));
vars.release();

    for (PhysicsSweepTestResult physicsSweepTestResult : results) {
        if (!physicsSweepTestResult.getCollisionObject().equals(rigidBody)&amp;&amp;physicsSweepTestResult.getCollisionObject()instanceof RigidBodyControl) {
            canForward = false;
            return;
        }
    }

    canForward = true;
}[/java]
@nomnom said: As Paul said, it's 'cause the force is constantly being applied, so we need to keep that force from being applied when something is in front of it.... I would suggest doing a sweep test of your capsule collision shape forward; if it doesn't collide, apply the force; if it does, don't apply the force, or lower the force. Just do a modified form of this code for your character controller (called during the physics tick)(canForward is a bool that states whether you can forward):

[java]protected void checkInFront() {
TempVars vars = TempVars.get();
Vector3f loc = vars.vect1;
Vector3f dirVector = vars.vect2;
loc.set(location).addLocal(localUp);
dirVector.set(location).addLocal(localForward);
List<PhysicsSweepTestResult> results = space.sweepTest(getSweepShape(), new Transform(loc), new Transform(dirVector));
vars.release();

    for (PhysicsSweepTestResult physicsSweepTestResult : results) {
        if (!physicsSweepTestResult.getCollisionObject().equals(rigidBody)&amp;&amp;physicsSweepTestResult.getCollisionObject()instanceof RigidBodyControl) {
            canForward = false;
            return;
        }
    }

    canForward = true;
}[/java]</blockquote>

Thanks, but you can’t do a sweep test with BetterCharacterControl’s mesh shape unfortunately as it is not a convex shape. I’m sure I will find some other way though.

EDIT: I’ve been messing around with an extended version of BetterCharacterControl and I’m seeing good signs, there may be hope yet, thanks for the idea/code !

@javagame said: Thanks, but you can't do a sweep test with BetterCharacterControl's mesh shape unfortunately as it is not a convex shape. I'm sure I will find some other way though.

Yeah, you’re right; I think I just used a cylinder shape or something; one of the defaults…

Way simpler:

setFriction(0) while no ground contact
setFriction(nromalValue) as soona s ground contact is reestablished.

protected boolean onGround = false;
is probably your friend.

5 Likes
@Empire Phoenix said: Way simpler:

setFriction(0) while no ground contact
setFriction(nromalValue) as soona s ground contact is reestablished.

protected boolean onGround = false;
is probably your friend.

setFriction? On what class is that method?

PhysicsRigidBody
one is embedded into the BetterCharacterControll.

(You probably need to extend and add a getter for it)

1 Like
@Empire Phoenix said: PhysicsRigidBody one is embedded into the BetterCharacterControll.

(You probably need to extend and add a getter for it)

Thank you! I’ve been messing around with rays for a while now, your version is so much cleaner with about a 1/100th of the code :slight_smile: