Bepu v2 Character Controllers

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

Re: Bepu v2 Character Controllers

Post by Norbo » Wed Jun 05, 2019 10:00 pm

I noticed that there's no air control. Is there a built-in way to implement this?
Nope, that's one of the features I decided not to implement for the demos. You could modify the CharacterControllers to create a StaticCharacterMotionConstraint while the character is in the air and give it appropriately low maximum force values. Or, since the robustness of a solved constraint is less important for air control, you could just do whatever you want to velocities to achieve your desired behavior.
Additionally, when the character stands on a moving object—such as a ship—and jumps, he doesn't have the same velocity as the moving object, meaning jumping is quite unpredictable in terms of where you'll land (sometimes not even on the same object). When a character stands, I'm assuming friction makes him move with whatever he's on top of. What would be the best way to go about giving him the same velocity as the object beneath him when he jumps?
It sounds like the simulation was given pose integrator callbacks that include damping. If you're using something like the DemoPoseIntegratorCallbacks, the damping implementation simply scales the current linear velocity by a value below 1 each time step. This has the effect of converging to a velocity of 0 over time. Since 0 velocity is measured according to a fixed 'world' frame of reference, jumping while on a moving boat will make the character appear to drift relative to the boat.

To address this, either use a smaller (or zero) linear damping or use a damping implementation that is aware of your frame of reference. In this case, perhaps wind speed or something. You could also use the ship's local frame of reference, although that's not exactly physical.

Incidentally, this is part of the reason why I didn't include air control in the demos. It's nonphysical and requires game-specific heuristics to produce decent results. On a moving boat, you'd probably want air control to be relative to the local frame of reference.
Finally, I noticed that unlike v1, v2 has no ApplyAngularImpulse method. Is there a different built-in method that I'm not aware of? If not, what's the alternative?
For an instantaneous angular impulse t, ApplyAngularImpulse(t) is the same as angularVelocity += t * inverseInertiaTensor. If you primarily care about changing the angular motion without regard for the inertia, you can just directly change the angular velocity too.

Norbo
Site Admin
Posts: 4661
Joined: Tue Jul 04, 2006 4:45 am

Re: Bepu v2 Character Controllers

Post by Norbo » Wed Jun 05, 2019 11:04 pm

I went ahead and added some BodyReference impulse helpers (and fixed another character bug): https://github.com/bepu/bepuphysics2/co ... 03a0adcc90

tomweiland
Posts: 33
Joined: Wed May 08, 2019 12:17 am

Re: Bepu v2 Character Controllers

Post by tomweiland » Thu Jun 06, 2019 4:11 am

Norbo wrote:
Wed Jun 05, 2019 11:04 pm
I went ahead and added some BodyReference impulse helpers (and fixed another character bug): https://github.com/bepu/bepuphysics2/co ... 03a0adcc90
Awesome, thanks!
Norbo wrote:
Wed Jun 05, 2019 10:00 pm
you could just do whatever you want to velocities to achieve your desired behavior.
I'm thinking I'll probably go that way since it sounds a lot simpler. Is there a property I can access to quickly check if the character is standing on something? CharacterController doesn't seem to have one...
Norbo wrote:
Wed Jun 05, 2019 10:00 pm
It sounds like the simulation was given pose integrator callbacks that include damping. If you're using something like the DemoPoseIntegratorCallbacks, the damping implementation simply scales the current linear velocity by a value below 1 each time step. This has the effect of converging to a velocity of 0 over time.
I did pull the pose integrator callbacks out of one of the demos, although I can't remember which one. The actual application of the damping implementation would happen in the IntegrateVelocity method right? In there I only have this:

Code: Select all

if (localInertia.InverseMass > 0)
{
    velocity.Linear = velocity.Linear + gravityDt;
}
Norbo wrote:
Wed Jun 05, 2019 10:00 pm
Since 0 velocity is measured according to a fixed 'world' frame of reference, jumping while on a moving boat will make the character appear to drift relative to the boat.

To address this, either use a smaller (or zero) linear damping or use a damping implementation that is aware of your frame of reference. In this case, perhaps wind speed or something. You could also use the ship's local frame of reference, although that's not exactly physical.

Incidentally, this is part of the reason why I didn't include air control in the demos. It's nonphysical and requires game-specific heuristics to produce decent results. On a moving boat, you'd probably want air control to be relative to the local frame of reference.
So when the character is standing on a moving object, he moves with it. The friction is what's holding him in place, right? So if he jumps and is no longer touching the object, shouldn't the result be closer to what we see in real life? What I mean is, shouldn't the velocity he had when he was touching it carry over, or do the motion constraints interfere with that?
Is there really no simple way to have the character conserve his momentum after separating from a moving object?

I guess as a workaround I could potentially somehow get the velocity of whatever he's standing on, but that would require accessing his supporting contacts.

What would using "a damping implementation that is aware of your frame of reference" roughly look like? That sounds like a more physically-based solution than changing the frame of reference based on what the character is standing on. Using wind speed might be an option, but its direction rarely matches the ship's velocity's direction (ship goes up and down waves, thereby rotating, or it might be sailing perpendicular to the wind). Its magnitude is also not guaranteed to match since the ship will have to accelerate and decelerate at certain times.

Norbo
Site Admin
Posts: 4661
Joined: Tue Jul 04, 2006 4:45 am

Re: Bepu v2 Character Controllers

Post by Norbo » Fri Jun 07, 2019 12:18 am

Is there a property I can access to quickly check if the character is standing on something?
CharacterController.Supported for a boolean, CharacterController.Support for the collidable it's standing on.
The actual application of the damping implementation would happen in the IntegrateVelocity method right?
Yup. In the DemoPoseIntegratorCallbacks, it looks like:

Code: Select all

            if (localInertia.InverseMass > 0)
            {
                velocity.Linear = (velocity.Linear + gravityDt) * linearDampingDt;
                velocity.Angular = velocity.Angular * angularDampingDt;
            }
So when the character is standing on a moving object, he moves with it. The friction is what's holding him in place, right? So if he jumps and is no longer touching the object, shouldn't the result be closer to what we see in real life? What I mean is, shouldn't the velocity he had when he was touching it carry over, or do the motion constraints interfere with that?
Is there really no simple way to have the character conserve his momentum after separating from a moving object?
Without damping, linear momentum should be conserved and the character should continue on a ballistic trajectory. The motion constraints are removed when the character is in the air.

If you haven't already, updating to the latest version of the character would be wise just to avoid any of the bugs that got fixed.
What would using "a damping implementation that is aware of your frame of reference" roughly look like? That sounds like a more physically-based solution than changing the frame of reference based on what the character is standing on. Using wind speed might be an option, but its direction rarely matches the ship's velocity's direction (ship goes up and down waves, thereby rotating, or it might be sailing perpendicular to the wind). Its magnitude is also not guaranteed to match since the ship will have to accelerate and decelerate at certain times.
Since damping is effectively a very approximate version of aerodynamic drag, making damping converge toward the windspeed rather than zero would be a physically reasonable approach. It wouldn't match the ship's local frame of reference, but neither would aerodynamic drag in reality.

Choosing a local reference based on the ship you're on is indeed nonphysical for an open air ship, but can be useful for gameplay reasons or if simulating other circumstances. These details are far more important at higher speeds (or higher damping values)- consider a game that takes place on jets. If you're inside a jet, you wouldn't want damping relative to the external wind speed to slam you into the back of the cabin.

But to reiterate, if you're not using damping, characters should move ballistically like any other dynamic body when not supported. If they don't seem to be, something else is going on.

tomweiland
Posts: 33
Joined: Wed May 08, 2019 12:17 am

Re: Bepu v2 Character Controllers

Post by tomweiland » Sun Jun 09, 2019 11:23 pm

Norbo wrote:
Fri Jun 07, 2019 12:18 am
If you haven't already, updating to the latest version of the character would be wise just to avoid any of the bugs that got fixed.
Just updated, it solved the issue of the character's linear momentum not being conserved, so that's great.

In terms of air control though, I'm a little stuck. I don't want to overwrite any velocity the character receives from other sources (like an explosion for example), but adding a certain velocity to the existing one will result in drastic accelerations. Is using motion constraints the only solution/workaround, or am I missing another simpler option?

Also, something I've been wondering: when I copy the CharacterControllers class into my project, it complains about the MathF class not being "accessible due to its protection level" (lines 553, 570, 593). I've just been swapping it out for the Math class, which seems to work fine, but I doubt this is intentional.

Norbo
Site Admin
Posts: 4661
Joined: Tue Jul 04, 2006 4:45 am

Re: Bepu v2 Character Controllers

Post by Norbo » Mon Jun 10, 2019 5:17 am

In terms of air control though, I'm a little stuck. I don't want to overwrite any velocity the character receives from other sources (like an explosion for example), but adding a certain velocity to the existing one will result in drastic accelerations. Is using motion constraints the only solution/workaround, or am I missing another simpler option?
Here's one option:

Code: Select all

currentMovementVelocity = dot(movementDirection, currentVelocity)
targetMovementVelocity = max(0, min(maximumSpeed, currentMovementVelocity + acceleration * dt))
changeInMovementVelocity = targetMovementVelocity - currentMovementVelocity
currentVelocity += changeInMovementVelocity * movementDirection
It measures the current velocity along the desired movement direction and then attempts to accelerate along it if permitted by the maximum speed. This has some quirks- the maximum speed is relative to the world frame of reference, and it's possible to 'surf' through the air half-life style.
Also, something I've been wondering: when I copy the CharacterControllers class into my project, it complains about the MathF class not being "accessible due to its protection level" (lines 553, 570, 593). I've just been swapping it out for the Math class, which seems to work fine, but I doubt this is intentional.
The MathF class is a part of .NET Core 2.0 (and higher). It sounds like there's a name collision with some other MathF type, or possibly the application target isn't .NET Core 2.0+. Notably .NET Standard 2.0 does not have MathF (which is why the library itself doesn't use it); I think that's coming in .NET Standard 2.1.

tomweiland
Posts: 33
Joined: Wed May 08, 2019 12:17 am

Re: Bepu v2 Character Controllers

Post by tomweiland » Fri Jun 14, 2019 5:13 am

Norbo wrote:
Mon Jun 10, 2019 5:17 am
Here's one option:

Code: Select all

currentMovementVelocity = dot(movementDirection, currentVelocity)
targetMovementVelocity = max(0, min(maximumSpeed, currentMovementVelocity + acceleration * dt))
changeInMovementVelocity = targetMovementVelocity - currentMovementVelocity
currentVelocity += changeInMovementVelocity * movementDirection
It measures the current velocity along the desired movement direction and then attempts to accelerate along it if permitted by the maximum speed.
After some playing around with it, I ended up with this (this is just for forwards/backwards, I do the same thing for left/right):

Code: Select all

float _currentZVelocity = Vector3.Dot(_character.ViewDirection * Math.Sign(inputDirection.Y), gameObject.collider.Velocity.Linear);
float _targetZVelocity = Math.Max(0, Math.Min(airSpeed, _currentZVelocity + 0.25f));
float _changeInZVelocity = _targetZVelocity - _currentZVelocity;
if (_changeInZVelocity > 0)
{
    gameObject.collider.Velocity.Linear += _changeInZVelocity * inputDirection.Y * _character.ViewDirection;
}
Without the if statement, any momentum the player had while running is immediately upon liftoff reduced to what is allowed by the airspeed.

The one most noticeable issue I've encountered is that if I run and jump, I continue with the proper momentum, however as soon as I press the key to move in the opposite direction of my current velocity, I lose all momentum and change direction. It almost looks like I'm hitting a wall mid-air. I could probably get around that with another few if statements, but maybe you have some insight as to how I could pull it off in a more elegant and efficient way?

Norbo
Site Admin
Posts: 4661
Joined: Tue Jul 04, 2006 4:45 am

Re: Bepu v2 Character Controllers

Post by Norbo » Fri Jun 14, 2019 9:53 pm

I added a little example to the CharacterDemo showing one possible implementation:
https://github.com/bepu/bepuphysics2/co ... 67376d5c73

(The pseudocode snippet I posted earlier had a sleepygoof- the target velocity should not be clamped against zero, the change should be. Clamping the target to zero would cause drastic wall-smack velocity changes.)

Post Reply

Who is online

Users browsing this forum: No registered users and 7 guests