The character suddenly doesn't move..

Hi. I’m working on a project by myself, but I have a problem.
I’m implementing something that gives damage if I collide with a certain actor.
If they collide first, they will draw a debug sphere. Up to this point, the character moved well and also understood the actors that collided.
But suddenly after implementing the damage, the character won’t move.

The picture below has the character coming out of the building, but the camera is shining outside the building right now. It’s hard to put into words. Sorry… anyway the character never moves.
It’s the same when you play outside the building. It doesn’t move at all.

#include "InputMappingContext.h"
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"

// Sets default values
CharacterPlayer::CharacterPlayer()
{
	// Camera
	SpringArm = CreateDefaultSubobject<USpringArmComponent>("SpringArm");
	SpringArm->SetupAttachment(RootComponent);

	Camera = CreateDefaultSubobject<UCameraComponent>("Camera");
	Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);	

	SpringArm->TargetArmLength = 450.0f;
	SpringArm->bUsePawnControlRotation = true;	
	SpringArm->bInheritPitch = true;
	SpringArm->bInheritRoll = true;
	SpringArm->bInheritYaw = true;
	SpringArm->bDoCollisionTest = true;	

	Camera->bUsePawnControlRotation = false;	


	

}

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

	APlayerController* PlayerController = CastChecked<APlayerController>(GetController());
	if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
	{
		Subsystem->AddMappingContext(DefaultMappingContext, 0);
	}
}

// Called to bind functionality to input
void ACharacterPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	// EnhancedInputComponent를 사용하지 않는다면 에러가 나도록 체크
	UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent);

	if (EnhancedInputComponent)
	{
		EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &ACharacter::Jump);
		EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
		EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &ACharacterPlayer::Move);
		EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &ACharacterPlayer::Look);
		EnhancedInputComponent->BindAction(AttackAction, ETriggerEvent::Triggered, this, &ACharacterPlayer::Attack);
	}
}

void ACharacterPlayer::Move(const FInputActionValue& Value)
{
	FVector2D MovementVector = Value.Get<FVector2D>();	

	const FRotator Rotation = Controller->GetControlRotation();	
	if (!Controller)
	{
		UE_LOG(LogTemp, Error, TEXT("Controller is NULL!"));
	}
	const FRotator YawRotation(0, Rotation.Yaw, 0);

	const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
	const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);

	AddMovementInput(ForwardDirection, MovementVector.X);
	AddMovementInput(RightDirection, MovementVector.Y);
}

void ACharacterPlayer::Look(const FInputActionValue& Value)
{
	FVector2D LookVector = Value.Get<FVector2D>();

	AddControllerYawInput(LookVector.X);
	AddControllerPitchInput(LookVector.Y);

}

It’s my code… I’ve done everything I can to see if the imc is set up properly, etc…
What’s weird is that after writing the damage code, it doesn’t suddenly move, so it’s the same even if you annotate all the damage code and build it again to run it.
I don’t think the damage code is the problem, please help.

Hey @sehwa how are you?

I don’t see anything wrong in your code. Could you share the implementation of the Attack method? Also, if you can show us how the IMC is configured, that would be helpful!


@BRGDemianLopez
First of all, thank you so much for replying!
First, when you left-click Attack, the Attack function is called. However, the implementation is implemented in CharacterBase, the parent class of CharacterPlayer. I wrote it like the code below.

void ALuckyCharacterPlayer::Attack()
{
	AttackPress();
}

The Attack function is done with Combo. Combo consists of 3 steps in total. The code is very long. Sorry.

void ALuckyCharacterBase::AttackPress()
{
	// If you run an attack for the first time, the combo is set to zero.
	// That's why I changed it to 1 to run the first combo.
	if (CurrentComboAttack == 0)
	{
		CurrentComboAttack = 1;
		ComboAttackStart();
		return;
	}

	if (ComboAttackTimerHandle.IsValid())
	{
		CheckNextCombo = true;

	}
	else
	{
		CheckNextCombo = false;
	}
}

void ALuckyCharacterBase::ComboAttackStart()
{

	// Montage Play
	const float ComboAttackRate = 1.0f;	
	UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
	AnimInstance->Montage_Play(ComboAttackMontage, ComboAttackRate);

	// Callback function to apply at the end of the montage
	FOnMontageEnded ComboEndDelegate;
	ComboEndDelegate.BindUObject(this, &ALuckyCharacterBase::ComboAttackEnd);
	AnimInstance->Montage_SetEndDelegate(ComboEndDelegate, ComboAttackMontage);

	ComboAttackTimer();
}

void ALuckyCharacterBase::ComboAttackEnd(UAnimMontage* TargetMontage, bool CheckEnded)
{
	ensure(CurrentComboAttack != 0);
	CurrentComboAttack = 0;
	CheckNextCombo = false;
}

void ALuckyCharacterBase::ComboAttackTimer()
{
	if (!ComboAttackData)
	{
		return;
	}

	ComboAttackTimerHandle.Invalidate();	
	int32 CurrentComboAttackIndex = FMath::Clamp(CurrentComboAttack - 1, 0, ComboAttackData->MaxComboActionCount);	// Index of the current combo action
	const float TimeRate = 1.0f;
	float NextComboRate = (ComboAttackData->NextComboFrame[CurrentComboAttackIndex] / ComboAttackData->ComboActionFrame) / TimeRate;	// Combo Time
	UE_LOG(LogComboAction, Warning, TEXT("Combo Time: %f"), NextComboRate);
	if (NextComboRate > 0.0f)
	{
		GetWorld()->GetTimerManager().SetTimer(ComboAttackTimerHandle, this, &ALuckyCharacterBase::CheckNextComboAttack, NextComboRate, false);
	}
}

void ALuckyCharacterBase::CheckNextComboAttack()
{
	ComboAttackTimerHandle.Invalidate();
	UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();

	// If you did the attack again before the timer went off, move on to the next section
	if (CheckNextCombo)
	{
		CurrentComboAttack = FMath::Clamp(CurrentComboAttack + 1, 1, ComboAttackData->MaxComboActionCount);	// Specify the next combo value
		// Next Combo Section
		FString NextSectionString = FString::Printf(TEXT("%s%d"), *ComboAttackData->ComboActionName, CurrentComboAttack);
		FName NextSection = FName(*NextSectionString);	
		AnimInstance->Montage_JumpToSection(NextSection, ComboAttackMontage);
	}

	CheckNextCombo = false;
	ComboAttackTimer();	
}

void ALuckyCharacterBase::AttackHitCheck()
{
	FHitResult HitResult;
	FCollisionQueryParams Params(NAME_None, false, this);	
	FVector Start = GetActorLocation();
	FVector End = Start + GetActorForwardVector() * 50;

	float Damage = 50.0f;	

	bool bHitCheck = GetWorld()->SweepSingleByChannel(HitResult, Start, End, FQuat::Identity, ECollisionChannel::ECC_GameTraceChannel1, FCollisionShape::MakeSphere(70.0f), Params);
	if (bHitCheck)
	{

	
		DrawDebugSphere(GetWorld(), HitResult.ImpactPoint, 30, 10, FColor::Cyan, false, 10.0f);	
		AActor* HitActor = HitResult.GetActor();
		if (HitActor)
		{
			UE_LOG(LogComboAction, Warning, TEXT("Hit Actor: %s"), *HitActor->GetActorNameOrLabel());
		}

		FDamageEvent DamageEvent;
		HitActor->TakeDamage(Damage, DamageEvent, GetController(), this);	
	}
	else
	{
		UE_LOG(LogComboAction, Warning, TEXT("No Hit"));
	}
}

float ALuckyCharacterBase::TakeDamage(float Damage, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
	Super::TakeDamage(Damage, DamageEvent, EventInstigator, DamageCauser);
	
	CurrentHp = CurrentHp - Damage;	// Apply Damage
	UE_LOG(LogHealth, Display, TEXT("Health: %f"), CurrentHp);

	if (CurrentHp <= 0)
	{
		UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
		GetCharacterMovement()->SetMovementMode(EMovementMode::MOVE_None);
		AnimInstance->StopAllMontages(1.0f);	
		AnimInstance->Montage_Play(DeadMontage);	
		SetActorEnableCollision(false);	

		FTimerHandle DeadTimerHandle;
		float DelayTime = 1.0f;
		GetWorld()->GetTimerManager().SetTimer(DeadTimerHandle, this, &ALuckyCharacterBase::Dead, 5.0f, false);	
	}
	return Damage;
}

void ALuckyCharacterBase::Dead()
{
	Destroy();
	UE_LOG(LogTemp, Error, TEXT("Dead"));
}

To explain a little bit more, if you left-click the current mouse, you’ll get the log. ComboTime logs come up. But this ComboTime only runs once, never after that.

IA_Jump & IA_Attack

IA_Look

IA_Move




IMC_DefaultMappingContext

I think the reason your character isn’t moving could be this line:

GetCharacterMovement()->SetMovementMode(EMovementMode::MOVE_None);

Try removing it and see if that fixes the issue.

Also, check if your character is dying due to multiple hit events being triggered simultaneously. If more than one ‘TakeDamage’ is being applied in the same combo, that might be causing the issue.

Where are you calling AttackHitCheck

AttackHitCheck makes a call on Notify. I wanted to cause damage at that animation point.
I’ve tried this and that because I’ve been asked elsewhere. I’m sorry I couldn’t tell you.

First of all, other people said that the input doesn’t seem to be working right now. So I did IMC and IA through blue print. The character blue print created IA for me, both moving and rotating.
What was the problem at this time was that I set up a log at the end of the IA. It was shown in the viewport. The character doesn’t move, but the log was shown in the viewport.

I just ran it and suddenly there was a problem with the deligate.

void ALuckyCharacterBase::ComboAttackStart()
{

	const float ComboAttackRate = 1.0f;	
	UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
	AnimInstance->Montage_Play(ComboAttackMontage, ComboAttackRate);

	FOnMontageEnded ComboEndDelegate;	// Here
	ComboEndDelegate.BindUObject(this, &ALuckyCharacterBase::ComboAttackEnd);
	AnimInstance->Montage_SetEndDelegate(ComboEndDelegate, ComboAttackMontage);

	ComboAttackTimer();
}

First of all, I’ve created a new project, moved the existing code, and re-created it. So fortunately, it’s possible to attack. Of course, I haven’t implemented the damage yet, but it’s working.
Thank you so much for your answer, I also think it would be better to do it there since the new project is working…

I think there’s something wrong with the input mapping.