Enemy Approaches but doesn't attack on Character respawn

Enemies behave normally when I start the game, but when I respawn, the enemies approach me but don’t attack me… why??

// Fill out your copyright notice in the Description page of Project Settings.

include “Enemy/Enemy.h”
include “Components/SkeletalMeshComponent.h”
include “GameFramework/CharacterMovementComponent.h”
include “Perception/PawnSensingComponent.h”
include “Component/AttributeComponent.h”
include “HUD/HealthBarComponent.h”
include “Components/CapsuleComponent.h”
include “Navigation/PathFollowingComponent.h”
include “Item/Weapon/Weapon.h”
include “AIController.h”
include “Character/SlashCharacter.h”

AEnemy::AEnemy()
{
PrimaryActorTick.bCanEverTick = true;

GetMesh()->SetCollisionObjectType(ECollisionChannel::ECC_WorldDynamic);
GetMesh()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Visibility, ECollisionResponse::ECR_Block);
GetMesh()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Camera, ECollisionResponse::ECR_Ignore);
GetMesh()->SetGenerateOverlapEvents(true);

HealthBarWidget = CreateDefaultSubobject<UHealthBarComponent>(TEXT("HealthBar"));
HealthBarWidget->SetupAttachment(GetRootComponent());

GetCharacterMovement()->bOrientRotationToMovement = true;
bUseControllerRotationPitch = false;
bUseControllerRotationYaw = false;
bUseControllerRotationRoll = false;

PawnSensing = CreateDefaultSubobject<UPawnSensingComponent>(TEXT("PawnSensing"));
PawnSensing->SightRadius = 4000.f;
PawnSensing->SetPeripheralVisionAngle(80.f);

}

void AEnemy::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);

if (IsDead()) return;
if (EnemyState > EEnemyState::EES_Patrolling)
{
	CheckCombatTarget();
}
else
{
	CheckPatrolTarget();
}

}

float AEnemy::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
HandleDamage(DamageAmount);
CombatTarget = EventInstigator->GetPawn();

if (IsInsideAttackRadius())
{
	EnemyState = EEnemyState::EES_Attacking;
}
else if (IsOutsideAttackRadius())
{
	ChaseTarget();
}

return DamageAmount;

}

void AEnemy::Destroyed()
{
if (EquippedWeapon)
{
EquippedWeapon->Destroy();
}
}

void AEnemy::GetHit_Implementation(const FVector& ImpactPoint, AActor* Hitter)
{
Super::GetHit_Implementation(ImpactPoint, Hitter);
if (!IsDead()) ShowHealthBar();
ClearPatrolTimer();
ClearAttackTimer();
SetWeaponCollisionEnabled(ECollisionEnabled::NoCollision);

StopAttackMontage();

}

void AEnemy::OnCharacterRespawn(ASlashCharacter* Character)
{
if (Character)
{
EnemyState = EEnemyState::EES_Attacking;
}
}

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

if (PawnSensing) PawnSensing->OnSeePawn.AddDynamic(this, &AEnemy::PawnSeen);
InitializeEnemy();
Tags.Add(FName("Enemy"));

}

void AEnemy::Die()
{
Super::Die();

EnemyState = EEnemyState::EES_Dead;
ClearAttackTimer();
HideHealthBar();
DisableCapsule();
SetLifeSpan(DeathLifeSpan);
GetCharacterMovement()->bOrientRotationToMovement = false;
SetWeaponCollisionEnabled(ECollisionEnabled::NoCollision);

}

void AEnemy::Attack()
{
Super::Attack();
if (CombatTarget == nullptr) return;

EnemyState = EEnemyState::EES_Engaged;
PlayAttackMontage();

}

bool AEnemy::CanAttack()
{
bool bCanAttack =
IsInsideAttackRadius() &&
!IsAttacking() &&
!IsEngaged() &&
!IsDead();
return bCanAttack;
}

void AEnemy::AttackEnd()
{
EnemyState = EEnemyState::EES_NoState;
CheckCombatTarget();
}

void AEnemy::HandleDamage(float DamageAmount)
{
Super::HandleDamage(DamageAmount);

if (Attributes && HealthBarWidget)
{
	HealthBarWidget->SetHealthPercent(Attributes->GetHealthPercentage());
}

}

AActor* AEnemy::ChoosePatrolTarget()
{
TArray<AActor*> ValidTargets;
for (AActor* Target : PatrolTargets)
{
if (Target != PatrolTarget)
{
ValidTargets.AddUnique(Target);
}
}

const int32 NumPatrolTargets = ValidTargets.Num();
if (NumPatrolTargets > 0)
{
	const int32 TargetSelection = FMath::RandRange(0, NumPatrolTargets - 1);
	return ValidTargets[TargetSelection];
}
return nullptr;

}

void AEnemy::CheckCombatTarget()
{
if (IsOutsideCombatRadius())
{
ClearAttackTimer();
LoseInterest();
if (!IsEngaged()) StartPatrolling();
}
else if (IsOutsideAttackRadius() && !IsChasing())
{
ClearAttackTimer();
if (!IsEngaged()) ChaseTarget();
}
else if (CanAttack())
{
StartAttackTimer();
}
}

void AEnemy::PatrolTimerFinished()
{
MoveToTarget(PatrolTarget);
}

void AEnemy::HideHealthBar()
{
if (HealthBarWidget)
{
HealthBarWidget->SetVisibility(false);
}
}

void AEnemy::ShowHealthBar()
{
if (HealthBarWidget)
{
HealthBarWidget->SetVisibility(true);
}
}

void AEnemy::LoseInterest()
{
CombatTarget = nullptr;
HideHealthBar();
}

void AEnemy::StartPatrolling()
{
EnemyState = EEnemyState::EES_Patrolling;
GetCharacterMovement()->MaxWalkSpeed = PatrollingSpeed;
MoveToTarget(PatrolTarget);
}

void AEnemy::ChaseTarget()
{
EnemyState = EEnemyState::EES_Chasing;
GetCharacterMovement()->MaxWalkSpeed = ChasingSpeed;
MoveToTarget(CombatTarget);
}

bool AEnemy::IsOutsideCombatRadius()
{
return !InTargetRange(CombatTarget, CombatRadius);
}

bool AEnemy::IsOutsideAttackRadius()
{
return !InTargetRange(CombatTarget,AttackRadius);
}

bool AEnemy::IsInsideAttackRadius()
{
return InTargetRange(CombatTarget, AttackRadius);
}

bool AEnemy::IsChasing()
{
return EnemyState == EEnemyState::EES_Chasing;
}

bool AEnemy::IsAttacking()
{
return EnemyState == EEnemyState::EES_Attacking;
}

bool AEnemy::IsDead()
{
return EnemyState == EEnemyState::EES_Dead;
}

bool AEnemy::IsEngaged()
{
return EnemyState == EEnemyState::EES_Engaged;
}

void AEnemy::ClearPatrolTimer()
{
GetWorldTimerManager().ClearTimer(PatrolTimer);
}

void AEnemy::PawnSeen(APawn* SeenPawn)
{
const bool bShouldChaseTarget =
EnemyState != EEnemyState::EES_Dead &&
EnemyState != EEnemyState::EES_Chasing &&
EnemyState < EEnemyState::EES_Attacking &&
SeenPawn->ActorHasTag(FName(“EngageableTarget”));

if (bShouldChaseTarget)
{
	CombatTarget = SeenPawn;
	ClearPatrolTimer();
	ChaseTarget();
}

}

void AEnemy::StartAttackTimer()
{
EnemyState = EEnemyState::EES_Attacking;
const float AttackTime = FMath::RandRange(AttackMin, AttackMax);
GetWorldTimerManager().SetTimer(AttackTimer, this, &AEnemy::Attack, AttackTime);
}

void AEnemy::ClearAttackTimer()
{
GetWorldTimerManager().ClearTimer(AttackTimer);
}

void AEnemy::SpawnDefaultWeapon()
{
UWorld* World = GetWorld();
if (World && WeaponClass)
{
AWeapon* DefaultWeapon = World->SpawnActor(WeaponClass);
DefaultWeapon->Equip(GetMesh(), FName(“WeaponSocket”), this, this);
DefaultWeapon->IgnoreActors.Emplace(this);
EquippedWeapon = DefaultWeapon;
}
}

bool AEnemy::InTargetRange(AActor* Target, double Radius)
{
if (Target == nullptr) return false;
const double DistanceToTarget = (Target->GetActorLocation() - GetActorLocation()).Size();
return DistanceToTarget <= Radius;
}

void AEnemy::MoveToTarget(AActor* Target)
{
if (EnemyController == nullptr || Target == nullptr) return;
FAIMoveRequest MoveRequest;
MoveRequest.SetGoalActor(Target);
MoveRequest.SetAcceptanceRadius(AcceptanceRadius);
EnemyController->MoveTo(MoveRequest);
}

void AEnemy::InitializeEnemy()
{
EnemyController = Cast(GetController());
MoveToTarget(PatrolTarget);
HideHealthBar();
SpawnDefaultWeapon();
}

void AEnemy::CheckPatrolTarget()
{
if (InTargetRange(PatrolTarget, PatrolRadius))
{
PatrolTarget = ChoosePatrolTarget();
const float WaitTime = FMath::RandRange(PatrolWaitMin, PatrolWaitMax);
GetWorldTimerManager().SetTimer(PatrolTimer, this, &AEnemy::PatrolTimerFinished, WaitTime);
}
}

Set a breakpoint on your setting of CanAttack and see what the functions returned. Should get you in the right direction.

it crashed when they approached me(attacking distance) where do I go from here?

I’ve only played with breakpoints once before so I don’t know much

my CanAttack works fine up until my Character dies and respawns

void ASlashCharacter::Respawn()
{
SetActorLocation(RespawnLocation);
Attributes->GetHealthPercentage();
SlashOverlay->SetHealthBarPercent(1.0f);
Attributes->Health = 100.f;
ActionState = EActionState::EAS_Unoccupied;

GetMesh()->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
GetMesh()->SetGenerateOverlapEvents(true);

NotifyEnemiesOfRespawn();

}

This is the part of my character code that respawns.

I would recommend getting breakpoints working first and understanding them well. If you’re going to be doing much programming at all for the game, it will save you hundreds of hours of work and cause you to learn exponentially faster.

Did a quick click through of this video and it seems to cover a lot of the core concepts.

1 Like

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