4 분 소요

Slime Project는 하드코어 액션 퍼즐 플랫포머 게임으로, FiniteStateMachine(FSM) 기반 상태 관리 시스템을 통해 모든 게임 엔티티의 행동을 체계적으로 관리합니다. 플레이어 슬라임의 움직임, 변신 능력, 그리고 변신 시 능력 변화를 구현했으며, 보스 몬스터와 일반 몬스터의 AI 로직을 담당하여 확장 가능한 게임 시스템을 구축했습니다.


1. 프로젝트 개요

본 프로젝트는 복잡한 게임 로직을 디자인 패턴을 활용해 구조화하는 데 집중했습니다. 모든 캐릭터와 몬스터는 통일된 인터페이스를 공유하며, 기능 중심의 컴포지션 설계를 통해 유지보수성을 극대화했습니다.

상태머신 시스템

FiniteStateMachine 기반
상태 전환 관리 및 라이프사이클

플레이어 시스템

슬라임 움직임/공격
변신 능력 동적 교체 구현

보스 AI

델리게이트 기반 스킬
HP 단계별 패턴 업그레이드

일반 몬스터 AI

상태머신 기반
유형별 행동 패턴 확장


2. FiniteStateMachine 기반 상태 관리 시스템

모든 몬스터와 게임 엔티티의 행동을 FiniteStateMachine 패턴으로 관리하는 시스템을 구현했습니다. State 베이스 클래스를 통해 각 상태의 Enter/Exit/LogicUpdate/PhysicsUpdate 라이프사이클을 체계적으로 관리합니다.

2.1 상태머신 구조 및 전환 플로우

FiniteStateMachine은 현재 상태를 관리하고, 상태 전환 시 이전 상태의 Exit와 새 상태의 Enter를 자동으로 호출하여 물리 및 애니메이션 상태의 정합성을 보장합니다.

State::Enter
상태 초기화
Execution Loop
LogicUpdate
PhysicsUpdate
Trigger
Transition?
[YES]
State::Exit
NewState::Enter

상태머신 핵심 로직 상태머신 초기화 및 안전한 상태 전환을 보장하는 핵심 로직입니다.

코드 보기: FiniteStateMachine.cs
// FiniteStateMachine.cs: 상태머신 핵심 로직
public class FiniteStateMachine
{
    public State currentState { get; private set; } 

    // 상태머신 초기화: 시작 상태 설정 및 Enter() 호출
    public void Init(State startingState) 
    {
        currentState = startingState;     // 현재 상태 설정
        currentState.Enter();             // 시작 상태 진입
    }

    // 상태 전환: 이전 상태 종료 후 새 상태 진입
    public void ChangeState(State newState) 
    {
        currentState.Exit();                // 이전 상태 종료
        currentState = newState;            // 새 상태로 전환
        currentState.Enter();               // 새 상태 진입
    }
}

2.2 State 베이스 클래스

모든 상태는 State 베이스 클래스를 상속받아 구현됩니다. 각 상태는 애니메이션 파라미터 제어와 상태 시작 시간 기록 등을 자동으로 처리합니다.

코드 보기: State.cs
// State.cs: 모든 상태의 베이스 클래스
public class State
{
    protected FiniteStateMachine stateMachine;  // 상태머신 참조
    protected Entity entity;                    // 엔티티 참조
    protected float startTime;                  // 상태 시작 시간
    protected string animBoolName;              // 애니메이션 파라미터 이름

    public virtual void Enter()                     // 상태 진입 시 호출
    {
        startTime = Time.time;                      // 시작 시간 기록
        entity.anim.SetBool(animBoolName, true);    // 애니메이션 트리거
        DoChecks();                                 // 상태 전환 조건 확인
    }
    
    public virtual void Exit()                     // 상태 종료 시 호출
    {
        entity.anim.SetBool(animBoolName, false);   // 애니메이션 종료
    }
    
    public virtual void LogicUpdate()         // Update()에서 호출
    {
    }
    
    public virtual void PhysicsUpdate()      // FixedUpdate()에서 호출
    {
        DoChecks();                                 // 물리 업데이트마다 조건 확인
    }

    public virtual void DoChecks()          // 상태 전환 조건 확인
    {
        // 플레이어 감지, 벽/절벽 감지 등
    }
}

3. 플레이어 슬라임 및 변신 시스템

플레이어 슬라임의 움직임, 공격, 대시, 피격 처리를 구현했습니다. 컴포지션 패턴을 활용하여 각 기능을 독립적인 클래스로 분리하고, Player_Slime에서 통합 관리합니다.

3.1 시스템 구조 (Composition Pattern)

Player_Slime은 모든 컴포넌트의 허브 역할을 수행하며, 각 기능 모듈은 자신의 도메인 로직에 집중합니다.

Player_Slime (Main Controller)
Player_Entity Inherited Component Hub
↓ Dispatch
SlimeMovement
이동, 점프, 입력 관리
SlimeAttack
근접 공격, 데미지 트리거
SlimeDash
대시 이동, 무적 프레임
SlimeDead
사망 처리, 게임오버 연동

3.2 변신 능력 시스템

플레이어가 몬스터를 처치하면 해당 몬스터의 형태로 변신할 수 있습니다. 변신 시 각 형태의 고유 능력을 사용할 수 있으며, Player_FormMovement를 통해 특수 이동 로직이 활성화됩니다.

  • 슬라임 (기본): 원거리 포물선 공격, 대시 무적 프레임 활용.
  • 토끼 (변신): 더블 점프 및 벽 점프 능력 획득. Rabbit_ability와 연동하여 벽 점프 중 조작 제한 물리 로직 적용.
코드 보기: Player_Slime.cs - 초기화 로직
// Player_Slime.cs: 플레이어 슬라임 메인 클래스
public class Player_Slime : Player_Entity
{
    public Player_SlimeMovement movement { get; private set; }
    public Player_Attack attack { get; private set; }
    public Player_Dash dash { get; private set; }

    protected override void Start()
    {
        base.Start();
        // 각 기능 컴포넌트 초기화 (Composition)
        movement = new Player_SlimeMovement(this, movementData, this);
        attack = new Player_Attack(this, attackData, meleePos);
        dash = new Player_Dash(this, dashData);
    }
}

4. 보스 및 일반 몬스터 AI 시스템

보스 몬스터의 스킬 시스템을 델리게이트 기반으로 구현하여 확장 가능한 AI를 설계했습니다. HP 단계에 따라 스킬이 업그레이드되며, 거리와 상황에 따라 지능적인 패턴을 생성합니다.

4.1 보스 AI 의사결정 및 스킬 시스템

보스는 매 업데이트마다 플레이어와의 거리를 산출하고, 델리게이트 배열에 등록된 스킬 풀(Pool)에서 최적의 패턴을 선택하여 실행합니다.

1. Distance Calc
플레이어 거리 및 방향 분석
2. Phase Check
HP 50% 이하 스킬 업그레이드
3. Skill Select
델리게이트 배열 랜덤 인덱싱
4. Action
Invoke Skill Action
코드 보기: MainBossBear.cs - 델리게이트 기반 스킬 관리
// MainBossBear.cs: 보스 스킬 시스템
public class MainBossBear : BossBearSetting
{
    private delegate void BossBear_SkillAction();
    private BossBear_SkillAction[] BossBear_Skills;

    public bool IsSkillUpgrade; // HP 단계 플래그

    public override void Start()
    {
        base.Start();
        // 델리게이트 배열에 메서드 직접 할당
        BossBear_Skills = new BossBear_SkillAction[4] { Rest, Smash, Dash, Rumbling };
    }

    private void RandomBossBearSkillState()
    {
        int RandomSkill_Index = Random.Range((int)BossBear_SkillEnum.Smash, (int)BossBear_SkillEnum.Skill_Max);
        // 선택된 스킬 메서드 대리 호출
        BossBear_Skills[RandomSkill_Index].Invoke();
    }
}

4.2 일반 몬스터 AI 확장 사례

일반 몬스터들은 공통의 Enemy_State를 상속받아 고유한 행동 패턴을 가집니다.

  • Bear (돌진형): DashState를 통한 강력한 물리 충격 기반 공격.
  • Spider (매복형): JumpState를 활용한 공중 도약 및 플레이어 타겟팅 낙하 공격.
  • Ant (기본형): 정형화된 순찰 및 근접 공격 루틴 수행.

5. 기술적 성과 요약

  • FSM 아키텍처: Enter/Exit 라이프사이클 관리를 통해 복잡한 상태 전이 시 발생할 수 있는 버그를 근본적으로 차단.
  • 컴포지션 기반 확장성: 플레이어 기능을 모듈화하여 새로운 변신 형태나 능력을 추가할 때 기존 코드 수정을 최소화.
  • 델리게이트 기반 AI: 보스의 스킬 패턴을 인덱스 기반으로 관리하여 패턴 추가 및 확률 조정의 유연성 확보.
  • 물리/애니메이션 동기화: LogicUpdate와 PhysicsUpdate를 분리하여 프레임 드랍 환경에서도 일관된 충돌 판정 및 움직임 보장.

Conclusion: Slime Project는 디자인 패턴을 실무에 어떻게 적용하여 대규모 게임 로직을 관리할 수 있는지에 대한 깊은 고민이 담긴 프로젝트입니다. FSM과 컴포지션을 통해 복잡한 액션 퍼즐의 메커니즘을 견고하게 구현해냈습니다.