Question on how to add a double jump and eventually a wall dodge

So far I have character movement done and a single jump done through action mapping (using a bit of the fps tutorial on the wiki A new, community-hosted Unreal Engine Wiki - Announcements and Releases - Unreal Engine Forums). I saw a way to add a second jump through blueprints but not c++ yet and was hoping you guys could help me out…

projectcharacter.h


	
//sets the jump flag when key is pressed (jump flag in character.h)
UFUNCTION()
	void OnStartJump();
//clears jump flag when key is released
UFUNCTION()
	void OnStopJump();


projectcharacter.cpp


//set jump flag
void Aprojectcharacter::OnStartJump()
{
	bPressedJump = true;
}

//clear jump flag
void Aprojectcharacter::OnStopJump()
{
	bPressedJump = false;
}

....

void Aprojectcharacter::SetupPlayerInputComponent(UInputComponent* InputComponent)
{
	InputComponent->BindAction("Jump", IE_Pressed, this, &Aprojectcharacter::OnStartJump);
	InputComponent->BindAction("Jump", IE_Released, this, &Aprojectcharacter::OnStopJump);
}


In Character.h there is a function “CanJump()” is there a way to force that to true after the first jump or would it be easier to apply force to the character to simulate a second jump, the idea is to have movement similar to UT2k4 so eventually I would like to add wall dodging as well. Thanks for any help.

1 Like

you can just have a global boolean

CanDoSecondJump

that is false until the user jumps the first time

then on first jump you set it to true

then if they do second jump, you set it false

and if they land, you set it to false

check out Character.h for the onlanded event to set the bool to false again




/** Called on landing after falling has completed, to perform actions based on the Hit result. Triggers the OnLanded event. */
	virtual void Landed(const FHitResult& Hit);



then whenever player presses the jump button you can check the boolean and apply force


if(CanDoSecondJump)
{
  //apply force
}

Here’s how I apply force, it replicates automatically in a networked context, as long as you call it server-side


MyCharacter->CharacterMovement->Velocity += FVector(0,0,1) * 30000;

just change the 30000 to change jump amount

could make the jump directional using




GetRootComponent()->GetRightVector() and GetForwardVector()



What would be the proper way to check if the jump key was pressed again while in the air? Adding the boolean check to ::OnStartJump() fires both the first and second jump with one press.

EDIT: On second thought, if I wanted to be able to have more control while in the air (as in starting the jump while moving backwards, then changing direction to go forward mid jump) would it be worth dropping the ::OnStartJump() and just make my own jump function by modifying the velocity? Or would it still be better to use that?

In 4.2, we have added some new functionality to help in situations such as this.

You have already mentioned overriding CanJump() - this is key to multiple ‘double’ jumps (simply returning true from this results in being able to jump forever in mid-air). Its overridable in Blueprint as well as C++, although in C++ the syntax is slightly more obtuse as you need to override CanJumpInternal_Implementation(). In 4.1 and previous this was ‘prettier’ in C++ as all you needed to do was override CanJump().

Another useful new feature you might find is the OnJumped() event/function that you can now hook into. This gets fired when we do the transition into ‘jumping’ movement mode, it might be handy to increment a counter in that event to let you check (in CanJump()) whether any more aerial jumps are allowed.

Lastly, hold-to-jump-higher functionality was added too - you can set JumpMaxHoldTime to a non-zero value, then hook a call to Jump() into an input event ‘pressed’ & a call to StopJumping() to an input event ‘released’ to get a basic jump where holding down a key will jump you higher the longer you hold it.

As Rama mentions above, you can apply forces directly to get a ‘jump’, but the preferred way of applying Jump forces is just to call Jump() - this will apply the pre-set jump vertical velocity and correctly transition the movement mode to ‘Jumping’.

For now in 4.1 could you give me an example on how to override CanJumpInternal_Implementation() because from what I have tried so far it hasn’t worked (still somewhat new to c++). Thanks for the other information as well I didn’t even think about the other checks relating to Jump().

Sure no problem.

In 4.1 you have the ability to override CanJump() (note CanJumpInternal_Implementation() is not available in 4.1), so in you character class you could do something like this:



// .H:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Character Movement")
int32 MaxJumpCount;

UPROPERTY()
int32 CurrentJumpCount;

bool CanJump() const OVERRIDE;

// .CPP:
bool AMyCharacter::CanJump() const
{
    return Super::CanJump() || (CharacterMovement->MovementMode == MOVE_Falling && CurrentJumpCount > 0 && CurrentJumpCount < MaxJumpCount);
}


You could override DoJump() to increment this CurrentJumpCount counter, as well as resetting it in an overridden version of OnLanded(). Make sure you call the Super:: versions where needed.

As I say, 4.2 makes this nicer & more robust by supplying new events & functions

Appreciate all the help, It works now. Looking forward to seeing the changes in 4.2 as well.
Code for anyone looking for it (some used from the FPS tutorial linked in OP):

MyCharacter.h


class AMyCharacter : public ACharacter
{
	GENERATED_UCLASS_BODY()

	virtual void BeginPlay() OVERRIDE;

	UFUNCTION()
		void OnStartJump();
	UFUNCTION()
		void OnStopJump();

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Character Movement")
		int32 MaxJumpCount;
	UPROPERTY()
		int32 CurrentJumpCount;

	bool CanJump() const OVERRIDE;

	virtual void OnLanded(const FHitResult& Hit) OVERRIDE;
}

MyCharacter.cpp


void AMyCharacter::BeginPlay()
{
	Super::BeginPlay();

	MaxJumpCount = 3;
	CurrentJumpCount = 0;

}

bool AMyCharacter::CanJump() const
{
	return Super::CanJump() || (CharacterMovement->MovementMode == MOVE_Falling && CurrentJumpCount > 0 && CurrentJumpCount < MaxJumpCount);
}

void AMyCharacter::OnStartJump()
{
	bPressedJump = true;
	CurrentJumpCount++;
}

void AMyCharacter::OnLanded(const FHitResult& Hit)
{
	CurrentJumpCount = 0;
}

void AMyCharacter::OnStopJump()
{
	bPressedJump = false;
}


1 Like

Can someone show an example on how to override OnJumped() in 4.2? It’s giving me “not overriding any parent method” errors.

Because OnJumped is a BlueprintNativeEvent, you need to implement OnJumped_Implementation in your derived class:

H:


virtual void OnJumped_Implementation() override;

CPP:


void AMyCharacter::OnJumped_Implementation()

BlueprintNativeEvent functions cause additional code to be generated and inserted into the ACharacter base class, so you won’t see a declaration in the base classes header and can’t override the OnJumped() function directly. You can however see the base implementation in ACharacter.cpp (which at the moment is empty).

This is great.

Sorry I know this is super late, but I am working in version 4.26 and I don’t understand why I would want to override any of the functions when setting the JumpMaxCount to 2 already gives you doublejump. The only case I could see it as a necessity is when you want the player to have two jumps no matter what. even if they haven’t jumped but are in the air. I am new to all this so I am just looking for confirmation or guidance.