08/18 FPS 게임 설계, AI 적용 및 씬구성

심지태
∙∙조회 4

책임 분류: 결정(뇌)과 실행(몸)을 나눈다

Player와 Enemy처럼 서로 다른 방식으로 움직이는 객체라도 체력, 공격, 충돌, 사망 같은 공통 기능까지 각각의 거대한 Controller에 넣어 구현하면 안 됩니다. Controller는 입력이나 AI처럼 ​무엇을 할지 결정하는 ‘뇌’의 역할에 집중하고, Health, Weapon, SightSensor처럼 실제 기능을 수행하는 부분은 독립된 컴포넌트인 ‘몸’으로 분리​해야 합니다. 이렇게 기능별로 책임을 나누면 Player와 Enemy가 동일한 규칙과 기능을 공유할 수 있어 중복 코드가 줄고, 체력이나 전투 규칙이 변경되어도 한 곳만 수정하면 되기 때문에 유지보수와 확장이 훨씬 쉬워집니다.

기능Player 전용공통 컴포넌트Enemy 전용
WASD 입력 읽기✔ (InputReader)
체력 감소·사망✔ (Health)
순찰 경로✔ (FSM)

IDamageable과 Health: 인터페이스 실전 투입

컴포넌트 분리가 기능의 책임을 나누는 것이라면, 인터페이스는 나눠진 기능들이 서로 통신하기 위한 공통 약속입니다. 예를 들어 Player와 Enemy가 모두 IDamageable을 구현하면, 공격하는 쪽은 상대가 누구인지 알 필요 없이 TakeDamage()만 호출하면 됩니다. 즉, 구체적인 객체에 의존하지 않고 필요한 기능만 바라보게 만들어 결합도를 낮추고 재사용성을 높이는 역할을 합니다.

옵저버패턴의 장점 : 결합도가 내려감.

옵저버패턴의 단점 : 추적이 어려워진다.

실습 : 오브젝트들의 컴포넌트 나누기

IDamageable : TakeDamage(받을 대미지, 공격대상) 메서드를 반드시 구현하도록 지정

Health : IDamageable를 상속받는 대상. 체력을 관리하는 컴포넌트. IDamageable의 TakeDamage를 통해 체력이 깍인다.

PlayerShooter : 플레이어가 레이캐스트를 쏴서 공격하는 컴포넌트.

EnemyAttacker : 적이 플레이어를 감지하고 공격하는 컴포넌트.

Coroutine: 시간차 실행의 기본

Coroutine 정리

Coroutine은 시간을 두고 이어지는 동작을 여러 프레임에 나누어 실행할 때 사용하는 Unity 기능입니다. 일반 함수는 호출된 프레임 안에서 끝까지 실행되지만, Coroutine은 yield return을 만나면 현재 위치에서 잠시 멈췄다가 조건이 충족되면 그 다음 줄부터 다시 실행합니다.

Coroutine은 별도의 스레드가 아니며 메인 스레드에서 실행됩니다. 따라서 기다리는 동안 게임 전체가 멈추는 것이 아니라 Unity는 계속 다음 프레임을 처리합니다.

scss
IEnumerator HitFeedback(){

ChangeColor(Color.red);

yield return new WaitForSeconds(0.1f);

ChangeColor(originalColor);

}
구성 요소역할
IEnumeratorCoroutine 함수의 반환 타입
yield return현재 실행을 잠시 중단
WaitForSeconds(0.1f)지정한 시간만큼 대기
yield return null다음 프레임까지 대기
StartCoroutine()Coroutine 실행 시작
StopCoroutine()실행 중인 Coroutine 중지

예를 들어 위 코드는 색을 빨갛게 변경 → 0.1초 대기 → 원래 색으로 복구하는 순서로 실행됩니다.

scss
StartCoroutine(HitFeedback());

즉, Coroutine은 피격 효과, 딜레이, 페이드, 쿨타임, 시간에 따른 이동처럼 즉시 끝나지 않고 일정 시간 동안 이어지는 로직을 구현할 때 주로 사용합니다.