Unreal 5 - Implementing Jump() causes game to freeze

image

Implementation

My axis maps work fine. When I try to jump and hit the space bar, the editor freezes and I have to go into task manager and kill the proces.

Replicated 5x in a row, after various rebuild, etc.

I noticed we have a CanJump() function and I used that as well to make sure that returns true first and to log if it is false.

Interesting enough when I log it also never logs indicating that the function is never entered in the first place… and that the binding is somehow jacked? (again take the input map image above and replace the Jump binding to the local binding for this conclusion)

void APlayerCharacter::Jump()
{
	if (CanJump())
	{
		UE_LOG(LogTemp, Display, TEXT("YOU JUMPED!!"));
		Jump();
		UE_LOG(LogTemp, Display, TEXT("YOU FINISHED JUMP!!"));
	}
	else
	{
		UE_LOG(LogTemp, Display, TEXT("YOU CANT JUMP!!"));
	}
}

Anything anyone knows of to cause Jump to fail like this and hang up the game?

Would you mind showing your full code?

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "PlayerCharacter.generated.h"

UCLASS()
class SIMPLESHOOTER_API APlayerCharacter : public ACharacter
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	APlayerCharacter();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

private:
	void MoveForward(float axisValue);
	void MoveSide(float axisValue);
	void LookUpDown(float axisValue);
	void LookSide(float axisValue);
	void Jump();
};

CPP File

#include "PlayerCharacter.h"

// Sets default values
APlayerCharacter::APlayerCharacter()
{
 	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void APlayerCharacter::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void APlayerCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

// Called to bind functionality to input
void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
	PlayerInputComponent->BindAxis(TEXT("MoveForward"), this, &APlayerCharacter::MoveForward);
	PlayerInputComponent->BindAxis(TEXT("MoveSide"), this, &APlayerCharacter::MoveSide);
	PlayerInputComponent->BindAxis(TEXT("LookUpDown"), this, &APlayerCharacter::LookUpDown);
	PlayerInputComponent->BindAxis(TEXT("LookSide"), this, &APlayerCharacter::LookSide);

	PlayerInputComponent->BindAction(TEXT("Jump"), EInputEvent::IE_Pressed, this, &APlayerCharacter::Jump);
}

void APlayerCharacter::MoveForward(float axisValue)
{
	AddMovementInput(GetActorForwardVector() * axisValue);
}

void APlayerCharacter::MoveSide(float axisValue)
{
	AddMovementInput(GetActorRightVector() * axisValue);
}

void APlayerCharacter::LookUpDown(float axisValue)
{
	AddControllerPitchInput(axisValue);
}

void APlayerCharacter::LookSide(float axisValue)
{
	AddControllerYawInput(axisValue);
}

void APlayerCharacter::Jump()
{
	if (CanJump())
	{
		UE_LOG(LogTemp, Display, TEXT("YOU JUMPED!!"));
		Jump();
		UE_LOG(LogTemp, Display, TEXT("YOU FINISHED JUMP!!"));
	}
	else
	{
		UE_LOG(LogTemp, Display, TEXT("YOU CANT JUMP!!"));
	}
}

What happens when you use that because that’s an infinite recursive function if CanJump returns true. You would need to use Super::Jump() there.

Also Jump is a virtual function so you should at the very least add the override specifier. It’s Unreals convention to also have the virtual keyword.

When I just use &ACharacter::Jump it does the same thing.

This is from the lecture from the instructor:

My initial version was his version and it caused the hang up so I broke his version out into its own method so that I could trace log it and it still hangs.

I’m not seeing the difference between what he did in the lecture here and what I am doing.

Changing my code to:

void APlayerCharacter::Jump()
{
	UE_LOG(LogTemp, Display, TEXT("YOU JUMPED!!"));
	Jump();
	UE_LOG(LogTemp, Display, TEXT("YOU FINISHED JUMP!!"));
}

Doing this still causes the freeze. Replacing all of this with the lecture’s code still causes the freeze.

I’m going to start looking at the editor now and how the character is placed in its blueprint.

Another update. The Jump method is in fact being called. I log traced that method to just output YOU JUMPED and return out. With that implementation in place it logs every time I hit the space key. It is 100% hanging up on Jump();

I’m not sure why your initial version was hanging but your additional Jump code is an infinite loop which will eventually lead to a stack overflow.

void APlayerCharacter::Jump()
{
	UE_LOG(LogTemp, Display, TEXT("YOU JUMPED!!"));
    // This calls the very function you are defining i.e. void APlayerCharacter::Jump()
	Jump();
    // execution will never reach here
	UE_LOG(LogTemp, Display, TEXT("YOU FINISHED JUMP!!"));
}

I see the issue.

So because I have a Jump() method defined in the h file and am using my own Jump() method and its named the same as ACharacter::Jump, it was causing an issue.

My C++ is only intermediate so I missed that. I’m used to C# where I would have said base.Jump(); (the compiler would also have warned me about shadowing in C# but here it didn’t say anything so it didn’t even cross my mind)

Thank you for helping me talk through this.

That’s not it, no. Your issue with that code has nothing to do with inheritance

void example()
{
    std::cout << "hello ";
    example();
    std::cout << " world!\n";
}

What would the output of this program be?

Jump is a virtual function, you have simply overridden it, there is no shadowing.

You are correct but again as a C# developer had I a

void Jump()
{
base.Jump();
}

That would have worked fine.

My issue here was that in my head I was calling the Super::Jump but left off the Super part.

In Visual Studio if I in C# said

void Jump()
{
Jump();
}

It squigglies my Jump with a shadowing warning assuming my parent has a Jump function.

You are 100% in that it is a function calling itself here; I missed it because I’m used to the compiler warning me about that type of thing (now had there been no base jump then in C# it also wouldn’t have said anything).

The issue is 100% my brain short circuited and didn’t even notice that my Jump was calling itself and was full on thinking it was calling the base Jump because I knew there was a base jump.

I’m not well versed in C# but that doesn’t sound right. Or perhaps you are unfamiliar with C++ and virtual? Because why would it give you shadowing warnings if you are overriding i.e.

public class Base
{
    public virtual void Jump()
    {
    }
}

class Derived : Base
{
    public override void Jump()
    {
        // Warning?
        Jump();
    }
}

You’re saying there would be a warning there?

if I have a virtual method in a parent class in C# and then in a child class I just say

public void Jump()

I get squigglied with a compiler warning saying I’m shadowing.

I understand the concepts in C++ and what virtual does (it says that there is implementation in the parent class and that you have the ability to override it in a child class).

Maybe its that I’m using resharper and its smarter and can detect these things for me and I take that for granted since I’ve used it in my IDEs for the past decade, I don’t know.

I don’t think it matters in this case. I understand the issue I had and why it was failing.

That’s not how that works in C++. That would still be a virtual function, you are overriding there which is why my C# example had override.

Edit: Example Compiler Explorer

image

for reference in C# of the compiler squiggley giving me a warning that I am using a Jump method when one is already declared in the base Character class. This is what my brain expected in C++ and why it never crossed my mind at first.

This would have immediately kicked me in the knee reminding me I need to override. Putting in override here clears the squiggly because I’m overriding the parent virtual function and all is well again.

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