[implemented] Suggestion: moveWithCollisions() - option for no sliding

I am encountering an issue that seems fairly common, based on what I’m reading in the forums.

“moveWithCollisions()” handles collisions by projecting the movement vector onto the collided surface, causing sliding along the collided surface. This allows for user-friendly reactions to wall collisions. When “moveWithCollisions()” is used with a gravity velocity vector, and the “ground” surface has any slope, this sliding effect results in sliding down the ground’s slope, at a speed commensurate with the size of the ground’s slope angle.

However, when the object being moved is a character, sliding down the slope is often not what is wanted, especially for slopes beneath a certain angle.

It would be useful to have a version of “moveWithCollisions()” that, rather than sliding, stops the object at the first point of collision. This could be done with an optional flag passed into “moveWithCollisions()” to short-circuit it on the first collision. Alternately, it could be handled with a separate function, perhaps one called “moveWithCollisionsNoSlide()”.

Here’s how such functionality could be used. For the purpose of explanation, I’ll refer to the new functionality as “moveWithCollisionsNoSlide()”:

  1. Call the standard “moveWithCollisions()” for all horizontal movement. If this horizontal movement pushes the object into a slope, the sliding effect of “moveWithCollisions()” will cause the object to move up the slope. If this horizontal movement pushes the object away from a slope, it will not affect the object’s vertical position, causing the object to float above the slope.

  2. Update the gravity velocity vector and pass it into a call to “moveWithCollisionsNoSlide()”. If the object is hovering over a slope, this will cause the object to fall, but not slide down the slope when the object collides with the slope.

If a maximum slope angle was wanted for the above example, then a ray could be cast from the object’s base to determine the normal of the ground beneath it, and thus the angle of the slope. If the angle is big enough, then “moveWithCollisions()” could be called instead of “moveWithCollisionsNoSlide()”, to force sliding down the slope.

While I haven’t yet fully grocked the code of “moveWithCollisions()”, it seems like what I am proposing is simply a matter of short-circuiting the logic at the first collision. This suggests that an optional flag parameter for “moveWithCollisions()” would be the most appropriate.

I can imagine that such functionality could prove useful in situations beyond preventing sliding on slopes, but this particular situation is quite common, and the requested functionality could provide a simple and robust solution. Integrating this into Babylon.js would greatly benefit developers seeking more controlled character interactions with sloped environments without resorting to complex, hacky, or niche workarounds.

1 Like

Yes this is quite a simple change. I’d be happy to review the PR if you want to give it a try

1 Like

I’m working on it…

3 Likes

I’ve put up a pull request here. It has passed all automated checks.

Also, for the record, handling slopes using this feature works as expected (as outlined above). The logic is nice and simple, especially compared to implementations I’ve tried up to now. Once the feature is added to babylon, I’ll replicate my slope handling (and basic character controller handling) logic in the playground.

1 Like

And it is merged!!

Welcome to the family :smiley:

1 Like

Aw thanks! It’s a pleasure.

I’m working on a playground to demo the new feature now. I’ll post it soon.

1 Like

Shoot. I should have considered that the feature wouldn’t be incorporated into the playground yet. I’ve got a playground script near ready to go, but I’ll wait to post it until this feature is propagated.

My impression from a forum search is that it’s likely going to be a while before that happens. However, if anyone has more up-to-date info, then please let me know.

This feature be published in the next week. Maybe Tuesday or Wednesday with a version 8.7.1 or officially Thursday with version 8.8.0.

But nothing prevents you from showing the PG by specifying: as soon as version 8.8 is released, the PG will be functional.

Maybe the documentation can be completed with your PG to here:

2 Likes

@Deltakosh, I just submitted a new pull request here with a fix for an issue I’ve noticed while working with this new feature.

This feature lets you move a mesh up to the first collision and no further. Unfortunately, due to floating point imprecision, this means moving the mesh to either just barely outside, or just barely inside the point of penetrating the other collided mesh (about 50/50). I’ve noticed that when the result is penetration, a subsequent call to moveWithCollision() will immediately snag on the mesh from the prior collision, causing another 50/50 chance for penetration.

The fix in my pull request is for moveWithCollision() to move the mesh to a small distance LESS than the first collision, so that it never penetrates. For a “small distance” I’m using the closeDistance value used elsewhere in the collision system. The distance is imperceptibly small, but the snagging effect now no longer happens.

@Dad72, Yes, once I put up the playground, I can give the documentation a go.

I’ve put up a demo of the character-controller here:

I’ve announced it in this post:

1 Like