์ํฝ ๋ชฌ์คํฐ๋ ์ผ๋ฐ ๋ชฌ์คํฐ๋ณด๋ค ์ ํฌ ํจํด์ด ๊ธธ๊ณ , ํ๋ ์ด์ด๊ฐ ํน์ ์กฐ๊ฑด์ ๋ง์กฑํ์ ๋ ๊ทธ๋ก๊ธฐ ์ํ๋ก ์ง์ ํ๋ ๊ตฌ์กฐ๊ฐ ํ์ํ๋ค.
๊ธฐ์กด NormalMonsterHealthBarComponent๋ HP๋ง ํ์ํ๊ณ ์์๊ธฐ ๋๋ฌธ์, ๊ทธ๋ก๊ธฐ ๋์ ์ํ๋ ๋ณ๋ ์ปดํฌ๋ํธ๋ก ๋ถ๋ฆฌํ๋ค.
EpicMonsterGroggyComponent๋ฅผ ์ถ๊ฐํด ๊ฐ๊ณต๊ฒฉ ํผ๊ฒฉ ํ์๋ฅผ ๋์ ํ๊ณ , ์ผ์ ํ์ ์ด์ ๋์ ๋๋ฉด GameplayEvent.GroggyTrigger๋ฅผ ๋ฐ์์ํค๋๋ก ํ๋ค.
GAS์ OnGameplayEffectAppliedDelegateToSelf๋ฅผ ๊ตฌ๋
ํ๊ณ , ์ ์ฉ๋ GE์ DynamicAssetTags์ Attack.Type.Heavy๊ฐ ์๋์ง ํ์ธํ๋ ๋ฐฉ์์ผ๋ก ๊ฐ๊ณต๊ฒฉ์ ํ์ ํ๋ค.
if (Spec.DynamicAssetTags.HasTag(RetrieveGameplayTags::Attack_Type_Heavy))
{
OnHeavyAttackReceived();
}
๊ทธ๋ก๊ธฐ ์ข
๋ฃ๋ State.Enemy.Groggy ํ๊ทธ ๋ณํ ์ฝ๋ฐฑ์ผ๋ก ๊ฐ์งํ๋ค.
GAS์์ ํน์ ๊ณต๊ฒฉ ํ์
์ ๊ตฌ๋ถํ ๋ GE ํด๋์ค๋ฅผ ๋๋ฆฌ๋ ๊ฒ๋ณด๋ค DynamicAssetTags ๊ธฐ๋ฐ์ผ๋ก ๋ถ๊ธฐํ๋ ๋ฐฉ์์ด ๋ ์ ์ฐํ๋ค.
์ํฝ ๋ชฌ์คํฐ๋ HP๋ฟ ์๋๋ผ ๊ทธ๋ก๊ธฐ ๋์ ์ํ๋ UI์ ํ์ํด์ผ ํ๋ค.
ํ์ง๋ง ๋ชจ๋ ๋ชฌ์คํฐ๊ฐ ๊ทธ๋ก๊ธฐ ๊ฒ์ด์ง๋ฅผ ๊ฐ์ง๋ ๊ฒ์ ์๋๋ฏ๋ก, ์ผ๋ฐ ๋ชฌ์คํฐ UI ๊ตฌ์กฐ๋ฅผ ํฌ๊ฒ ๋ฐ๊พธ์ง ์๊ณ ํ์ฅํ ํ์๊ฐ ์์๋ค.
NormalMonsterHealthBarComponent์์ EpicMonsterGroggyComponent๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ์๋ง ๊ทธ๋ก๊ธฐ ๊ฒ์ด์ง ์
๋ฐ์ดํธ ๋ธ๋ฆฌ๊ฒ์ดํธ๋ฅผ ๋ฐ์ธ๋ฉํ๋ค.
UEpicMonsterGroggyComponent* GroggyComp =
GetOwner()->FindComponentByClass<UEpicMonsterGroggyComponent>();
if (GroggyComp)
{
GroggyComp->OnGroggyGaugeUpdated.AddDynamic(
this, &UNormalMonsterHealthBarComponent::HandleGroggyGaugeUpdated);
}
์ปดํฌ๋ํธ ์กด์ฌ ์ฌ๋ถ๋ฅผ ๊ธฐ๋ฅ ํ์ฑํ ์กฐ๊ฑด์ผ๋ก ์ฌ์ฉํ๋ฉด ์ผ๋ฐ ๋ชฌ์คํฐ์ ์ํฝ ๋ชฌ์คํฐ๋ฅผ ๋ณ๋ ํด๋์ค๋ก ๊ณผํ๊ฒ ๋ถ๋ฆฌํ์ง ์์๋ ๋๋ค.
๋๋๊ณค์ ์ผ๋ฐ ๋ชฌ์คํฐ์ ๋์ผํ๊ฒ DT_MonsterData, DT_MonsterPattern, StateTree ๊ธฐ๋ฐ์ผ๋ก ๋์ํด์ผ ํ๋ค.
์ด๊ธฐ์๋ ๋๋๊ณค ์ ์ฉ ์ ๋๋ฉ์ด์ ์ํ์ค, ํํธ๋ฐ์ค ํ์ด๋ฐ, ๊ณต์ค ํ์ด์ฆ ์ฌ๋ถ ๋ฑ์ ๋ฐ์ดํฐ ํ ์ด๋ธ ํ๋๋ก ํ์ฅํ๋ ๋ฐฉํฅ๋ ๊ฒํ ํ๋ค.
ํ๋ก์ ํธ ๊ธฐ์ค์ ๊ธฐ์กด DT_MonsterData, DT_MonsterPattern ๊ตฌ์กฐ๋ฅผ ๊ณ ์ ํ๊ธฐ๋ก ํ๊ธฐ ๋๋ฌธ์, ์ต์ข
๊ตฌํ์์๋ ๋ฐ์ดํฐ ํ
์ด๋ธ ๊ตฌ์กฐ๋ฅผ ๋ณ๊ฒฝํ์ง ์์๋ค.
๋์ ๋๋๊ณค ์ ์ฉ ์์ธ๋ RowName ๊ธฐ๋ฐ ๋ฐํ์ ๋ณด์ ์ผ๋ก ์ฒ๋ฆฌํ๋ค.
์๋ฅผ ๋ค์ด Dragon_Bite๋ AttackMontage๊ฐ ์์ด๋ ์ฝ๋์์ ๋๋๊ณค ๋ฐ์ดํธ ์ํ์ค๋ฅผ ๋์ ๋ชฝํ์ฃผ๋ก ์ฌ์ํ๋๋ก ํ๋ค.
Polygonal_Dragon_AnimationBite_Attack
HitboxStartTime = 0.38f
HitboxDuration = 0.28f
๊ณต์ฉ ๋ฐ์ดํฐ ํ ์ด๋ธ์ ์ฌ๋ฌ ๋ชฌ์คํฐ๊ฐ ์์กดํ๋ฏ๋ก, ํน์ ๋ชฌ์คํฐ ์๊ตฌ์ฌํญ๋ง ๋ณด๊ณ ๊ตฌ์กฐ๋ฅผ ํ์ฅํ๋ฉด ์ ์ง๋ณด์ ๋น์ฉ์ด ์ปค์ง ์ ์๋ค.
DT_MonsterPattern.csv ๋ฆฌ์ํฌํธ ์ค ๋ค์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
Row has more cells than properties, is there a malformed string?
์์ธ์ bCanTriggerGroggy์ HitboxBoneName ์ฌ์ด์ ๋น ์ปฌ๋ผ ๊ฐ์๊ฐ ๋ง์ง ์์๊ธฐ ๋๋ฌธ์ด๋ค.
Header:
..., bCanBeParried, bCanTriggerGroggy, CounterEventTag, RequiredElementTag, RequiredActionTag, HitboxBoneName, ...
CounterEventTag, RequiredElementTag, RequiredActionTag 3๊ฐ ๋น ๊ฐ์ ํํํด์ผ ํ๋๋ฐ ์ผํ ๊ฐ์๊ฐ ์๋ชป๋์ด ํ ์ ์ฒด๊ฐ ๋ฐ๋ ธ๋ค.
UE DataTable CSV ์ค๋ฅ์์ more cells than properties๊ฐ ๋์ค๋ฉด ์ค์ ๊ฐ๋ณด๋ค ๋น ์
๊ฐ์๋ฅผ ๋จผ์ ํ์ธํด์ผ ํ๋ค.
์ํฝ ๋ชฌ์คํฐ์ฉ ๋ธ๋ฃจํ๋ฆฐํธ์ ๊ทธ๋ก๊ธฐ ์ปดํฌ๋ํธ์ ๋ฐ์ดํฐ Row ์ค์ ์ ์ ์ฉํ๋ค.
| BP | ์์ |
|---|---|
BP_Dragon | GroggyComponent ์ถ๊ฐ, ๋๋๊ณค ๋ฐ์ดํฐ ์ฐ๊ฒฐ |
BP_Treant | RetrieveEnemyCharacter ๊ธฐ๋ฐ ์ ๊ท ๊ตฌ์ฑ, Treant_Water Row ์ฐ๊ฒฐ |
BP_Magma | RetrieveEnemyCharacter ๊ธฐ๋ฐ ์ ๊ท ๊ตฌ์ฑ, Magma_Fire Row ์ฐ๊ฒฐ |
๋ธ๋ฃจํ๋ฆฐํธ CDO ์ค์ ์ค DataRowName ํ๋กํผํฐ๋ฅผ ์ฐพ์ง ๋ชปํ๋ ๋ฌธ์ ๊ฐ ์์๋ค.
์ค์ ํ๋กํผํฐ๋ช
์ MonsterDataRowName์ด์๋ค.
๋ธ๋ฃจํ๋ฆฐํธ CDO๋ฅผ ์๋ํ๋ก ์์ ํ ๋๋ ์ถ์ธกํ ์ด๋ฆ์ ์ฐ๊ธฐ๋ณด๋ค ์ค์ CDO ํ๋กํผํฐ ๋ชฉ๋ก์ ๋จผ์ ํ์ธํด์ผ ํ๋ค.
StateTreeTask_EnemyAerialPhase์์ ๋๋๊ณค ๊ณต์ค ํ์ด์ฆ ์ง์
/๋ณต๊ท ์ SetAerialMode()๋ฅผ ํธ์ถํ์ง๋ง, ๋จธ์ง ๊ณผ์ ์์ ํด๋น ํจ์๊ฐ ๋๋ฝ๋์ด ๋น๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
ARetrieveEnemyCharacter์ SetAerialMode(bool bAerial)์ ์ถ๊ฐํ๋ค.
if (bAerial)
{
MoveComp->SetMovementMode(MOVE_Flying);
MoveComp->GravityScale = 0.f;
}
else
{
MoveComp->GravityScale = DefaultGravityScale;
MoveComp->SetMovementMode(MOVE_Falling);
}
์ฐฉ์ง ์์๋ MOVE_Falling์์ ์ง๋ฉด ๊ฐ์ง ํ ์์ฐ์ค๋ฝ๊ฒ MOVE_Walking์ผ๋ก ๋์๊ฐ๋๋ก ํ๋ค.
๊ณต์ค ํ์ด์ฆ ์ข
๋ฃ ์ ๋ฐ๋ก MOVE_Walking์ผ๋ก ๋๋ฆฌ๋ ๊ฒ๋ณด๋ค MOVE_Falling์ ๊ฑฐ์ณ CharacterMovement์ ์ง๋ฉด ๊ฐ์ง๋ฅผ ํ์ฉํ๋ ํธ์ด ์์ฐ์ค๋ฝ๋ค.
๋๋๊ณค์ด ํ๋ ์ด์ด๋ฅผ ์ธ์ํ๊ณ ๊ณต๊ฒฉ ๋ชจ์ ์ ์ํํ์ง๋ง ์ค์ ๋ฐ๋ฏธ์ง๊ฐ ๋ค์ด๊ฐ์ง ์์๋ค.
์์ธ์ Dragon_Bite ํํธ๋ฐ์ค๊ฐ Head ๋ณธ์ ๋ถ๋๋ก ๋์ด ์์์ง๋ง, ์ค์ ๋๋๊ณค ์ค์ผ๋ ํค์ ๋จธ๋ฆฌ ๋ณธ์ RigHead์๊ธฐ ๋๋ฌธ์ด๋ค.
Dragon_Bite์ ํํด ๋ฐํ์ ๋ณด์ ์ผ๋ก ํํธ๋ฐ์ค ๋ณธ๊ณผ ํ์ ํฌ๊ธฐ๋ฅผ ์กฐ์ ํ๋ค.
HitboxBoneName = RigHead
HitboxRadius = 200
HitboxOffset = (130, 0, 0)
MaxActivationRange = 520
๋ํ ๋๋๊ณค ๋ฉ์ ํฌ๊ธฐ์ ๋ง๊ฒ ์บก์ ํฌ๊ธฐ์ ๋ฉ์ ์๋ ์์น๋ ๋ณด์ ํ๋ค.
CapsuleRadius = 170
CapsuleHalfHeight = 255
MeshRelativeLocation = (0, 0, -255)
๊ณต๊ฒฉ์ด ๋ง์ง ์๋ ๋ฌธ์ ๋ ๋ฐ๋ฏธ์ง ๋ก์ง๋ณด๋ค ๋จผ์ ํํธ๋ฐ์ค๊ฐ ์ค์ ์ค์ผ๋ ํค์ ์ฌ๋ฐ๋ฅธ ๋ณธ์ ๋ถ๋์ง ํ์ธํด์ผ ํ๋ค.
๋๋๊ณค์ด ๊ณต๊ฒฉ ์ ํ๋ ์ด์ด๋ฅผ ๋ฐ๋ผ๋ณผ ๋ ๋ฐ์ ์์ง์ด์ง ์๊ณ ๋ชธ๋ง ํ์ ํด ๋ถ์์ฐ์ค๋ฌ์ ๋ค.
๋ํ ์ฌ๋กฏ ์ด๋ ์ค ํ๋ ์ด์ด๋ฅผ ๋ฐ๋ผ๋ณธ ์ฑ ์์ผ๋ก ์ด๋ํด, ํฐ ๋ชธ์ง์ ๋๋๊ณค์ด ๋ฏธ๋๋ฌ์ง๋ ๊ฒ์ฒ๋ผ ๋ณด์๋ค.
๊ณต๊ฒฉ ์ง์ ๋ฐฉํฅ ์ ๋ ฌ ์ค์๋ ๋๋๊ณค์ ์ข/์ฐ ์คํธ๋ ์ดํ ์ ๋๋ฉ์ด์ ์ ์งง์ ๋์ ๋ชฝํ์ฃผ๋ก ์ฌ์ํ๋ค.
์ ์ฉ Turn-in-place ์ ๋๋ฉ์ด์
์ด ์์๊ธฐ ๋๋ฌธ์ ๊ธฐ์กด Strafe_Left_WO_Root, Strafe_Right_WO_Root๋ฅผ ๋ณด์กฐ ํด ์ ๋๋ฉ์ด์
์ผ๋ก ํ์ฉํ๋ค.
์ฌ๋กฏ ์ด๋๊ณผ ์ถ์ ์ด๋์์๋ ๋๋๊ณค์ ํํด ์คํธ๋ ์ดํ๋ฅผ ๋๊ณ ์ด๋ ๋ฐฉํฅ์ผ๋ก ํ์ ํ๋๋ก ํ๋ค.
bOrientRotationToMovement = true
bUseControllerDesiredRotation = false
ClearFocus()
MoveToLocation(..., bCanStrafe = false)
์ผ๋ฐ ๋ชฌ์คํฐ์๊ฒ ์์ฐ์ค๋ฌ์ด ์คํธ๋ ์ดํ ์ด๋๋ ๋ํ ๋ชฌ์คํฐ์๊ฒ๋ ์ด์ํ ์ ์๋ค. ๋ชฌ์คํฐ ์ฒดํ์ ๋ฐ๋ผ ํ์ ์ ์ฑ ๊ณผ ์ด๋ ์ ๋๋ฉ์ด์ ์ฌ์ฉ ๋ฐฉ์์ ๋ค๋ฅด๊ฒ ๊ฐ์ ธ๊ฐ์ผ ํ๋ค.
๋๋๊ณค ํน์๊ณต๊ฒฉ ํฌ์ฌ์ฒด๋ ํ๋ ์ด์ด๊ฐ ํจ๋งํ๋ฉด GameplayEvent.Parry.Success๊น์ง๋ ๋ฐ์ํ์ง๋ง, ํฌ์ฌ์ฒด๊ฐ ๋๋๊ณค์๊ฒ ๋๋์๊ฐ ๊ทธ๋ก๊ธฐ๋ฅผ ์ ๋ฐํ๋ ํ๋ฆ์ ์์๋ค.
๋ํ ๊ฐ๋์ธ๋ ๊ฐ์ EnemyProjectile์ ์ฌ์ฉํ ์ ์์ด, ๊ณตํต ํฌ์ฌ์ฒด์ ๋ฐ์ฌ ๊ธฐ๋ฅ์ ๋ฌด์กฐ๊ฑด ๋ฃ์ผ๋ฉด ๋ค๋ฅธ ๋ชฌ์คํฐ ๋์์ด ๊นจ์ง ์ ์์๋ค.
EnemyProjectile์๋ ๊ณตํต ๋ฐ์ฌ ๊ธฐ๋ฅ๋ง ์ถ๊ฐํ๊ณ , ๊ธฐ๋ณธ๊ฐ์ ๋นํ์ฑํํ๋ค.
GA_ShootProjectiles์์ ํ์ฌ ํจํด์ด Dragon_AerialFireball์ผ ๋๋ง ๋ฐ์ฌ ๊ธฐ๋ฅ์ ํ์ฑํํ๋ค.
if (IsDragonAerialFireballPattern())
{
Projectile->ConfigureReflection(AvatarActor);
}
ํจ๋ง ์ฑ๊ณต ์ ํฌ์ฌ์ฒด๋ ํ๊ดด๋์ง ์๊ณ ๋๋๊ณค ๋ฐฉํฅ์ผ๋ก ๋๋์๊ฐ๋ค.
๋ฐ์ฌ๋ ํฌ์ฌ์ฒด๊ฐ ๋๋๊ณค์๊ฒ ์ ์คํ๋ฉด PatternCounterComponent๋ฅผ ํตํด ์นด์ดํฐ/๊ทธ๋ก๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ํํ๋ค.
๊ณต์ฉ ํด๋์ค์ ๊ธฐ๋ฅ์ ์ถ๊ฐํ ๋๋ ๊ธฐ๋ฅ ์์ฒด์ ํ์ฑํ ์กฐ๊ฑด์ ๋ถ๋ฆฌํด์ผ ํ๋ค.
์ด๋ฒ ๊ฒฝ์ฐ EnemyProjectile์ ๋ฐ์ฌ ๊ธฐ๋ฅ์ ์ ๊ณต๋ง ํ๊ณ , ๋๋๊ณค ํจํด์์๋ง opt-in ๋ฐฉ์์ผ๋ก ์ผ๋ ๊ตฌ์กฐ๊ฐ ๊ฐ์ฅ ์์ ํ๋ค.
๋๋๊ณค์ ๊ธฐ์กด ๋ชฌ์คํฐ ์์คํ ์ ์ฌ์ฌ์ฉํด์ผ ํ์ง๋ง, ํฌ๊ธฐ์ ํจํด ํน์ฑ ๋๋ฌธ์ ์์ธ ์ฒ๋ฆฌ๊ฐ ํ์ํ๋ค.
๋ฐ์ดํฐ ํ
์ด๋ธ ๊ตฌ์กฐ๋ฅผ ํ์ฅํ๊ธฐ๋ณด๋ค Dragon_Bite, Dragon_AerialFireball ๊ฐ์ ํน์ RowName ๊ธฐ์ค์ผ๋ก ๋ฐํ์ ๋ณด์ ์ ์ ํํ๋ค.
๊ฐ๊ณต๊ฒฉ ๊ฐ์ง, ํจ๋ง ์ฑ๊ณต, ๊ทธ๋ก๊ธฐ ํธ๋ฆฌ๊ฑฐ ๋ชจ๋ GameplayTag๋ฅผ ๊ธฐ์ค์ผ๋ก ์ฐ๊ฒฐํ๋ค.
GE ์ข ๋ฅ๋ฅผ ๋๋ฆฌ๋ ๊ฒ๋ณด๋ค ํ๊ทธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ฆ์ ๋ถ๊ธฐํ๋ ์ชฝ์ด ๋ฐ์ดํฐ ๋๋ฆฌ๋ธ ๊ตฌ์กฐ์ ๋ ์ ๋ง์๋ค.
๋๋๊ณค์ ์ผ๋ฐ ๋ชฌ์คํฐ์ฒ๋ผ ์คํธ๋ ์ดํํ๋ฉด ์คํ๋ ค ๋ถ์์ฐ์ค๋ฝ๋ค.
๋ํ ๋ชฌ์คํฐ๋ ์ด๋ ๋ฐฉํฅ์ผ๋ก ๋ชธ์ ๋๋ฆฌ๊ณ ์ ์ง ์ ๋๋ฉ์ด์ ์ ์ฌ์ฉํ๋ ์ชฝ์ด ๋ ์์ ์ ์ด๋ค.
๋๋๊ณค๊ณผ ๊ฐ๋์ธ์ด ๊ฐ์ ํฌ์ฌ์ฒด ํด๋์ค๋ฅผ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์, ๋ฐ์ฌ ๊ธฐ๋ฅ์ ๊ธฐ๋ณธ ๋์์ผ๋ก ๋ฃ์ง ์์๋ค.
๊ณตํต ๊ธฐ๋ฅ์ EnemyProjectile์ ๋๋, Dragon_AerialFireball์์๋ง ๋ช
์์ ์ผ๋ก ์ผ๋ ๊ตฌ์กฐ๋ก ๋ค๋ฅธ ๋ชฌ์คํฐ์ ๋ํ ๋ถ์์ฉ์ ์ค์๋ค.