Checking if CharacterController Is Grounded

Discuss any questions about BEPUphysics or problems encountered.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Checking if CharacterController Is Grounded

Post by Norbo »

I am now able to reproduce the jumping issue. Holding "W" while jumping into a wall will cause the player to slide up and jump:
It almost looks like the character is jumping off of each nearby platform as it reaches it, assuming you're continually triggering jump in that video. The only questionable component of this theory is that the character must be approaching a surface to consider it a support. As the character's vertical velocity is still quite significant in that video, particularly for the first 'intermediate' jump, there is probably something else going on. Is this CharacterController from the development fork's BEPUphysicsDemos?

If you aren't continually jumping in that video, I don't have any explanation.
Similar behavior happens if you press "E" while jumping into one of the steps in the playground demo.
I can't reproduce any unexpected behavior in the CharacterPlaygroundDemo in the development fork. The closest I get is jumping a second time once the character finds support on the step, which can look a little like a 'fling,' but is just another regular jump.

Sometimes, those secondary jumps are off surfaces which do not have traction, just support. Such 'sliding' jumps use the weaker SlidingJumpSpeed and propel the character along the surface normal rather than directly upward. This is expected, but it can feel weird if unfamiliar.

Another effect is jumping immediately before the step would have otherwise happened, so instead of climbing the step, the character's shins just slam into the top of the next step and stop it from proceeding horizontally.
_untitled_
Posts: 32
Joined: Sat Jan 19, 2013 8:20 pm

Re: Checking if CharacterController Is Grounded

Post by _untitled_ »

What do you mean by continually jumping? Does Jump() check if the player has traction before adding the velocity?
And yes, this is the exact same character controller from the dev fork.

Did you try going as far as you can on the steps until the step height is too high, and then try jumping and walking forward at the same time? Doing that allowed me to get up two more steps.

I did set MaxSlidingForce to be the same as MaxTractionForce (to remove the sliding effect), but that was the horizontal constraint, so I assume it can't be an issue.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Checking if CharacterController Is Grounded

Post by Norbo »

What do you mean by continually jumping?
Hammering the jump button, or the programmatic equivalent.
Does Jump() check if the player has traction before adding the velocity?
Yup. A full jump requires traction. A 'sliding' jump will occur if the character has support, but not traction. No jump will occur without support.
Did you try going as far as you can on the steps until the step height is too high, and then try jumping and walking forward at the same time? Doing that allowed me to get up two more steps.
That is an intended behavior-those steps were designed to require jumping, and later jump-crouching, to get over, demonstrating that stepping has a limited maximum height. Unless you mean a single jump flung you multiple steps upward, which I have not seen.

The first 'unsteppable' step that is just on the threshold of being steppable seems to be the easiest spot to show off the 'sliding jump' behavior on the staircase. As the character reaches a certain height, it will start generating contacts with the nearby step's top edge. Due to the beveled edges on the character cylinder, the contact normals won't be perfectly horizontal or vertical, but in between. Generally, these early contacts are too steep to have traction, but they do count as support. So, the character can perform a 'sliding jump' without yet being all the way onto the new step. This is intended behavior and enables some 'parkour' style stuff- the slanted platforms on the other side of the character controller playground are made for doing this.
_untitled_
Posts: 32
Joined: Sat Jan 19, 2013 8:20 pm

Re: Checking if CharacterController Is Grounded

Post by _untitled_ »

Norbo wrote: Hammering the jump button, or the programmatic equivalent.
So what you're saying is that if a player holds down the jump button, it will cause undefined behavior, even though the controller checks if the player has support before jumping?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Checking if CharacterController Is Grounded

Post by Norbo »

So what you're saying is that if a player holds down the jump button, it will cause undefined behavior, even though the controller checks if the player has support before jumping?
Nope; it should work perfectly fine (edit: and in tests, it has worked perfectly fine). I was just asking to understand the situation better.

If, in that video, you weren't jumping- the character just boosted itself up a couple of times with no input- then I would be really confused. I wouldn't even have a partial explanation. If the character was constantly jumping, I could at least see why it appeared to 'jump' multiple times, even if there was other weird stuff going on also that allowed it to jump when it shouldn't have or something.
_untitled_
Posts: 32
Joined: Sat Jan 19, 2013 8:20 pm

Re: Checking if CharacterController Is Grounded

Post by _untitled_ »

Don't worry, my player didn't become self aware and start jumping. :P

The first jump you see is me trying to get the "glitch" the happen, but it didn't so I tried again. I basically jumped and held down the "W" key to attempt to walk into the wall. Would checking if the vertical velocity <= 0 before stepping work?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Checking if CharacterController Is Grounded

Post by Norbo »

Would checking if the vertical velocity <= 0 before stepping work?
Stepping can only occur when the character already has traction; it doesn't appear to be related to the observed behavior (unless I misunderstand what's going on).

I do have one thing you could try, though: at line 317 in the CharacterController, there's an if statement which checks the relative velocity along the support normal before it permits a transition from unsupported->traction. This technically permits 'sliding' jumps with separating velocity. Originally, it looks like this:

Code: Select all

                bool hadTraction = SupportFinder.HasTraction;

                CollectSupportData();


                //Compute the initial velocities relative to the support.
                Vector3 relativeVelocity;
                ComputeRelativeVelocity(ref supportData, out relativeVelocity);
                float verticalVelocity = Vector3.Dot(supportData.Normal, relativeVelocity);


                //Don't attempt to use an object as support if we are flying away from it (and we were never standing on it to begin with).
                if (SupportFinder.HasTraction && !hadTraction && verticalVelocity < 0)
                {
                    SupportFinder.ClearSupportData();
                    supportData = new SupportData();
                }
You could try swapping out the HasTraction/hadTraction parts with HasSupport/hadSupport instead:

Code: Select all

                bool hadSupport = SupportFinder.HasSupport;

                CollectSupportData();


                //Compute the initial velocities relative to the support.
                Vector3 relativeVelocity;
                ComputeRelativeVelocity(ref supportData, out relativeVelocity);
                float verticalVelocity = Vector3.Dot(supportData.Normal, relativeVelocity);


                //Don't attempt to use an object as support if we are flying away from it (and we were never standing on it to begin with).
                if (SupportFinder.HasSupport && !hadSupport && verticalVelocity < 0)
                {
                    SupportFinder.ClearSupportData();
                    supportData = new SupportData();
                }
This will limit some parkour jumping behaviors, but it shouldn't be too significant. I am slightly concerned that there is some other specific reason for using traction instead of support here that I'm forgetting- the character isn't exactly simple :)- but it may make the behavior more like you expect.

The ability to use sliding jumps quickly alone would not account for the ability to fling yourself a great distance like in the youtube video, though. Jumps do not just add velocity, they push the separating velocity to a specific value without exceeding it.
_untitled_
Posts: 32
Joined: Sat Jan 19, 2013 8:20 pm

Re: Checking if CharacterController Is Grounded

Post by _untitled_ »

It appears that that piece of code has not fixed the issue.

I am not sure if the flinging problem could be linked to this problem. However, I think that perhaps floating-point precision could have a part in this. I tried it again, and this time I noticed that the player "rejumps" when his feet reach the top of a block. Kind of hard to explain in words, so here's a video:
https://dl.dropbox.com/u/59540455/jump_bug2.mp4

It appears that the character controller thinks that the top of a block is a ledge, even though there is a block on top.

(Also notice how the player falls slower on the way down - this is friction, correct?)
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Checking if CharacterController Is Grounded

Post by Norbo »

It appears that the character controller thinks that the top of a block is a ledge, even though there is a block on top.
That is likely. Depending on the topology of the mesh, that could be an 'unsmoothed' boundary. At such boundaries, it is possible (and expected) that there will exist contact normals which are not perfectly aligned and flat. The character could get its toes on that briefly, allowing a jump (most likely a sliding jump).

The triangle mesh contact generator considers any boundary where the involved triangles have shared indices to be 'smooth,' and will correct contacts normals accordingly. So, the boundaries should disappear if connectivity information in the form of shared indices is available. Basically, providing this information turns the mesh from just a soup of separate triangles into a contiguous whole.

[Edit: I should mention that, if there's actually a triangle with a vertical normal that represents the top of the box hiding behind the wall, that won't be filtered out by the boundary smoother. That kind of 'T' intersection is best avoided.]
(Also notice how the player falls slower on the way down - this is friction, correct?)
Friction is explicitly disabled by the character. It's probably just landing on whatever it managed to jump off of, but the slope is too steep to stand on with traction.


None of the above would explain flinging beyond the capacity of a jump as shown in the youtube video, though.
_untitled_
Posts: 32
Joined: Sat Jan 19, 2013 8:20 pm

Re: Checking if CharacterController Is Grounded

Post by _untitled_ »

Norbo wrote: That is likely. Depending on the topology of the mesh, that could be an 'unsmoothed' boundary. At such boundaries, it is possible (and expected) that there will exist contact normals which are not perfectly aligned and flat. The character could get its toes on that briefly, allowing a jump (most likely a sliding jump).

The triangle mesh contact generator considers any boundary where the involved triangles have shared indices to be 'smooth,' and will correct contacts normals accordingly. So, the boundaries should disappear if connectivity information in the form of shared indices is available. Basically, providing this information turns the mesh from just a soup of separate triangles into a contiguous whole.

[Edit: I should mention that, if there's actually a triangle with a vertical normal that represents the top of the box hiding behind the wall, that won't be filtered out by the boundary smoother. That kind of 'T' intersection is best avoided.]
It appears my hunch is correct. Implementing networked physics somehow got me to be able to "stand" on the occluded top face of a block. Add in the entropy of networking with this weird bug, and you get a very weird sliding and bouncing experience if a player is in a 1x1 hole and trying to jump around.

https://dl.dropbox.com/u/59540455/jump_ ... orking.mp4

My mesh is pretty simple:
http://i.imgur.com/LbVW3yA.png

Each face is just two triangles.

Any way to circumvent this issue? Linking the indices would be out of the question, since that would make mesh generation too complex.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Checking if CharacterController Is Grounded

Post by Norbo »

able to "stand" on the occluded top face of a block.
Is there actually an occluded face included in the triangle data, forming a T junction with the wall? If so, boundary smoothing cannot help; the superfluous face must be removed.

If such faces exist, removing them may improve boundary behavior sufficiently that you don't have to worry about including proper connectivity information.
Any way to circumvent this issue? Linking the indices would be out of the question, since that would make mesh generation too complex.
The short answer is no. The alternatives are generally more complex, and are not all guaranteed fixes.

For example, you could stitch contiguous regions into the minimum triangles needed to represent the area to reduce the number of boundaries, but the remaining boundaries would still cause bumps and the algorithm is far from trivial.

Another option would be to create a custom collidable and implement custom boundary smoothing designed specifically for your data set. However, robust boundary smoothing is one of the harder projects in collision detection, both conceptually and in implementation.

It's technically possible to implement boundary smoothing without explicitly stored connectivity information, but that would require dynamically determining the connectivity information instead. These dynamic methods, by virtue of having limited execution time and information to work with, are generally less reliable and/or less efficient than methods that rely on explicit connectivity information.
_untitled_
Posts: 32
Joined: Sat Jan 19, 2013 8:20 pm

Re: Checking if CharacterController Is Grounded

Post by _untitled_ »

The occluded face is not generated. I run a basic occlusion algorithm which checks if a neighboring block (+X, -X +Y, -Y, +Z, -Z) is solid, and if it is, the face is not created.
I'm confused as to how the character is able to stand on such a small "ledge". Unless the player's collision body is a point/line, shouldn't the player fall off/not be able to stand on it?

http://i.imgur.com/soBulkR.png

Or does the finding supports system not factor this in?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Checking if CharacterController Is Grounded

Post by Norbo »

The character's body is nonrotating cylinder. It can't fall over, so the only way it can fall off an object is to slide. If there exist contact normals such that the character has traction, it will not slide off. The expected behavior in your picture, as drawn, is that the character has traction and does not fall off.

However, if the situation is modified such that there is no explicitly constructed ledge, just a flat wall composed of multiple triangles, it is still possible for there to exist bumps or even 'ledges' depending on penetration depth.
boundarysmoothing.png
boundarysmoothing.png (27.51 KiB) Viewed 10873 times
In the above, the 'bump' would feel like you landed on something and then slid off because you didn't have traction. The 'ledge' would actually let you stand on it, with traction, until penetration correction pushed you out of the wall.

As mentioned, without connectivity information, all the triangles are just separate objects which generate contacts individually. So, whenever the character is penetrating the wall, there's a good chance that it will hit 'bumps.' Connectivity information smoothing removes the issue by making the mesh's collision detection aware of neighboring triangles.
_untitled_
Posts: 32
Joined: Sat Jan 19, 2013 8:20 pm

Re: Checking if CharacterController Is Grounded

Post by _untitled_ »

How would connectivity information be created, and how are the normals generated?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Checking if CharacterController Is Grounded

Post by Norbo »

How would connectivity information be created
The connectivity information used by meshes is the indices list.

For example, here are two possible definitions for a quad. If your vertex list looks like this:
(-1, 0, -1)
(1, 0, 1)
(-1, 0, 1)
(-1, 0, 1)
(1, 0, -1)
(1, 0, 1)

and your index list looks like this:
0, 1, 2, 3, 4, 5

then the boundary between the two triangles will not be smoothed because the indices do not include useful connectivity information. They just define isolated triangles composed of duplicate vertices.

In contrast, if your vertex list looks like this:
(-1, 0, -1)
(-1, 0, 1)
(1, 0, -1)
(1, 0, 1)

and your index list looks like this:
0, 2, 1, 1, 2, 3

then the boundary between the two triangles will be smoothed because the vertices are shared.

Any method which ends up producing indices demonstrating such sharing will work.
how are the normals generated?
That's a broad and deep question; I'm not sure what level of answer you're looking for. Most relevantly, a test is performed for each 'nearby' triangle and the character body. Those contacts are analyzed in various ways to produce the final manifold. One of these analyses is boundary smoothing, which tries to correct contact normals on edges so that they are aligned with the rest of the surface. Note in the rightmost example in the above picture how, despite being just as far in as the middle configuration, the normal points directly out from the wall rather than up.
Post Reply