왜.... 오셨나요?

부끄러워요

유니티개발 TIL

TIL_유니티 실전 프로젝트(턴제시스템 연결(2))

와피했는데 2025. 9. 22. 21:34

들어가기 앞서

턴제시스템에 순서와 CommandPattern과 EventManager의 연결을 진행할 예정임


구현


몬스터턴때 몬스터들이 한차례씩 움직이도록 기능 설정

 

● 적들이 차례대로 행동하도록 하고 전체 턴이 종료되는걸 감지하여 턴넘기는 기능 구현

 

>TurnBasedManager 클래스내에 로직 추가

public Queue<BaseEnemy> monsterQueue = new Queue<BaseEnemy>();

//(중략)---------------------------------

// ===== 적 턴 진행 순서로직 =====
// 적 턴 시작 시 호출
public void BeginEnemyPhase()
{
    monsterQueue.Clear();
    currentEnemy = null;
    enemyPhaseActive = true;

    List<BaseEnemy> monsters = GameManager.Unit.enemies;
    foreach (var enemy in monsters)
    {
        if (enemy == null || enemy.controller == null) continue;
        if (enemy.controller.isDie) continue;
        enemy.controller.isDone = false;
        enemy.controller.startTurn = false;
        monsterQueue.Enqueue(enemy);
    }

    TryStartNextEnemy();
}

// 개별 적 턴 종료 시점에 호출되는 로직
private void OnEnemyTurnEnded()
{
    if (!enemyPhaseActive) return;
    if (currentEnemy != null && currentEnemy.controller != null)
    {
        // [중요] 완료 후 플래그 초기화
        currentEnemy.controller.startTurn = false;
        currentEnemy.controller.isDone = false;
        currentEnemy = null;
    }
    TryStartNextEnemy();
}

// 큐에서 다음 적을 하나 꺼내어 턴 시작
private void TryStartNextEnemy()
{
    while (monsterQueue.Count > 0)
    {
        var enemy = monsterQueue.Dequeue();
        if (enemy == null || enemy.controller == null) continue;
        if (enemy.controller.isDie) continue;

        if (!enemy.controller.startTurn)
        {
            enemy.controller.startTurn = true;
            enemy.controller.isDone = false;
            enemy.controller.StartTurn();
            currentEnemy = enemy;
            return; // 현재 적이 완료되면 OnEnemyTurnEnded 이벤트로 이어짐
        }
    }

    // 큐가 비었고 진행 중인 적이 없으면 적 턴 종료
    if (currentEnemy == null)
    {
        enemyPhaseActive = false;
        ChangeTo<PlayerTurnState>("Enemy phase finished");
    }
}
기능 설명
적턴 시작 전에 실행되어 큐(Queue) UnitManager에 있는 public List<BaseEnemy> enemies = new List<BaseEnemy>();를 참조받아 생성된 스테이지내 몬스터들 중 isDie(죽은것)은 제외한 리스트 인덱스를 큐에 담음 그리고 몬스터의 FSM을 초기화 하기위해 isDone과 startTurn을 false로 바꿈 그후 리스트 첫번째 인덱스부터 담기 큐에서 하나씩 꺼내어 한 몬스터의  EnemyController클래스 내에 있는 StartTurn()메서드를 실행시켜 FSM를 시작시킴 그리고 마지막 행동에 TrueBasedManager내에 OnEnemyTurnEnded를 호출시켜 로 만들고 이 다음 currentEnemy를 null시켜 다음 적의 차례를 만들어준다


버그수정


발생 상태클래스 내부에 하위 상태클래스로 넘어가지 않는 현상 발생
문제 상위 클래스에 ChangeState를 하지 않았음
해결 Base를 상속받아 상태첫 시작될때 시작하는 OnEnter 메서드에 ChangeState를 넣어 하위 클래스로 상태변경함

마치며.


턴제에서는 몬스터가 여러마리일경우 자료구조를 통해 한마리씩 지정하여 움직이게 하는게 중요하다 이렇게 안할경우 몬스터가 한번에 움직이고 탐색과정중 꼬일수도있어서 차례대로 실행해주는것이 중요함