목차
- 타이머 만들기
- 타이머에 맞춰서 에너미 패트롤 시키기
1. 타이머 만들기
타이머를 만들기 위해서는 FTimerHandle 구조체가 필요하다. 타이머핸들은 타이머를 관리하는 데 사용되는 구조체라고 한다.
class PRACTICE_API AEnemy : public ACharacter, public IHitInterface
{
// 생략
private:
FTimerHandle PatrolTimer; // 타이머 핸들
void PatrolTimerFinished(); // 콜백함수
}
타이머 핸들과 타이머가 다 되면 실행할 함수를 선언해주었다. 이제 함수를 정의해보자.
void AEnemy::PatrolTimerFinished()
{
if (EnemyController && PatrolTarget)
{
FAIMoveRequest MoveRequest;
MoveRequest.SetGoalActor(PatrolTarget);
MoveRequest.SetAcceptanceRadius(15.f);
EnemyController->MoveTo(MoveRequest);
}
}
함수의 내용은 그저 타이머가 다 되면 이동시키는 역할을 한다.
이제 함수를 다시보면 안에 구문을 무려 3곳에서 사용한다는 것을 알 수 있고 앞으로 더 많은 곳에서 사용할 가능성이 있다.
이 부분을 따로 함수로 다시 만들어주자.
void MoveToTarget(AActor* Target);
void AEnemy::MoveToTarget(AActor* Target)
{
if (EnemyController == nullptr || Target == nullptr) return;
FAIMoveRequest MoveRequest;
MoveRequest.SetGoalActor(Target);
MoveRequest.SetAcceptanceRadius(15.f);
EnemyController->MoveTo(MoveRequest);
}
이제 이 구문을 쓰고 있던 부분을 함수로 고쳐주면 된다.
이렇게 함수를 리팩터링하고 이제 사용하도록 하자. 타이머를 사용하려고 한다.
BeginPlay()로 들어가보자.
void AEnemy::BeginPlay()
{
Super::BeginPlay();
if (HealthBarWidget)
{
HealthBarWidget->SetVisibility(false);
}
EnemyController = Cast<AAIController>(GetController());
//MoveToTarget(PatrolTarget);
GetWorldTimerManager().SetTimer(PatrolTimer, this, &AEnemy::PatrolTimerFinished, 5.f);
}
이렇게 하면 에너미가 게임 시작 후 5초 후에 움직인다.
2. 타이머에 맞춰서 에너미 패트롤 시키기
이제 에너미를 패트롤 시킬 차례이다. BeginPlay에서 주석으로 처리했던 부분은 다시 돌려놓고 밑에 타이머를 세팅했던 부분은 지우도록 하자.
void AEnemy::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (CombatTarget)
{
if (!InTargetRange(CombatTarget, CombatRadius))
{
CombatTarget = nullptr;
if (HealthBarWidget)
{
HealthBarWidget->SetVisibility(false);
}
}
}
if (InTargetRange(PatrolTarget, PatrolRadius))
{
PatrolTarget = ChoosePatrolTarget();
GetWorldTimerManager().SetTimer(PatrolTimer, this, &AEnemy::PatrolTimerFinished, 5.f);
}
}
Tick 함수에서 에너미를 이동시키던 부분에서 콜백함수를 호출하면 된다. (에너미를 이동시키는 부분은 리팩터링을 통해 간소화 하였다.)
지금은 5초 마다 함수를 호출하지만 이 시간을 랜덤으로 지정하고 싶다. 랜덤한 시간값을 얻을 수 있게 헤더파일에서 최소 시간과 최대 시간을 지정하자.
UPROPERTY(EditAnywhere, Category = "AI Navigation")
float WaitMin = 5.f;
UPROPERTY(EditAnywhere, Category = "AI Navigation")
float WaitMax = 10.f;
void AEnemy::CheckPatrolTarget()
{
if (InTargetRange(PatrolTarget, PatrolRadius))
{
PatrolTarget = ChoosePatrolTarget();
const float WaitTime = FMath::RandRange(WaitMin, WaitMax);
GetWorldTimerManager().SetTimer(PatrolTimer, this, &AEnemy::PatrolTimerFinished, WaitTime);
}
}
랜덤 시간을 부르고 순찰하게 바꾸었다.
이렇게 해서 순찰 기능을 완성하였다. 다음에는 에너미가 캐릭터 발견시 캐릭터를 쫒아오도록 만들어 볼 것이다.
'게임프로그래밍 > 실습1' 카테고리의 다른 글
[언리얼 실습] 60. 에너미의 순찰, 추격, 공격 상태 구분하기 (0) | 2024.11.05 |
---|---|
[언리얼 실습] 59. 에너미가 플레이어 발견시 반응하기 (0) | 2024.11.05 |
[언리얼 실습] 57. 에너미 실제로 패트롤 시키기 (0) | 2024.11.04 |
[언리얼 실습] 56. 에너미 패트롤 하기. (0) | 2024.11.04 |
[언리얼 실습] 55. 블랜드스페이스를 통해 에너미의 속도에 따른 애니메이션 구현하기 (0) | 2024.11.04 |