๐Ÿ“˜TIL - ์–ธ๋ฆฌ์–ผ AI ์ˆ ๋ž˜์žก๊ธฐ ์‹œ์Šคํ…œ ๊ตฌํ˜„ ๋ฐ AI ๊ฐ์ง€ ๊ตฌ์กฐ ํ™•์žฅ

HappyCircleยท2026๋…„ 5์›” 6์ผ

Unreal ๊ฐœ๋ฐœ

๋ชฉ๋ก ๋ณด๊ธฐ
122/163

๊ตฌํ˜„ ๋ฐฐ๊ฒฝ

์ด์ „์—๋Š” ์ˆ ๋ž˜/๋„๋ง์ž ์ƒํƒœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๊ฒŒ์ž„ ํ๋ฆ„๊ณผ AI ๊ตฌ์กฐ๋ฅผ ์„ค๊ณ„ํ•˜๋Š” ๋‹จ๊ณ„์˜€๋‹ค๋ฉด,
์˜ค๋Š˜์€ ์‹ค์ œ ์–ธ๋ฆฌ์–ผ C++ ์ฝ”๋“œ์™€ BehaviorTree๋ฅผ ์—ฐ๊ฒฐํ•ด์„œ
AI๊ฐ€ ์‹ค์ œ๋กœ ์ถ”์ ํ•˜๊ณ  ๋„๋ง๊ฐ€๋Š” ํ๋ฆ„์„ ๊ตฌํ˜„ํ•˜๋Š” ์ž‘์—…์„ ์ง„ํ–‰ํ–ˆ๋‹ค.


BTTask ๊ตฌํ˜„

์˜ค๋Š˜์€ BehaviorTree์—์„œ ์‚ฌ์šฉํ•  Task๋“ค์„ ์‹ค์ œ C++ ํด๋ž˜์Šค๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค.

BTTask_FindNearestRunner
BTTask_CalculateEscapeLocation
BTTask_TryCatchTarget

FindNearestRunner ๊ตฌํ˜„

์ˆ ๋ž˜ AI๊ฐ€ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋„๋ง์ž๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๋กœ์ง์ด๋‹ค.

ํ˜„์žฌ Pawn ๊ฐ€์ ธ์˜ค๊ธฐ
โ†’ IsTagger ํ™•์ธ
โ†’ ๋“ฑ๋ก๋œ ์บ๋ฆญํ„ฐ ์ˆœํšŒ
โ†’ ์ˆ ๋ž˜๊ฐ€ ์•„๋‹Œ ๋Œ€์ƒ๋งŒ ํ•„ํ„ฐ๋ง
โ†’ ๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ
โ†’ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋Œ€์ƒ ์„ ํƒ
โ†’ Blackboard TargetActor ์ €์žฅ

๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ์€ FVector::DistSquared ๊ธฐ๋ฐ˜์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์„œ
๋ถˆํ•„์š”ํ•œ sqrt ์—ฐ์‚ฐ์„ ์ค„์˜€๋‹ค.

const float DistSq = FVector::DistSquared(
    SelfLocation,
    CandidateLocation
);

Blackboard ์ €์žฅ์€ ์•„๋ž˜ ๋ฐฉ์‹์œผ๋กœ ์—ฐ๊ฒฐํ–ˆ๋‹ค.

Blackboard->SetValueAsObject(
    TEXT("TargetActor"),
    BestTarget
);

CalculateEscapeLocation ๊ตฌํ˜„

๋„๋ง์ž AI๋Š” ์ˆ ๋ž˜ ๋ฐ˜๋Œ€ ๋ฐฉํ–ฅ์œผ๋กœ ์ด๋™ํ•˜๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค.

ํ˜„์žฌ ์ˆ ๋ž˜ ์œ„์น˜ ๊ฐ€์ ธ์˜ค๊ธฐ
โ†’ ๋‚ด ์œ„์น˜์™€ ๋ฐฉํ–ฅ ๊ณ„์‚ฐ
โ†’ Normalize
โ†’ ์ผ์ • ๊ฑฐ๋ฆฌ๋งŒํผ ์ด๋™ ์œ„์น˜ ๊ณ„์‚ฐ
โ†’ NavMesh ๊ธฐ์ค€ ์œ„์น˜ ๋ณด์ •
โ†’ EscapeLocation ์ €์žฅ

ํ•ต์‹ฌ์€ ๋‹จ์ˆœ ๋ฐฉํ–ฅ ๊ณ„์‚ฐ๋งŒ ํ•˜์ง€ ์•Š๊ณ 
ProjectPointToNavigation()์œผ๋กœ ์‹ค์ œ ์ด๋™ ๊ฐ€๋Šฅํ•œ ์œ„์น˜๋ฅผ ์ฐพ๋Š” ๋ถ€๋ถ„์ด์—ˆ๋‹ค.

NavSys->ProjectPointToNavigation(
    RawEscapeLocation,
    ProjectedLocation
);

์ด ์ฒ˜๋ฆฌ๋ฅผ ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฒฝ์ด๋‚˜ ์žฅ์• ๋ฌผ ์ชฝ์œผ๋กœ ์ด๋™ ์œ„์น˜๊ฐ€ ์žกํžˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•˜๋‹ค.


BTService ๊ธฐ๋ฐ˜ ์žก๊ธฐ ์ฒ˜๋ฆฌ

์ฒ˜์Œ์—๋Š” MoveTo ์™„๋ฃŒ ํ›„ ์žก๊ธฐ ํŒ์ •์„ ์‹œ๋„ํ–ˆ๋Š”๋ฐ,
๋ฐ˜์‘์ด ๋А๋ ค์„œ ๊ตฌ์กฐ๋ฅผ ์ˆ˜์ •ํ–ˆ๋‹ค.

BTService_TryCatchTarget
โ†’ ์ผ์ • ์ฃผ๊ธฐ Tick
โ†’ TryCatchTarget() ํ˜ธ์ถœ
โ†’ CatchRange ์•ˆ์ด๋ฉด ์ฆ‰์‹œ ์žก๊ธฐ

์„œ๋น„์Šค Tick ๊ฐ„๊ฒฉ์€ ์•„๋ž˜์ฒ˜๋Ÿผ ์งง๊ฒŒ ์„ค์ •ํ–ˆ๋‹ค.

Interval = 0.15f;
RandomDeviation = 0.05f;

์ด ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋‹ˆ๊นŒ
์ถ”๊ฒฉ ๋„์ค‘์—๋„ ๊ณ„์† ์žก๊ธฐ ํŒ์ •์„ ์‹œ๋„ํ•ด์„œ
AI ๋ฐ˜์‘์ด ํ›จ์”ฌ ์ž์—ฐ์Šค๋Ÿฌ์›Œ์กŒ๋‹ค.


AI Perception ์ ์šฉ

์˜ค๋Š˜ ๊ตฌํ˜„์—์„œ ๊ฐ€์žฅ ํฐ ๋ถ€๋ถ„์€
AI ๊ฐ์ง€ ๊ตฌ์กฐ๋ฅผ ์‹ค์ œ๋กœ ๋ถ™์ธ ๋ถ€๋ถ„์ด์—ˆ๋‹ค.

UAIPerceptionComponent
UAISenseConfig_Sight
UAISenseConfig_Hearing

AIController์—์„œ PerceptionComponent๋ฅผ ์ƒ์„ฑํ•˜๊ณ ,
์‹œ์•ผ์™€ ์ฒญ๊ฐ ๊ฐ์ง€๋ฅผ ๊ฐ๊ฐ ์„ค์ •ํ–ˆ๋‹ค.

PerceptionComp->ConfigureSense(*SightConfig);
PerceptionComp->ConfigureSense(*HearingConfig);

์‹œ์•ผ ๊ฐ์ง€ ๊ตฌํ˜„

์ˆ ๋ž˜ AI๋Š” ์‹œ์•ผ ์•ˆ์— ๋„๋ง์ž๊ฐ€ ๋“ค์–ด์˜ค๋ฉด
TargetActor๋ฅผ Blackboard์— ์ €์žฅํ•˜๋„๋ก ํ–ˆ๋‹ค.

๋„๋ง์ž ๊ฐ์ง€
โ†’ WasSuccessfullySensed ํ™•์ธ
โ†’ Blackboard TargetActor ์ €์žฅ
โ†’ LastKnownRunnerLocation ์ €์žฅ
BB->SetValueAsObject(
    TEXT("TargetActor"),
    Actor
);

์‹œ์•ผ๋ฅผ ์žƒ์œผ๋ฉด TargetActor๋Š” ์ œ๊ฑฐํ•˜๊ณ ,
๋งˆ์ง€๋ง‰ ์œ„์น˜๋งŒ ์œ ์ง€ํ•˜๋„๋ก ์ฒ˜๋ฆฌํ–ˆ๋‹ค.

BB->ClearValue(TEXT("TargetActor"));

๋ฐœ์†Œ๋ฆฌ ๊ฐ์ง€ ๊ตฌํ˜„

๋„๋ง์ž๋Š” ์ด๋™ ์ค‘ ์ผ์ • ์†๋„ ์ด์ƒ์ด๋ฉด
Footstep Noise๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๋„๋ก ๊ตฌํ˜„ํ–ˆ๋‹ค.

์†๋„ ์ฒดํฌ
โ†’ Noise Timer ์ฆ๊ฐ€
โ†’ ์ผ์ • ์ฃผ๊ธฐ๋งˆ๋‹ค Noise ๋ฐœ์ƒ
โ†’ Hearing ๊ฐ์ง€
โ†’ LastHeardLocation ์ €์žฅ

Noise ๋ฐœ์ƒ์€ ์•„๋ž˜ ํ•จ์ˆ˜๋กœ ์ฒ˜๋ฆฌํ–ˆ๋‹ค.

UAISense_Hearing::ReportNoiseEvent(
    GetWorld(),
    GetActorLocation(),
    FootstepNoiseLoudness,
    this
);

์ด ๊ตฌ์กฐ ๋•๋ถ„์—
๊ตฌ์กฐ๋ฌผ ๋’ค์— ์ˆจ์–ด ์žˆ์–ด๋„ ๋›ฐ์–ด๋‹ค๋‹ˆ๋ฉด
์ˆ ๋ž˜ AI๊ฐ€ ์œ„์น˜๋ฅผ ์ถ”์ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋๋‹ค.


์€ํ ๊ตฌ์กฐ๋ฌผ ์ฒ˜๋ฆฌ

๊ตฌ์กฐ๋ฌผ ๋’ค์— ์ˆจ์„ ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋„ ๊ฐ™์ด ์ ์šฉํ–ˆ๋‹ค.

์ค‘์š”ํ–ˆ๋˜ ๋ถ€๋ถ„์€ Collision ์„ค์ •์ด์—ˆ๋‹ค.

Visibility = Block

์ด ์„ค์ •์ด ๋˜์–ด ์žˆ์–ด์•ผ
AI Sight LineTrace๊ฐ€ ๊ตฌ์กฐ๋ฌผ์— ๋ง‰ํžˆ๋ฉด์„œ
๋„๋ง์ž๊ฐ€ ์‹œ์•ผ์—์„œ ์‚ฌ๋ผ์กŒ๋‹ค.

๋ณ„๋„ ๋ณต์žกํ•œ ์ฝ”๋“œ ์—†์ด๋„
์–ธ๋ฆฌ์–ผ ๊ธฐ๋ณธ Perception ๊ตฌ์กฐ๋งŒ์œผ๋กœ ๊ฝค ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋™์ž‘ํ–ˆ๋‹ค.


Blackboard ํ™•์žฅ

๊ธฐ์กด Blackboard์— ์•„๋ž˜ Key๋“ค์„ ์ถ”๊ฐ€ํ–ˆ๋‹ค.

IsTagger
TargetActor
EscapeLocation
LastKnownRunnerLocation
LastHeardLocation

ํŠนํžˆ LastKnownRunnerLocation๊ณผ
LastHeardLocation์ด ๋“ค์–ด๊ฐ€๋ฉด์„œ
AI๊ฐ€ ๋‹จ์ˆœ ํ˜„์žฌ ์œ„์น˜๋งŒ ๋”ฐ๋ผ๊ฐ€๋Š” ๊ตฌ์กฐ์—์„œ ๋ฒ—์–ด๋‚˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค.


BehaviorTree ๊ตฌ์กฐ ์ˆ˜์ •

์ตœ์ข…์ ์œผ๋กœ๋Š” ์•„๋ž˜ ํ๋ฆ„์œผ๋กœ ์ •๋ฆฌํ–ˆ๋‹ค.

์ˆ ๋ž˜
โ†’ TargetActor ์žˆ์œผ๋ฉด ์ถ”๊ฒฉ
โ†’ ์ถ”๊ฒฉ ์ค‘ ๊ณ„์† ์žก๊ธฐ ์‹œ๋„
โ†’ ์•ˆ ๋ณด์ด๋ฉด ๋งˆ์ง€๋ง‰ ์œ„์น˜ ์ˆ˜์ƒ‰

๋„๋ง์ž
โ†’ ์ˆ ๋ž˜ ๋ฐ˜๋Œ€ ๋ฐฉํ–ฅ ๊ณ„์‚ฐ
โ†’ NavMesh ์œ„์น˜ ์ด๋™

MoveTo๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๋‹จ์ˆœ AI๋ณด๋‹ค
ํ›จ์”ฌ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋™์ž‘ํ•˜๋Š” ๋А๋‚Œ์ด ๋‚ฌ๋‹ค.


์˜ค๋Š˜์˜ ์ •๋ฆฌ

  • ์˜ค๋Š˜์€ ๋‹จ์ˆœ BehaviorTree ์„ค๊ณ„ ์ˆ˜์ค€์—์„œ ๋ฒ—์–ด๋‚˜,
    Perception๊ณผ Blackboard๋ฅผ ์‹ค์ œ ์—ฐ๊ฒฐํ•ด์„œ ๊ฐ์ง€ ๊ธฐ๋ฐ˜ AI ํ๋ฆ„์„ ๊ตฌํ˜„ํ–ˆ๋‹ค.
  • ํŠนํžˆ ์‹œ์•ผ, ๋ฐœ์†Œ๋ฆฌ, ๋งˆ์ง€๋ง‰ ๊ฐ์ง€ ์œ„์น˜ ๊ฐ™์€ ์š”์†Œ๋“ค์ด ๋“ค์–ด๊ฐ€๋ฉด์„œ
    AI ์›€์ง์ž„์ด ๋‹จ์ˆœ ์ขŒํ‘œ ์ด๋™๋ณด๋‹ค ํ›จ์”ฌ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ณด์ด๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค.
profile
๊ฐœ๋ฐœํ•ฉ์‹œ๋‹ค!

0๊ฐœ์˜ ๋Œ“๊ธ€