Bepu v2 Character Controllers

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

Re: Bepu v2 Character Controllers

Post by Norbo »

The character controller doesn't do anything fundamentally special- part of the reason it's in the demos rather than inside the engine itself is to show how to make such a thing externally. So yes, in a sense, it's a matter of convenience, or a starting point for people who want to make their own similar form of character.

The design is relatively simple- it analyzes contacts between the character body and the environment and uses them to create motors that let the character move around on supporting surfaces. The fact that it uses solver-aware motor constraints means it'll interact with other constraints robustly.

You don't have to use it, and it's not the only way to make a character-ish thing. Some use cases can get by with a simple object controlled by velocities or other simple stuff.
parapoohda
Posts: 92
Joined: Fri May 31, 2019 6:30 am

Re: Bepu v2 Character Controllers

Post by parapoohda »

I look into demo there are no click movement. I want to make click movement. Should I make player move by manipulate valocity. And when player near click-point he will stop. I think I will calculate distant between player and click-point by Pythagorean theorem (only x and y because character can't fly). Or should I make collidable at click-point and use callback to reset target and remove target.

I see entity mover in

viewtopic.php?f=4&t=2359&p=13368&hilit=click#p13368

Are there no entity mover anymore? Or it is not in there in the first place.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Bepu v2 Character Controllers

Post by Norbo »

Click-to-move is at a higher level than the physics representation of the character- any physical representation will work, you just have to control it according to your desired scheme (for example, setting movement direction and target velocity for a character controller, or just directly setting velocities for a simple directly controlled body).
Are there no entity mover anymore? Or it is not in there in the first place.
v2 does not have an entity mover type. You can, however, look at how it's implemented in v1 and just do what it did:
https://github.com/bepu/bepuphysics1/bl ... er.cs#L136
parapoohda
Posts: 92
Joined: Fri May 31, 2019 6:30 am

Re: Bepu v2 Character Controllers

Post by parapoohda »

How can I munipulate velocity directly. Thank you. I try to look into characterdemo. I look into it until I struck at target velocity. I can't find what I want.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Bepu v2 Character Controllers

Post by Norbo »

An example of updating the character controller goals can be found in the CharacterDemo's CharacterInput.UpdateCharacterGoals.

If you just want to change a body's velocity, one easy way is to use a BodyReference.
var reference = Simulation.Bodies.GetBodyReference(bodyHandle);
reference.Velocity.Linear = new Vector3(1,0,0);
Note that the BodyReference properties return direct references and modifying them does not automatically wake up the body. If you want to wake the body up, set the reference.Awake property to true.

(This assumes you're using the latest commit on master; I recently improved the BodyReference related APIs.)
parapoohda
Posts: 92
Joined: Fri May 31, 2019 6:30 am

Re: Bepu v2 Character Controllers

Post by parapoohda »

Thank you. I feel like i'm silly after look how easy you munipulate velocity. :lol: :lol:

Oh you write it for me. Thank you very much
parapoohda
Posts: 92
Joined: Fri May 31, 2019 6:30 am

Re: Bepu v2 Character Controllers

Post by parapoohda »

Um, is it intention? I comment movemnt in character demo and add
var reference = Simulation.Bodies.GetBodyReference(bodyHandle);
reference.Velocity.Linear = new Vector3(1,0,0);
It is passthrought that lizard? What does awake do? When I am make it true it done nothing. If it false it sleep.

Oh It seem collision work but it somehow passthrough ground.
I test it in contact demo and makeit move by previous method.It not react as gravity(Maybe I have to add vector myself). And it not react to ground.

I think I will look into CharacterInput.UpdateCharacterGoals.

:) Thank you for everything you do
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Bepu v2 Character Controllers

Post by Norbo »

It is passthrought that lizard?
If using a PositionFirstTimestepper, which happens to be the default, velocities set outside of the physics timestep will be integrated into position at the beginning of the frame before collision detection or the solver can stop it. This has some advantages, but as you see, can be a little confusing too because bodies can be shoved through walls pretty easily.

If you pass the PositionLastTimestepper into Simulation.Create (instead of the null default parameter), velocities specified outside of the timestep will instead be resisted by collisions and other constraints.
What does awake do? When I am make it true it done nothing. If it false it sleep.
An object that is moving around is already awake, so setting it to true wouldn't change anything. Groups of objects which are moving very little enter a very low resource use state and go to sleep together. If you modify one of the BodyReference's direct reference properties (like BodyReference.Pose), it doesn't automatically wake the object up, so other sleeping objects could be left in the air or something along those lines. Setting Awake to true in that case would make the group of objects start simulating again so they'd fall appropriately.
I test it in contact demo and makeit move by previous method.It not react as gravity(Maybe I have to add vector myself). And it not react to ground.
Setting velocity directly will overwrite any other influences, including gravity. Usually you'd want to add your velocity change onto the existing velocity, plus some work to make sure you're not accelerating the object infinitely. (Measuring with Vector3.Dot(body.Velocity.Linear, desiredMovementDirection) and using it to compute the actual needed acceleration and such.)
parapoohda
Posts: 92
Joined: Fri May 31, 2019 6:30 am

Re: Bepu v2 Character Controllers

Post by parapoohda »

:D :D Thank you norbo.
parapoohda
Posts: 92
Joined: Fri May 31, 2019 6:30 am

Re: Bepu v2 Character Controllers

Post by parapoohda »

I use Simulation.Create with TNarrowPhaseCallbacks from carDemo and TPoseIntegratorCallbacks from characterDemo.
So I didn't send characters to narrow phase callback. When I use characters.Simulation it is null. I need to send simulation to constructor of character input isn't it.
parapoohda
Posts: 92
Joined: Fri May 31, 2019 6:30 am

Re: Bepu v2 Character Controllers

Post by parapoohda »

Update
After send simulation to it is not error anymore but I can't still move it.
parapoohda
Posts: 92
Joined: Fri May 31, 2019 6:30 am

Re: Bepu v2 Character Controllers

Post by parapoohda »

I make some change to update character goal by remove camera and change input to vector 2 instead

Code: Select all

internal void UpdateCharacterGoals(System.Numerics.Vector2 velocity, System.Numerics.Vector3 viewDirection, float simulationTimestepDuration)
            {
                var movementDirectionLengthSquared = velocity.LengthSquared();
                System.Numerics.Vector2 movementDirection;
                if (movementDirectionLengthSquared > 0)
                {
                    movementDirection = velocity / MathF.Sqrt(movementDirectionLengthSquared);
                }
                ref var character = ref characters.GetCharacterByBodyHandle(bodyHandle);
#if DEBUG
                Console.WriteLine($" characters: {characters}");
                Console.WriteLine($" simulation : {simulation}");
                //Console.WriteLine($" characters.Simulation.Bodies : {characters.Simulation.Bodies}");
#endif
                var characterBody = new BodyReference(bodyHandle, simulation.Bodies);
                var newTargetVelocity = velocity;
                //Modifying the character's raw data does not automatically wake the character up, so we do so explicitly if necessary.
                //If you don't explicitly wake the character up, it won't respond to the changed motion goals.
                //(You can also specify a negative deactivation threshold in the BodyActivityDescription to prevent the character from sleeping at all.)
                if (!characterBody.Awake &&
                     character.Supported ||
                    newTargetVelocity != character.TargetVelocity ||
                    (newTargetVelocity != System.Numerics.Vector2.Zero))
                {
                    simulation.Awakener.AwakenBody(character.BodyHandle);
                }
                character.TargetVelocity = newTargetVelocity;
                character.ViewDirection = viewDirection;

                //The character's motion constraints aren't active while the character is in the air, so if we want air control, we'll need to apply it ourselves.
                //(You could also modify the constraints to do this, but the robustness of solved constraints tends to be a lot less important for air control.)
                //There isn't any one 'correct' way to implement air control- it's a nonphysical gameplay thing, and this is just one way to do it.
                //Note that this permits accelerating along a particular direction, and never attempts to slow down the character.
                //This allows some movement quirks common in some game character controllers.
                //Consider what happens if, starting from a standstill, you accelerate fully along X, then along Z- your full velocity magnitude will be sqrt(2) * maximumAirSpeed.
                //Feel free to try alternative implementations. Again, there is no one correct approach.
                if (!character.Supported && movementDirectionLengthSquared > 0)
                {
                    BepuUtilities.Quaternion.Transform(character.LocalUp, characterBody.Pose.Orientation, out var characterUp);
                    var characterRight = System.Numerics.Vector3.Cross(character.ViewDirection, characterUp);
                    var rightLengthSquared = characterRight.LengthSquared();
                    if (rightLengthSquared > 1e-10f)
                    {
                        characterRight /= MathF.Sqrt(rightLengthSquared);
                        var characterForward = System.Numerics.Vector3.Cross(characterUp, characterRight);
                        var worldMovementDirection = characterRight * velocity.X + characterForward * velocity.Y;
                        var currentVelocity = System.Numerics.Vector3.Dot(characterBody.Velocity.Linear, worldMovementDirection);
                        //We'll arbitrarily set air control to be a fraction of supported movement's speed/force.
                        const float airControlForceScale = .2f;
                        const float airControlSpeedScale = .2f;
                        var airAccelerationDt = characterBody.LocalInertia.InverseMass * character.MaximumHorizontalForce * airControlForceScale * simulationTimestepDuration;
                        var maximumAirSpeed = speed * airControlSpeedScale;
                        var targetVelocity = MathF.Min(currentVelocity + airAccelerationDt, maximumAirSpeed);
                        //While we shouldn't allow the character to continue accelerating in the air indefinitely, trying to move in a given direction should never slow us down in that direction.
                        var velocityChangeAlongMovementDirection = MathF.Max(0, targetVelocity - currentVelocity);
                        characterBody.Velocity.Linear += worldMovementDirection * velocityChangeAlongMovementDirection;
                        System.Diagnostics.Debug.Assert(characterBody.Awake, "Velocity changes don't automatically update objects; the character should have already been woken up before applying air control.");
                    }
                }
            }
But it isn't move.
I write line by print Position

Code: Select all

internal System.Numerics.Vector3 Position => new BepuPhysics.BodyReference(collider.bodyHandle, map.Simulation.Bodies).Pose.Position;
Could you please help me? Thank you.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Bepu v2 Character Controllers

Post by Norbo »

It's a bit hard for me to guess without the full context. It could be something wrong with the input target velocity and view direction, or possibly something else like the character not having support, or a number of other contextual things.

I'd recommend making incremental changes within the CharacterDemo, and when something doesn't work the way you expect anymore, copy and paste the full modified CharacterDemo here and I'll take a closer look.
parapoohda
Posts: 92
Joined: Fri May 31, 2019 6:30 am

Re: Bepu v2 Character Controllers

Post by parapoohda »

This is part of project. Thank you.

https://github.com/parapoohda/TestMoveInBepu
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Bepu v2 Character Controllers

Post by Norbo »

The view direction passed into the modified UpdateCharacterGoals function is zero, since the character.ViewDirection is never assigned to anything else. Without a valid view direction, the character controller does not know how to interpret the movement direction because the movement direction is in terms of the view direction (projected onto the support surface).

You can pass in a fixed view direction like (0,0,1) to give it something to work with.
Post Reply