Project/VESTIGIA

[쿼리도 슈팅 #04] 유니티 턴제 게임 동적 경로 재계산 - 매번 다시 계산하지 않고 맵 버전으로 푼 방법

gggdesigner0905 / 2026. 7. 17. 19:25

턴제 전략 게임에서 벽을 설치할 때마다 모든 적의 경로를 다시 계산하는 대신, 맵 변경 버전(PathRevision)으로 필요한 순간에만 갱신한 과정을 정리했어요.

1. 들어가며

안녕하세요, 쿼리도 슈팅에서 PO(프로덕트 오너, 제품의 방향을 책임지는 역할)와 개발을 맡고 있는 정회륜이에요.

이번 글에서는 플레이어가 벽을 설치했을 때 적의 경로를 언제, 어떤 단위로 다시 계산하도록 만들었는지 소개해요.
모든 적의 경로를 무조건 다시 계산하는 대신, 전장의 변화와 적의 행동 시점을 기준으로 갱신한 과정도 함께 다룰게요.

이런 상황을 겪고 있다면 도움이 될 거예요.

  • 타일 기반 턴제 게임을 만들고 있다
  • 전투 도중 장애물이 생기거나 사라진다
  • 적의 행동 예고와 실제 행동을 일치시켜야 한다
  • 동적 경로 탐색의 정확성과 성능 사이에서 고민 중이다
  • 기존 경로 탐색 시스템을 크게 바꾸지 않고 동적 장애물을 넣고 싶다

2. 벽이 왜 문제였나

쿼리도 슈팅은 캐릭터를 움직여 적을 공격하면서, 벽을 설치해 전장을 바꾸는 턴제 전략 게임이에요.

벽으로 적의 접근 경로를 늘리거나 특정 방향으로 유도하는 게 핵심 전략이죠.
벽은 단순한 장애물이 아니라, 적의 판단과 이동 결과를 실시간으로 바꾸는 시스템이에요.

예를 들어 적이 플레이어를 향해 직진하고 있을 때 그 앞에 벽을 세우면, 적은 기존 경로를 버리고 우회로를 찾아야 해요.
이 변화가 제대로 처리되지 않으면 벽을 설치한 의미가 사라져요.

적은 자기 턴이 되면 플레이어나 지정된 목표 지점까지 이동해요.
그런데 경로를 계산해 둔 뒤에 플레이어가 벽을 설치하면, 적이 기억하는 경로와 실제 맵 상태가 달라져요.

여기서 이런 문제가 생길 수 있었어요.

  • 적이 새로 설치된 벽 방향의 타일로 이동을 시도한다
  • 적이 벽 앞에서 멈춘 채 아무 행동도 못 한다
  • 벽이 설치됐는데 적은 기존 경로대로 움직인다
  • 경로를 다시 계산하더라도 모든 적이 한꺼번에 연산해 턴 전환이 늦어진다

쿼리도 슈팅에서는 플레이어가 세운 벽이 적의 움직임을 바꾸는 것 자체가 중요한 전략적 피드백이에요.

적이 벽을 통과하지 못하게 막는 것만으로는 부족했어요.
벽이 설치된 순간부터 적의 다음 행동과 예고 정보가 새로운 전장 상태를 반영해야 했죠.

결론은 이거였어요.
맵이 바뀔 때 모든 경로를 즉시 다시 계산하는 구조 대신, 맵이 변경됐다는 사실만 기록해 두고 경로가 실제로 필요한 시점에 최신 상태로 계산하는 구조.

3. 왜 이 방식을 골랐나

벽 설치 직후 모든 적의 내부 경로를 완성하는 것보다 중요한 게 두 가지 있었어요.

  • 플레이어에게 표시되는 적의 다음 행동이 최신 상태를 반영할 것
  • 적이 실제 행동할 때 현재 전장에서 유효한 경로를 쓸 것

그래서 벽이 설치될 때는 경로를 곧바로 계산하지 않고, 맵이 변경됐다는 사실만 시스템에 알리기로 했어요.
경로 계산은 실제로 필요한 지점에서만 해요.

  • 적의 턴이 시작될 때
  • 기존 경로의 다음 이동 타일이 막혔을 때
  • 적의 목표 위치가 바뀌었을 때

플레이어가 보는 정보와 실제 적 행동의 일관성은 지키면서, 불필요한 전체 탐색은 줄이는 게 목표였어요.

4. 실제로 적용한 방법

가장 먼저, 벽을 화면에 미리 보여주는 상태와 실제 맵 데이터에 벽이 등록된 상태를 구분했어요.

플레이어가 설치 위치를 고르는 동안에는 벽의 미리보기 오브젝트만 움직여요.
이 단계에서 적의 경로를 다시 계산하면 커서가 움직일 때마다 경로 탐색이 반복되거든요.

그래서 아래 조건을 모두 만족했을 때만 맵이 변경된 것으로 처리했어요.

  • 벽 배치 가능 여부 검사가 끝났다
  • 플레이어가 설치를 확정했다
  • 벽 데이터가 실제 맵(그리드)에 등록됐다
  • 해당 타일의 이동 가능 상태가 바뀌었다

각 적이 경로를 마지막으로 계산한 시점과 현재 전장 상태가 같은지 확인할 수 있도록 맵 변경 버전을 뒀어요.
벽이 설치되거나 제거될 때마다 PathRevision 값을 올려요.

public sealed class PathRevision
{
    public int Current { get; private set; }

    public void Increase()
    {
        Current++;
    }
}

적은 경로를 계산한 뒤 그때의 버전을 저장해요.

private int calculatedRevision = -1;
private IReadOnlyList<GridPosition> currentPath;

private void RecalculatePath(GridPosition target)
{
    currentPath = pathFinder.FindPath(CurrentPosition, target);
    calculatedRevision = pathRevision.Current;
}

행동하기 전에는 현재 버전과 자신이 저장한 버전을 비교하고요.

private bool IsPathOutdated()
{
    return calculatedRevision != pathRevision.Current;
}

이 구조면 벽 설치 시스템이 모든 적을 직접 찾아가 경로를 지우거나 다시 계산할 필요가 없어요.
적이 자기 행동 시점에 경로가 오래됐는지 스스로 판단해요.

다만 맵 버전이 바뀌었다고 모든 적의 경로가 반드시 막힌 건 아니에요.
맵 오른쪽에 벽이 생겨도 왼쪽에 있는 적의 경로에는 아무 영향이 없을 수 있죠.

이럴 때까지 전체 경로를 다시 계산하면 연산 낭비라, 두 조건을 함께 확인하도록 했어요.

  • 맵의 변경 버전이 달라졌는가
  • 기존 경로에 지금 이동할 수 없는 타일이 포함됐는가

6. 적용 결과

가장 큰 변화는 플레이어가 세운 벽과 적의 반응 사이 인과관계가 명확해졌다는 점이에요.

벽을 설치하면 적의 행동이 바뀌고, 실제 턴에서도 예고된 경로대로 움직여요.
플레이어는 자신이 세운 벽이 전투에 어떤 영향을 줬는지 바로 확인할 수 있어요.

경로 재계산 시점이 명확해지면서 벽 시스템, 경로 탐색 시스템, 적 행동 시스템의 역할 구분도 전보다 분명해졌고요.

주의할 점

작업하면서 주의해야 했던 것들이에요.

A. 벽 설치의 전략적 결과가 즉시 전달돼야 해요. 

경로 계산이 정확해도 행동 예고가 늦게 바뀌면, 플레이어는 벽이 제대로 작동하지 않는다고 느껴요.
계산 성능만이 아니라 UI 갱신 시점도 같이 검토해야 해요.

B. 적이 절대 이동할 수 없는 상태를 어떻게 처리할지 먼저 정해야 해요. 

게임 규칙이 먼저예요.
벽으로 모든 경로를 차단할 수 없게 배치 단계에서 막을지, 차단은 허용하되 적이 벽을 공격하게 할지.

이 규칙이 불명확하면 경로 탐색 코드가 게임 기획까지 대신 판단하게 돼요.

C. 경로 탐색 결과와 이동 애니메이션은 분리해야 해요. 

적이 이동하는 도중 경로를 다시 계산해 현재 리스트를 교체하면, 애니메이션과 논리 위치가 어긋날 수 있어요.
경로 변경은 행동 시작 전에 확정하고, 이동 중 맵 변경을 허용해야 한다면 현재 이동 단계가 끝난 뒤 새 경로를 적용하는 게 안전해요.

D. 경로 캐시를 쓴다면 맵 버전을 같이 저장해야 해요. 

출발 위치와 목적지가 같아도 벽 배치가 다르면 경로 결과가 달라져요.
캐시 키에 맵 버전이나 이동 가능 상태를 구분할 값을 포함해야 해요.

7. 마무리

이번 작업에서 배운 건 하나예요.
이벤트를 발생시킨 다음, 다른 코드가 언제 어떻게 반응할지 행동 분기를 명확하게 갈라놓을 것.

Unity의 Update에서 상황을 확인하는 코드를 최대한 줄이고 이벤트로 관리하니, 실행 순서 때문에 생기는 오류가 사라지고 연산도 가벼워졌어요.