Character only does short hop C#

Godot Version

4.2.2

Question

I’m just trying to get the basics of movement down for a side scrolling 2D platformer when I got stuck on coding the jumping. I can’t seem to understand on how to get it to work. I tried watching tutorials to get close, but now my character only does a short hop. Here is my code, if I’m missing something then please let me know.

using Godot;
using System;
using System.Security.Cryptography.X509Certificates;

public partial class player : CharacterBody2D
{
[Signal]
public delegate void HitEventHandler();

[Export]
public int speed {get; set;} = 500;
[Export]
float jump_height;
[Export]
float jump_time_to_peak;
[Export]
float jump_time_to_descent;

float jump_velocity;
float jump_gravity;
float fall_gravity;

bool is_on_floor;

public Vector2 ScreenSize;



public override void _Ready()
{
	ScreenSize = GetViewportRect().Size;
	jump_velocity = ((2 * jump_height) / jump_time_to_peak) *-1;
	jump_gravity = ((-2 * jump_height) / (jump_time_to_peak * jump_time_to_peak)) *-1;
	fall_gravity = ((-2 * jump_height) / (jump_time_to_descent * jump_time_to_descent)) *-1;
}

public override void _PhysicsProcess(double delta)
{
	var velocity = Vector2.Zero;

	is_on_floor = IsOnFloor();


	if (Input.IsActionPressed("right")){
		velocity.X += 1;
	}
	if (Input.IsActionPressed("left")){
		velocity.X += -1;
	}

	if(Input.IsActionJustPressed("jump") && is_on_floor)
	{
		velocity.Y = jump_velocity;
	}

	if(!is_on_floor)
	{
		velocity.Y += GetGravity(velocity.Y) * (float)delta;
	}


	MoveAndSlide();



	var animatedSprite2D = GetNode<AnimatedSprite2D>("AnimatedSprite2D");
	animatedSprite2D.Play();

	if (velocity.Length() > 0){
		velocity = velocity.Normalized() * speed;
	}
	

	Position += velocity * (float)delta;
	Position = new Vector2(x: Mathf.Clamp(Position.X, 0, ScreenSize.X), y: Mathf.Clamp(Position.Y, 0, ScreenSize.Y));

	if (velocity.X != 0)
	{
		animatedSprite2D.Animation = "walk";
		animatedSprite2D.FlipV = false;
		animatedSprite2D.FlipH = velocity.X < 0;
	}

	if (velocity.X == 0)
	{
		animatedSprite2D.Animation = "idle";
		animatedSprite2D.FlipV = false;
		if(Input.IsActionJustReleased("left"))
		{
			animatedSprite2D.FlipH = true;
		}
	}
}
public float GetGravity(float v)
{
	if(v < 0)
	{
		return jump_gravity;
	}
	else
	{
		return fall_gravity;
	}
}

You are setting the velocity to zero every frame.

Then to “jump” you are only changing the velocity if the button was “just pressed” which is only going to be true for 1 frame.

Take a look at the code (gdscript though) from Brackeys tutorial

Notice how he doesnt set the velocity to zero each frame?

If it isnt on the floor, he adds the gravity.

If the button was just pressed and it is on the floor, he adds the jump velocity.

1 Like

Here’s a couple of things I’m noticing when looking at your script.

Defining a pre-existing variable
The variable velocity, which is used in conjunction with MoveAndSlide(), is inherited from the CharacterBody2D class (see class reference). There’s no need to define it manually. Doing so only sows confusion as to which variable is in use: the local, or the inherited variable. While it may still be working, it’s a redundant variable.


Incorrect use of the velocity variable
The velocity variable represents the current velocity of the object and can be modified to achieve custom movement behaviour (such as your script). This is usually done with MoveAndSlide() as it is a convenient way to perform character movement. Without it, you would have to perform your own collision force calculations - usually using MoveAndCollide() (see the manual).

While you are succesfully utilizing MoveAndSlide() to perform your movement, you are also manually performing your own integration:

	Position += velocity * (float)delta;

You are essentially moving your character twice.


Not separating your velocity axes when processing the velocity

	if (velocity.Length() > 0){
		velocity = velocity.Normalized() * speed;
	}

As we have just established, velocity is a direct representation of how fast your character is moving. Setting the length of your velocity in the way you’ve done in the above snippet does not take into account the character’s motion when in the air. When not grounded (!IsOnFloor()), the y-velocity of your character is affected by the normalization you’re performing. Furthermore, you likely don’t want your jump/fall speed to be affected by your speed. In general, separate your axes when processing movement.

The code above is likely what is messing with your jump.


Report back if you need further assistance.
2 Likes

Hey thank you for the help, this is exactly what I needed thank you

1 Like

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