๐ Project Galaga ์์ํฉ๋๋ค.
Unreal C++๊ณผ ๊ฒ์์ํ์ ์ ๋ชฉํด์ ํ๋ก์ ํธ๋ฅผ ์งํํ์ต๋๋ค.
2024.05.04 ~ 2024.05.21์ ๊ฐ๋ฐ ๊ธฐ๊ฐ์ผ๋ก, ์ด 17์ผ ๋์ ๊ฐ๋ฐ์ ์๋ฃํ์์ต๋๋ค.
๊ฑฐ์ฐฝํ๊ฒ ์์ํ ํ๋ก์ ํธ๋ณด๋จ ์ง๊ธ๊น์ง ๋ฐฐ์ด ๊ฒ๋ค์ ์ข ํฉ์ ์ผ๋ก ์ฌ์ฉํด์ ๊ฒฐ๊ณผ๋ฌผ์ ๋ง๋ค์ด ๋ด๋ณด๊ฒ ๋ค๋ ๋ง์์ผ๋ก ์์ฑํ์์ต๋๋ค.
ํด๋น ์๋ฆฌ์ฆ์๋ ๊ฐ๋ฐ ์ผ์ง๋ฅผ ์ ๋ฆฌํ๋ฉฐ, ๊ฐ๋ฐ ๋ด์ฉ์ ๋ํ ์ค๋ช ๊ณผ ์ด์๋ฅผ ์ ๋ฆฌํ ์์ ์ ๋๋ค.
์ด๋ฒ์๋ ์ ์ ๋ํด์ ๊ตฌํํ ์ฌํญ์ ๋๋ค.
ํด๋น ๋ด์ฉ์ด ๊ฐ์ฅ ๊ฐ๋ฐ์ ์์ด์ ๊ฐ์ฅ ํฐ ์์๋ผ๊ณ ๋ณผ ์ ์์ต๋๋ค.
์ ์ ์ธํ๊ณผ ์ถฉ๋์ ํ๋ ์ด์ด์๋ ๋ฐ๋๋ก Overlap์ผ๋ก ๊ตฌํํด์ฃผ์์ต๋๋ค.
์ ์ ๋ฒฝ ๋ฐ์์ ์ด๋ํ์ฌ ๋ค์ด์์ผํ๊ณ , ํ๋ ์ด์ด์ ์ถฉ๋ ์ Overlap Event๋ฅผ ๋ฐ์ํ์ฌ ๋ฐ๋ฏธ์ง๋ฅผ ์ฃผ์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ ์ ํฌ๊ฒ 3๊ฐ์ง์ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
UENUM(BlueprintType)
enum class EEnemyType : uint8
{
Suiside,
Patrol,
Fixed,
PassBy,
Random,
InOut,
};
UENUM(BlueprintType)
enum class EEnemyAttackType : uint8
{
Suiside,
Front,
Target,
Spread,
Orbit,
Laser,
Wave,
Angle,
};
UENUM(BlueprintType)
enum class EEnemyFocus : uint8
{
Player,
TargetMP,
Front,
Back,
Center,
PlayerOnce,
};
๊ฐ ํจํด๋ค์ Enum Class๋ก ๊ตฌํํ์์ต๋๋ค.
์ ์์์ ์ฒด๋ ฅ, ๊ณต๊ฒฉ์๋, ์ด๋์๋ ๋ฑ์ ์์๋ฅผ EnemyStat์ ์นดํ
๊ณ ๋ฆฌ๋ก ๋ฌถ์ด ๊ฐ์ ๋ฃ์ด์ค ์ ์๋๋ก ํ์์ต๋๋ค.
์ ์ ์ ํ ์ํ ๊ธฐ๊ณ๋ฅผ ๊ฐ์ ธ ์ค์ ๋ Stat์ ๋ฐ๋ผ์ ํจํด์ด ์งํ๋๋๋ก ๊ตฌํํ์์ต๋๋ค.
Enemy FSM์ ์กํฐ ์ปดํฌ๋ํธ๋ก ์ ์ํ์ฌ ๊ฐ ์ํ๋ง๋ค Switch๋ฅผ ํตํด ํจํด ํจ์๊ฐ ๋์ํ๋๋ก ๊ตฌํํ์ต๋๋ค.
AEnemyBase::AEnemyBase()
{
fsm = CreateDefaultSubobject<UEnemyFSM>(TEXT("FSM"));
}
์ด๋ค ์ํ์ธ์ง์ ๋ฐ๋ผ ๊ฐ State ์คํํจ์๋ก ๋์ด ๊ฐ๋๋ก ํ์์ต๋๋ค.
void UEnemyFSM::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
switch (mState)
{
case EEnemyState::IDLE:
IdleState();
break;
case EEnemyState::MOVE:
MoveState();
break;
case EEnemyState::ATTACK:
AttackState();
break;
case EEnemyState::DIE:
DieState();
break;
default:
break;
}
}
}
์ด๋ค ์์ง์ ํจํด์ ๊ฐ์ก๋์ง์ ๋ฐ๋ผ ๊ฐ ์์ง์ ํจํด ํจ์๋ฅผ ์คํํ์์ต๋๋ค.
void UEnemyFSM::MoveState()
{
switch (me->GetMType())
{
case EEnemyType::Suiside:
SuisideMove();
break;
case EEnemyType::Patrol:
PatrolMove();
break;
case EEnemyType::Fixed:
FixedMove();
break;
case EEnemyType::PassBy:
PassByMove();
break;
case EEnemyType::Random:
RandomMove();
break;
case EEnemyType::InOut:
InOutMove();
break;
default:
break;
}
if (currentTime >= me->GetEnemyAttackSpeed())
{
SetAttackState();
}
}
์ด๋ค ๊ณต๊ฒฉ ํจํด์ ๊ฐ์ก๋์ง์ ๋ฐ๋ผ ๊ฐ ๊ณต๊ฒฉ ํจํด ํจ์๋ฅผ ์คํํ์์ต๋๋ค.
void UEnemyFSM::AttackState()
{
me->FireSound();
switch (me->GetMAttackType())
{
case EEnemyAttackType::Suiside:
SetMoveState();
break;
case EEnemyAttackType::Front:
FrontAttack();
break;
case EEnemyAttackType::Target:
TargetAttack();
break;
case EEnemyAttackType::Spread:
SpreadAttack();
break;
case EEnemyAttackType::Orbit:
OrbitAttack();
break;
case EEnemyAttackType::Laser:
me->laserEffect();
me->GetWorldTimerManager().SetTimer(LaserTimer, this, &UEnemyFSM::LaserAttack, 2.0f, false);
break;
case EEnemyAttackType::Wave:
WaveAttack();
break;
case EEnemyAttackType::Angle:
AngleAttack();
default:
break;
}
SetMoveState();
currentTime = 0.0f;
}
์ฌ๊ธฐ๊น์ง ์ ๊ตฌํ์ ๋ํ ๊ฐ์์
๋๋ค.
์์ง์ ํจํด, ๊ณต๊ฒฉ ํจํด, ํฌ์ปค์ค์ ๋ํด์ ๋ฐ๋ก ํฌ์คํ
ํ๊ฒ ์ต๋๋ค.