CharacterController jump catching on nearby boxes

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Vanit
Posts: 6
Joined: Tue Jan 03, 2017 11:56 pm

CharacterController jump catching on nearby boxes

Post by Vanit »

I love bepuphysics and thus far have scraped by mining the forums for answers to most of my questions, but I think I finally need to ask a question of my own. :)

I'm creating a 3D platforming game using the SphereCharacterController (modified into a CylinderCharacterController actually, but regular SphereCharacterController has the same issue). The game world consists of many boxes stacked on eachother, not unlike Minecraft, where each box is 1x1x1, and the character is a bit smaller than that (h=0.6, r=0.4). The problem I'm having is that when the controller stands right next to a perfect stack of boxes and jumps, it seems to hit the bottom edge of the second box in the stack and then is bounced away from the stack. I'd like to get to the state where the controller can jump in this position and just go straight up.

For reference I'm using the 1.5.0 binaries.
Vanit
Posts: 6
Joined: Tue Jan 03, 2017 11:56 pm

Re: CharacterController jump catching on nearby boxes

Post by Vanit »

Was reading through some other posts and found mention of CollisionDetectionSettings.AllowedPenetration. I tried setting it to 0.001f, which seems to have helped a lot, but the controller is still being nudged away slightly and lowering AllowedPenetration further doesn't seem to affect that.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: CharacterController jump catching on nearby boxes

Post by Norbo »

That does sound like the character is hitting surface-internal boundaries. To confirm, does the 'bump' happen if the character walks into the wall, stops and waits for any depenetration to occur, and then jumps? If it does, it might be something else. For now, I'll assume it is just hitting internal edges:

This is a pretty hard problem to fully solve when dealing with a bunch of isolated objects. Any amount of penetration can cause a detected contact normal at a boundary to no longer align with the continuous surface's normal, and the engine has no way of correcting the normal since it's not aware of the continuous surface.

In meshes, this is addressed by using the index array as connectivity information. Contacts whose normals are 'blocked' by connected geometry are corrected or dropped.

Something conceptually similar could be created for a voxel grid custom collidable. Contacts on an edge which is known to be shared with another box would have their normals clamped to the unblocked region, which for an internal box-box edge would just be the continuous surface's normal. Since a contact can only stop motion along the normal, the character would smoothly slide along the surface.

Such an implementation would touch some of the grossest parts of the engine, though. It wouldn't be fun to add. It might be easier to instead create a mesh with the appropriate connectivity information to provide smooth borders.

Increasing the collision margin on the character might reduce the effect a little bit too. It'll still be there (as you saw with the SphereCharacterController), but the detected normal will tend to be closer to the continuous one for shallow penetration due to the rounded shape.

As always, the v2 side of things:
1) There won't be any more 'allowed penetration'- all collisions try to resolve to 0 penetration. Collision softness can still result in some remaining penetration if it's being pushed into collision, though.
2) All objects use speculative contacts for cheap small scale CCD, and explicit CCD is quite a bit more robust. Penetration caused by discrete motion will tend to be much reduced.
3) Creating custom collidables will be... different. Less unnecessary grossness in the API design, but potentially more necessary grossness. Hopefully it will be easier on balance.

This is a problem I would really like to solve in a general way- it would be great to have something that would work for compounds composed of arbitrary convexes. I just have no idea how to do it in a budget of ~100 nanoseconds (yet).
Vanit
Posts: 6
Joined: Tue Jan 03, 2017 11:56 pm

Re: CharacterController jump catching on nearby boxes

Post by Vanit »

Thanks for the thorough reply Norbo, much appreciated!

Firstly I can confirm the bump happens when the character walks up to the stack and waits before jumping, so hopefully that opens up some other solutions.

Your comment about continuous surfaces has given me the idea that I might be able to solve this simply by negotiating continuous stacks into a single physics box, as my levels are pretty static and being generated from a 3D array. Although I'm still keen on what can be done to help cases where I do need to stack dynamic entities (i.e. a moving box that's at rest).
It might be easier to instead create a mesh with the appropriate connectivity information to provide smooth borders.
Total beginner so would appreciate some guidance if this is easy-ish. Is this something can be done at run time? Sounds similar to what I was thinking with consolidating the stacks?
Increasing the collision margin on the character might reduce the effect a little bit too.
Where exactly is that? Had a quick look in the controller and couldn't see anything.
Vanit
Posts: 6
Joined: Tue Jan 03, 2017 11:56 pm

Re: CharacterController jump catching on nearby boxes

Post by Vanit »

Well this is interesting. I went ahead and implemented box consolidation such that vertical stacks of adjacent boxes are now a single box, but it didn't completely reduce the bump effect. Instead now AllowedPenetration = default is the same as AllowedPenetration = 0.001 was before consolidation, so it seems there's another factor at play here aside from the continuous surface thing.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: CharacterController jump catching on nearby boxes

Post by Norbo »

Regarding boundary bump mitigation:
Although I'm still keen on what can be done to help cases where I do need to stack dynamic entities (i.e. a moving box that's at rest).
Given the lack of completely general purpose boundary smoothing, this pretty much relies on minimizing penetration and reducing the normal deviation when it exists. In v1, that might mean a shorter and more frequent time steps, combined with a smooth shape like a capsule or rounded cylinder.

(I actually came up with a potential solution to this between the previous post and this one. I'm not sure if it'll actually be fast enough, and it's pretty darn complicated so no guarantees, but I MIGHT be able to solve this generally in v2... eventually. Probably several months at the earliest :P)
Total beginner so would appreciate some guidance if this is easy-ish. Is this something can be done at run time? Sounds similar to what I was thinking with consolidating the stacks?
It's not super duper easy to implement, but conceptually it's fairly simple- identify all surfaces that are exposed (that is, not blocked by another grid entry) and create some triangles for them. Then, ensure that vertices on the edges between triangles are shared- maybe by maintaining a hash table of vertex locations already encountered. It's possible to optimize this a bit further by combining adjacent quads when possible, but doing this can get complicated fast since T junctions introduce unavoidable boundary bumps.

It could be done at runtime, but it would probably have to be handled asynchronously to avoid frame hitches. There are also some annoyances created by the API design- changing a mesh's topology tends to require garbage generation in v1 (not in v2!). For some games that's okay, but random GC pauses can get pretty terrible in a high performance or VR focused game.

It is indeed similar to consolidating the stacks in end result, except that it could also smooth boundaries in all directions rather than just up and down.
Where exactly is that? Had a quick look in the controller and couldn't see anything.
It's a property of the CharacterController.Body.CollisionInformation.Shape. In the CharacterController, it's set by the constructor's margin parameter and CollisionMargin property. In the SphereCharacterController, there is no directly exposed collision margin property because the radius of the sphere is the collision margin.

Regarding not-boundary-bump causes:
Does it still happen if CollisionResponseSettings.PenetrationRecoveryStiffness is set to 0?
If it's still there, how large is the effect? Starting from 0 velocity and jumping, does it immediately jump to something like 0.2 horizontal velocity, or is it more like 1e-4?

If you output the set of contacts (enumerate each pair in character.Body.CollisionInformation.Pairs, and then enumerate each contact in pair.Contacts), do any of the generated contact normals point in a weird direction, maybe mostly-horizontal-but-a-little-down?

If setting the stiffness to 0 gets rid of it, then some contact is detecting nonzero depth. If you set the character.HorizontalMotionConstraint.PositionAnchorDistanceThreshold to 0, does it still happen?
Vanit
Posts: 6
Joined: Tue Jan 03, 2017 11:56 pm

Re: CharacterController jump catching on nearby boxes

Post by Vanit »

Glad to hear this might be fixed in the elusive v2 :) Thanks for the mesh explanation, luckily it seems like the vertical consolidation is all I need as I can't see any issues with adjacent vertical edges.

Setting CollisionResponseSettings.PenetrationRecoveryStiffness to 0 does indeed fix the issue, but I'm guessing that's not a longterm solution as it seems to allow me to penetrate boxes. :) character.HorizontalMotionConstraint.PositionAnchorDistanceThreshold to 0 seems to have no effect sadly.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: CharacterController jump catching on nearby boxes

Post by Norbo »

As long as what you observe is a fairly small effect, it may just be the nature of penetration correction and the discrete collision detection. If that's the case, then you may be able to mitigate it (without sinking into the ground) by reducing the CollisionResponseSettings.MaximumPenetrationRecoverySpeed, maybe with a lower but nonzero PenetrationRecoveryStiffness too.

It's also possible that the character's movement force is high enough that it's managing to shove itself into the wall, worsening penetration-related issues. If that's happening, reducing the TractionForce property may help. It will also reduce acceleration speed, though.
Post Reply