목차
- 에너미 상태 추가하기
- 에너미 공격 반복하기
1. 에너미 상태 추가하기
UENUM(BlueprintType)
enum class EEnemyState : uint8
{
EES_Patrolling UMETA(DisplayName = "Patrolling"),
EES_Chasing UMETA(DisplayName = "Chasing"),
EES_Attacking UMETA(DisplayName = "Attacking")
};
현재 에너미의 상태이다. 순찰, 추격, 공격으로 나누어져 있는데 공격 쪽을 좀 더 분화할 것이다. 공격을 하고있는 순간과 쿨다운 중이라 공격을 하지는 않지만 공격사거리 안에 있기 때문에 추격도 하지 않는 상태로 나눌 필요가 있다.
UENUM(BlueprintType)
enum class EEnemyState : uint8
{
EES_Dead UMETA(DisplayName = "Dead"),
EES_Patrolling UMETA(DisplayName = "Patrolling"),
EES_Chasing UMETA(DisplayName = "Chasing"),
EES_Attacking UMETA(DisplayName = "Attacking"),
EES_Engaged UMETA(DisplayName = "Engaged")
};
Engaged는 실제로 검을 휘두르는 상태가 될 것이고 Dead 상태는 말그대로 죽은 상태이다. 현재 에너미가 죽어도 애니메이션의 재생이 끝나지 않는다. 그래서 Dead 상태의 추가로 에너미가 살아있는지 아닌지를 확인할 것이다.
다만 이렇게 하면 불필요해지는 부분이 있다.
UENUM(BlueprintType)
enum class EDeathPose : uint8
{
// EDP_Alive UMETA(DisplayName = "Alive"), 제거
EDP_Death1 UMETA(DisplayName = "Death1"),
EDP_Death2 UMETA(DisplayName = "Death2"),
EDP_Death3 UMETA(DisplayName = "Death3"),
EDP_Death4 UMETA(DisplayName = "Death4"),
EDP_Death5 UMETA(DisplayName = "Death5"),
EDP_MAX UMETA(DisplayName = "MAX")
};
이제 더 이상 EDathPose 상태에서 살아있는지 아닌지 확인할 필요가 없다. 이걸 제거하면 애니메이션 블루프린트에서 현재 사용하기 있기 때문에 이 부분들을 수정해주어야 한다.
UPROPERTY(BlueprintReadOnly)
EDeathPose DeathPose;
UPROPERTY(BlueprintReadOnly)
EEnemyState EnemyState = EEnemyState::EES_Patrolling;
에너미 스테이트를 블루프린트에 노출시키고 데스포즈의 기본값 설정을 지운다. 이제 컴파일을 하고 애니메이션 블루프린트로 들어가 수정해주자.
이벤트 그래프로 들어가 에너미스테이트 변수를 새로 만들어준다.
이제 쓰레드에서 실제로 값을 저장해주자.
이제 애님그래프에서 조건을 바꿔주자
이제 에너미 스테이트에서 죽었는지 아닌지를 확인한다.
이렇게 하면 되긴 하는데 문제가 처음에 에너미가 죽어있는채로 시작한다. 정확한 원인은 잘 모르겠지만 아마 초기화 문제인것으로 추정되어 캐릭터 타입중 가장 최소의 값을 따로 만들어주었다.
UENUM(BlueprintType)
enum class EEnemyState : uint8
{
EES_NoState UMETA(DisplayName = "No State"),
EES_Dead UMETA(DisplayName = "Dead"),
EES_Patrolling UMETA(DisplayName = "Patrolling"),
EES_Chasing UMETA(DisplayName = "Chasing"),
EES_Attacking UMETA(DisplayName = "Attacking"),
EES_Engaged UMETA(DisplayName = "Engaged"),
};
EES_NoState 상태는 쓰일 일은 없지만 혹시라도 Dead 초기화 되는 것을 막아준다.
이제 상태도 추가했으니 에너미의 공격이 반복되게 바꿔보자.
2. 에너미 공격 반복하기
강의를 따라하다 보니 약간의 리펙터링이 있었다. 못보던 함수가 많이 추가되었지만 슈도코드라고 생각하고 진행하면 이해하는데는 문제 없을 듯 하다.
void AEnemy::CheckCombatTarget()
{
// 생략
}
else if (IsInSideAttackRadius() && !IsAttacking())
{
EnemyState = EEnemyState::EES_Attacking;
Attack();
}
}
현재 공격하는 부분은 위와 같다. 이제는 이렇게 단순히 시작하는 것이 아니라 타이머를 만들고 사용하고 싶다.
타이머를 사용하기 위해서는 타이머핸들을 만들어야 한다.
void StartAttackTimer();
FTimerHandle AttackTimer;
UPROPERTY(EditAnywhere, Category = "Combat")
float AttackMin = 0.2f;
UPROPERTY(EditAnywhere, Category = "Combat")
float AttackMax = 1.f;
타이머 핸들과 시간 변수를 만들고 타이머를 시작할 때 사용할 함수를 선언하였다.
이제 함수를 정의하자.
void AEnemy::StartAttackTimer()
{
EnemyState = EEnemyState::EES_Attacking;
const float AttackTime = FMath::RandRange(AttackMin, AttackMax);
GetWorldTimerManager().SetTimer(AttackTimer, this, &AEnemy::Attack, AttackTime);
}
함수를 정의했으면 이제 이 함수를 사용하면 된다.
void AEnemy::CheckCombatTarget()
{
if (IsOutSideCombatRadius())
{
ClearAttackTimer();
LoseInterast();
if (!IsEngaged()) StartPatrolling();
}
else if (IsOutSideAttackRadius() && !IsChasing())
{
ClearAttackTimer();
if (!IsEngaged()) ChaseTarget();
}
else if (IsInSideAttackRadius() && !IsAttacking())
{
StartAttackTimer();
}
}
공격 사거리 밖에 있으면 타이머를 초기화 해주는 작업도 추가하였다.
이렇게 하여 공격을 반복하게 하였다. 사실 아직도 문제점이 많다. 이 부분들은 계속해서 고치도록 하겠다.
'게임프로그래밍 > 실습1' 카테고리의 다른 글
[언리얼 실습] 68. 플레이어 캐릭터 히트 구현 (0) | 2024.11.08 |
---|---|
[언리얼 실습] 67. 에너미 Engage 상태로 만들기 (0) | 2024.11.07 |
[언리얼 실습] 65. 에너미 어택 몽타주 재생하기 (0) | 2024.11.06 |
[언리얼 실습] 64. 에너미에게 무기 쥐어주기 (0) | 2024.11.06 |
[언리얼 실습] 63. 자식 에너미 클래스 만들기 (0) | 2024.11.06 |