역할(이영호): 공격형 RL 설계·개선(1.0→1.4) + 평가 자동화(CSV Logger) — 공격형 BT는 공동 작업

한눈에 보기

Unity ML-Agents 환경에서 1:1 전투 에이전트를 행동 트리(BT)와 강화학습(RL) 두 방식으로 각각 구현하고 같은 조건에서 성능을 비교한 인공지능 수업 팀 프로젝트입니다. 팀은 공격형과 수비형을 각각 BT·RL로 나눠 만들었고 저는 그중 공격형 RL을 맡아 관측·보상·행동 마스크를 설계하고 1.0에서 1.4까지 여섯 번의 학습 사이클로 다듬었습니다. 개선 근거를 남기려고 평가 자동화(CSV Logger) 도 직접 만들어 매 버전을 30 episode(최종 비교는 100 episode) 기준으로 집계했습니다.

결과: 공격형 RL 최종 1.4 모델은 방어형 baseline 상대 30판 중 28승, 공격 대비 명중(hit) 비율 55.4%, 방어 중 헛공격 비율 1.7% 를 기록했습니다. 보상만으로 풀리지 않던 문제(방어 중 공격 91.9%)를 행동 마스크(Action Mask) 로 끊어낸 것이 핵심 전환점이었습니다.

역할 분담

구분담당비고
공격형 RL이영호 (핵심)관측 18종·보상 설계·Action Mask, 1.0→1.4 개선 사이클
평가 자동화이영호 (핵심)CombatEvaluationCsvLogger 등 — 승패·시간·데미지·행동 분포 CSV 집계
공격형 BT공동9순위 대응형 공격 트리 (RL의 비교 기준이자 baseline)
수비형 BT · RL팀원Defensive Counter 전략
결과 비교·시각화팀원9개 모델(공격 3 × 수비 3) 대전 그래프

이 문서는 제가 맡은 공격형 RL과 평가를 중심으로 정리하되, 이해를 돕기 위해 공격형 BT와 팀 전체 비교 결과도 함께 담았습니다.

프로젝트 개요

공격형 BT (공동 작업)

RL의 비교 대상이자 초기 baseline이 된 상대 상태에 반응하는 대응형 공격 트리입니다. 보스몬스터 AI를 가정해 단순히 공격만 반복하지 않고 상대가 공격하면 막고 상대가 방어·회피하기 어려운 빈틈에 공격하도록 설계했습니다.

Root Selector → (전투 Sequence | Victory) 구조이며, 전투 Sequence는 TargetAlive → UpdateTargetInfo → 전투 행동 Selector 순으로 흐릅니다. 전투 행동 Selector는 아래 9개 행동을 우선순위대로 평가합니다.

순위행동언제
1상대 공격 방어상대가 공격 중이고 방어가 가능할 때
2빈틈 공격상대 스킬이 모두 쿨타임이라 반격 못 할 때
3콤보 공격사거리·정면·빈틈이 맞고 콤보 쿨타임(15초)이 찼을 때
4조준사거리 안이지만 정면이 아닐 때
5압박 유지상대가 보이면 접근하거나 거리를 좁혀 유지
6기본 공격사거리·정면이 맞고 상대가 방어 중이 아닐 때
7돌격상대가 시야 끝·사거리 밖이면 빠르게 접근
8추적상대가 보이지만 멀면 지속 이동
9수색상대를 놓치면 마지막 목격 위치 또는 무작위 수색

수업의 BT 필수 요건은 다음 노드로 충족했습니다.

BT 결과: 수비형 baseline BT와 100회 대전에서 100승 0패, 평균 28.36초, 평균 100 피해 · 자기 체력 100 유지, 방어 중 헛공격 0회. 규칙이 잘 맞는 상대에겐 빠르고 안정적이지만, 뒤에서 보듯 학습형 수비 상대에는 같은 실수를 반복하는 한계도 함께 드러납니다.

공격형 RL — 설계 (담당)

공격형 RL의 목표는 “오래 버티는 모델”이 아니라 “실제로 때리고 이기는 모델” 입니다. 그래서 승률뿐 아니라 hit 수 · 공격 대비 hit 비율 · 방어 중 공격 비율 · 평균 episode 시간을 함께 평가 지표로 삼았습니다.

Observation (18종)

StudentCombatAgentAtk.csCollectObservations()에서 18개 값을 정규화(01 또는 -11)해 전달합니다. Unity Behavior Parameters의 Vector Observation Size와 정확히 일치시켰습니다.

범주관측값설계 의도
체력자기·상대 체력 비율우세/열세 판단
위치·거리상대 X/Z offset, 거리접근·후퇴 판단
방향자기 forward X/Z, 상대를 바라보는 정도(dot)조준 상태 판단
자기 쿨타임공격·방어·회피 쿨타임지금 가능한 행동 판단
상대 쿨타임공격·방어·회피 쿨타임상대 빈틈 판단 (방어·회피는 1.4 추가)
상대 상태공격 중·방어 중·무적공격/방어 타이밍 판단 (무적은 1.4 추가)
사거리상대가 공격 사거리 안인지공격 가능 여부

Action (discrete 2 branch)

Branch크기
이동5없음 / 전진 / 후진 / 좌 / 우
스킬4없음 / 공격 / 방어 / 회피

이동은 월드 좌표가 아니라 상대 기준 방향으로 처리해, 모델이 맵 위치가 아니라 전투 관계(접근·후퇴·좌우)를 학습하도록 했습니다.

Reward (최종 1.4)

공격 “횟수”가 아니라 실제 명중과 승리를 우선하도록 설계했습니다.

분류항목의도
데미지damageRewardScale+0.08 × 데미지실제 명중 우선
승리winReward+3episode 목표 명확화
유효 공격validAttackReward+0.02공격 탐색 유도
빈틈 공격defensiveCooldownAttackReward+0.04상대 방어 쿨타임 중 공격 유도
기다림defensePatienceReward+0.002방어 중 상대에 무리한 공격 대신 대기
기회 상실missedAttackOpportunityPenalty-0.025열린 기회에서 무행동 방지
방어 중 공격blockedAttackPenalty-0.12방어 중 헛공격 억제
잘못된 공격invalidAttackPenalty-0.02사거리 밖 공격 억제
피격damagePenaltyScale-0.006 × 데미지맞는 행동 억제
무행동idleActionPenalty-0.006정지 정책 방지
시간 초과timeoutPenalty-1무승부 회피

Action Mask (1.4 핵심)

1.3까지는 “방어 중인 상대를 공격하는” 행동을 보상 패널티만으로 줄이려 했지만, 오히려 방어 중 공격 비율이 91.9%까지 올랐습니다. 그래서 1.4에서는 WriteDiscreteActionMask()애초에 잘못된 공격을 선택지에서 제거했습니다.

상황처리
자기 행동 중(busy)공격·방어·회피 비활성화
공격 쿨타임 남음공격 비활성화
상대 방어 중 / 무적공격 비활성화
방어·회피 쿨타임 남음방어·회피 각각 비활성화

공격형 RL — 개선 사이클 (1.0 → 1.4)

핵심 교훈은 “보상만으로는 전투 타이밍을 다 가르치기 어렵다” 였습니다. 각 버전을 CSV로 평가해 병목을 찾고 다음 버전의 방향을 정했습니다.

버전핵심 문제개선결과 (30 episode)
1.0회피·방어에 치우침, 공격 성과 없음생존형 보상 구조 문제 확인30판 시간초과, 데미지 0, 회피 360
1.1무행동 정책으로 수렴공격 탐색 강화 필요 확인공격 1회, 데미지 0
1.2공격은 늘었지만 다 막힘무행동 패널티·공격 보상 강화공격 574, hit 0, 방어 중 공격 82.8%
1.3첫 데미지, 그러나 타이밍 실패데미지 보상·방어 중 공격 패널티 강화데미지 280, hit 14, 방어 중 공격 91.9%
1.4보상만으로는 억제 한계Action Mask + 상대 쿨타임·무적 관측 추가28승/30, hit 160, 방어 중 공격 1.7%

1.3 → 1.4 변화가 이 프로젝트의 하이라이트입니다. 관측을 15→18로 늘리고 잘못된 공격을 마스킹하자, 공격 횟수는 570→289회로 줄었는데도 hit는 14→160회로 늘었습니다. “많이 때리기”에서 “맞을 때 때리기” 로 정책이 바뀌었습니다.

남은 한계: 공격 중심으로 기울며 받은 데미지가 80→320으로 늘었습니다. 승률을 지키면서 피격을 줄이는 방어 균형이 다음 과제로 남았습니다.

PPO 학습 설정

항목항목
trainerPPOhidden units / layers128 / 2
behaviorCombatAgentbatch / buffer64 / 2048
learning rate0.0003gamma / lambd0.99 / 0.95
beta / epsilon0.005 / 0.2time horizon64
max steps1,000,000time scale20
run idcombat_rl_014
mlagents-learn Assets/Config/combat_ppo.yaml --run-id=combat_rl_014 --force --timeout-wait 600

평가 자동화 — CSV Logger (담당)

개선 사이클을 근거 있게 돌리려면 매번 똑같은 조건에서 자동으로 지표를 뽑는 도구가 필요했습니다. 그래서 CombatEvaluationCsvLogger를 직접 만들었습니다.

이 CSV 로그가 있었기에 “방어 중 공격 비율 91.9%” 같은 정확한 병목 수치를 짚어 다음 버전 방향을 정할 수 있었습니다. 보고서와 발표의 모든 BT/RL 수치도 이 로그에서 집계했습니다.

평가 신뢰도 메모: 일부 로그에서 데미지가 체력 100을 넘는 행이 관측됐는데, Logger의 자체 timeout이 EpisodeManager reset보다 먼저 동작한 동기화 문제로 파악했습니다. 그래서 승률·hit 수·방어 중 공격 비율을 중심 지표로 쓰고 이 동기화 보정을 다음 사이클 과제로 기록해 두었습니다.

결과 — BT vs RL 비교

같은 “공격형” 전략인데도 두 방식의 행동은 뚜렷이 달랐습니다.

팀 종합 결론: BT는 사람이 설계한 조건이 맞는 상황에서 빠르고 명확하지만 상대 패턴이 바뀌면 약점을 반복합니다. RL은 보상·관측으로 상황별 타이밍을 학습해 더 유연하지만, 보상 구조에 따라 결정력이 부족하거나 장기전으로 흐를 수 있습니다. 명확한 규칙 전략엔 BT, 복잡한 전투 타이밍·상대 변화 대응엔 RL 이 더 적합하다고 정리했습니다.

기술 스택

Unity · ML-Agents (PPO) · C# · Python · Behavior Tree · Reinforcement Learning · CSV 평가 자동화

배운 점