해당 범위 내에 플레이어가 들어오면 이를 감지하는 적Enemy를 구현해보았습니다.
다음과 같이 4마리의 적을 만들었습니다.
<Tower.cpp>
bool ATower::InFireRange() {
if (Tank == nullptr)
return false;
float Distance = FVector::Dist(GetActorLocation(), Tank->GetActorLocation());
return Distance <= FireRange;
}
위와 같이 적들의 위치(GetActorLocation)와 플레이어의 Pawn(Tank->GetActorLocation)의 거리를 FVector::Dist로 구하고 사정거리 내에 있는지 여부를 반환합니다. 이를 Tick에 넣어줍니다.
<BasePawn.cpp>
void ATower::Tick(float deltaTime) {
Super::Tick(deltaTime);
if (InFireRange())
RotateTurret(Tank->GetActorLocation());
}
void ABasePawn::RotateTurret(FVector LookAtTarget) {
FVector ToTarget = LookAtTarget - TurretMesh->GetComponentLocation();
FRotator LookAtRotation = FRotator(0.f, ToTarget.Rotation().Yaw, 0.f);
TurretMesh->SetWorldRotation(
FMath::RInterpTo(
TurretMesh->GetComponentRotation(),
LookAtRotation,
UGameplayStatics::GetWorldDeltaSeconds(this),
15.f)
);
}
이렇게 하면 플레이어가 감지되었을 경우 적의 Rotation이 플레이어 쪽으로 바라보게 될 겁니다.
공격 기능
void ABasePawn::Fire() {
FVector ProjectileSpawnPointLocation = ProjectileSpawnPoint->GetComponentLocation();
DrawDebugSphere(
GetWorld(),
ProjectileSpawnPointLocation,
25.f,
12,
FColor::Red,
false,
3.f
);
}
공격 기능을 임시로 DrawDebugSphere를 통해 구현했습니다.
다음으로는 플레이어가 감지되었을 경우 적이 2초에 한 번씩 플레이어를 공격하도록 해봅니다.
<Tower.cpp>
void ATower::BeginPlay() {
Super::BeginPlay();
GetWorldTimerManager().SetTimer(FireRateTimerHandle, this, &ATower::CheckFireCondition, FireRate, true);
}
void ATower::CheckFireCondition() {
if (InFireRange()) {
Fire();
}
}
이렇게 BeginPlay에서 GetWorldTimerManager().SetTimer()를 사용하여 FireRate초마다 반복 공격하도록 합니다.
그런데 이렇게 하면 적이 여러 마리 있을 때, 플레이어가 각각 다른 타이밍에 적들의 사정거리 안으로 들어가더라도 적들은 모두 같은 타이밍에 공격을 수행하게 됩니다.
이는 World Timer, 즉 적들이 모두 같은 타이머를 사용하기 때문입니다.
이를 해결하기 위해 Tick으로 적들이 플레이어를 감지하도록 하고, 감지될 때마다 World Timer를 작동시키도록 합니다. 또, Tick마다 Timer가 여러 번 작동되면 안 되기 때문에 bool 변수 IsDetected로 한 번만 사용하도록 구현했습니다.
void ATower::Tick(float deltaTime) {
Super::Tick(deltaTime);
if (InFireRange()) {
RotateTurret(Tank->GetActorLocation());
if (!IsDetected) {
IsDetected = true;
GetWorldTimerManager().SetTimer(FireRateTimerHandle, this, &ATower::CheckFireCondition, FireRate, true);
}
}
else {
IsDetected = false;
}
}
이렇게 하면 처음 플레이어가 감지될 경우 한 번만 Timer를 작동시키고, 플레이어가 사정거리 밖으로 나가면 IsDetected를 false로 설정하여 또 다시 감지를 대기합니다.
플레이어가 적의 사정거리 안에 들어오면 적의 시선이 플레이어에게 향하도록 구현했고, 아직은 미흡하지만 Timer를 사용한 공격기능까지 구현해보았습니다.
'언리얼 엔진5' 카테고리의 다른 글
[UE5] 무기 장착하기 (0) | 2025.03.27 |
---|---|
[UE5] 타이머 설정하기 (0) | 2025.03.27 |
[UE5] C++ 클래스에서 컴포넌트 구성하기 (0) | 2025.03.27 |