Velocity doesn't work as expected when trying to make a symmetrical jump

Godot 4.2.2

I created an async Jump() method that looks like this:

async void Jump(int _dir)
    {
        jumping = true;
        for(int _frame = JumpDuration; _frame >= -JumpDuration; _frame--)
        {
            Velocity = (Vector2.Up * _frame * Math.Abs(_frame) * JumpHeight) + (Vector2.Right * Fws * _dir);
            MoveAndSlide();
            await ToSignal(GetTree(), SceneTree.SignalName.ProcessFrame);
        }
        jumping = false;
    }

Here, _dir is -1, 0 or 1 depending on input, Fws is an int that curates horizontal speed and JumpHeight is a float that curates height of the jump.

Jump arc is supposed to be symmetrical around _frame = 0, so I expected the formula to return the character back to the starting position. It did not. What in fact happened is that he rose significantly. I tried to extend the fall by adding another iteration:

for(int _frame = JumpDuration; _frame >= -JumpDuration-1; _frame--)

It seemed to solve the problem, but sometimes the character now falls a bit lower than at the start of the jump. I tried using _PhysicsProcess too, but that didn’t solve a thing as well.

What are the reasons behind managing the physics manually instead of using the physics functionality provided by Godot?

The current formula for Velocity might not be perfectly symmetrical due to floating-point precision errors or the way the motion is being applied in each frame.

I thought that building the movement arc myself would let me fully tweak it to my liking.

So you suggest I apply gravity and entry velocity upon jump start?

You can honestly do whatever you want. If you think that you can create better physics functionality than the Godot physics engine or any drop-in replacement such as Godot Jolt - Godot Asset Library, then go for it.

I would not suggest to anyone to build custom physics functionality if they don’t know what they’re doing and why they are doing it.

Not really helpful. I’m looking for a way to create a jump that will look good and have geometry and velocity completely controllable. Fighters are a very precise genre and just giving out control to a physics engine feels like a compromise for me.

For example, linearly changing speed with every frame disables the slow-down approaching the peak of the jump that a square function would have. This slowdown is generally used in fighters to highlights the peak point of the jump, making it easier to read and react to.
At this point I’ll try to make gravity a linear function, but I’d very much like to hear other possible ways to create such a jump

Since this is a physics object you should use physics process/await physics frame.

Can you post the context of where you call the jump function?

Are there any other functions interacting with velocity? Are you calling move and slide multiple times?

We know the expected behavior, can you post a video of the actual behavior?

Also, I’m sure you know this, Velocity is in pixels per second.

OK, guys, I’m sorry for caused trouble, but I made progress myself.

This is the code invoking the jump:

public override void _Process(double delta)
    {
        if(jumping)
        {
            return;
        }

        Movement();
        MoveAndSlide();
void Movement()
    {

        if(StateMachine.GetCurrentNode() != "Idle" & StateMachine.GetCurrentNode() != "Walk")
        {
            return;
        }

        if(JustDirectionY==1)
        {
            Jump(DirectionX);
            return;
        }

        Velocity = SpeedX; // SpeedX is a precalculated Vector2
    }

The next methods in _Process() only work with animation

Search:
So, I tried a lot of things.

I realised that on the first frame of the jump, MoveAndSlide() was called upon twice (if(jumping){return} only working on the beginning of next frame) and fixed it.

But SOMEHOW, character still SOMETIMES fell to the wrong Y pos. The jump was significant and not linear at all. He didn’t rise or fall or do either bit by bit. Only randomly and by big jumps.

Regarding Velocity, I tried setting it via new Vector2(//constant value//, //quadratic formula based on parameter _frame//), amongst other things. I figured out that the uncertainty of the outcome came particularly from how Velocity is applied. I thought so because GlobalPosition returned the character back to expected position, when applied the same quadratic formula.

Now the problem rose that the X transformation on GlobalPosition seemed to be DIABOLICAL. The character quite literally broke the speed of sound when applied the same constant transformation every frame. That’s why I decided to change only the vertical GlobalPosition, and use Velocity to cover horizontal axis.

Solution:

async void Jump(int _dir)
{
    jumping = true;
    StateMachine.Stop();
    Sprite.Frame = 0;
    GD.Print(GlobalPosition);
    for(int _frame = 0; _frame <= JumpDuration; _frame++)
    {
        GlobalPosition = new Vector2(GlobalPosition.X, JumpCoefficient*(Math.Abs(_frame-JumpDuration/2))*(_frame-JumpDuration/2)*(_frame-JumpDuration/2) - JumpCoefficient*(JumpDuration/2*JumpDuration/2*JumpDuration/2));
        Velocity = new Vector2I(Fws*_dir, 0);
        MoveAndSlide();
        GD.Print(GlobalPosition);
        await ToSignal(GetTree(), SceneTree.SignalName.ProcessFrame);
    }
    jumping = false;
}

And this solution satisfies me fully. Now I can fully control the attributes of the jump algebraically.

I am yet to automate the powering and coefficients, which are to be raised to the same power as the parameter, but that is not that hard.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.