AI 절차적 던전 생성에서 플레이어 동선과 난이도를 다루는 법
AI 기반 절차적 던전에서 플레이어가 길을 잃거나 난이도가 갑자기 치솟는 문제를 줄이는 방법을 정리합니다. 동선 점수와 위험 예산, 성과 기반 난이도 조절 수식, Unity 구현 예시를 함께 살펴봅니다.

핵심 요약
AI 기반 절차적 던전에서 중요한 것은 방을 무작위로 배치하는 일이 아닙니다. 플레이어가 목표를 이해하고 감당할 위험을 고를 수 있게 만드는 것이 핵심입니다.
이 설계의 생성기는 동선 점수와 위험 예산을 만족하는 후보만 채택하도록 만들 수 있습니다. 동적 난이도 조절(DDA)도 플레이어의 실력 추정치에 맞춰 다음 구간의 적 구성, 회복 수단, 경로 정보를 조금씩 조정하도록 설계할 수 있습니다.
절차적 던전에서 플레이어 동선 문제가 생기는 이유
그래프 기반 PCG로 연결 구조를 갖춘 방을 생성할 수 있습니다. 하지만 시작 방에서 보스까지 갈 수 있다는 사실만으로는 좋은 동선이 보장되지 않습니다.
다음과 같은 문제가 쉽게 생깁니다.
- 주 경로가 너무 길어 목표 상실과 피로가 커진다.
- 분기 수가 과도해 탐색이 전략이 아니라 무작위 선택이 된다.
- 열쇠, 회복, 상점이 위협 구간 뒤에 배치돼 회복 불가능한 실패 상태가 된다.
- 전투 밀도가 급격히 변해 긴장과 휴식의 리듬이 사라진다.
이 문제를 확인하려면 던전을 타일의 모음이 아니라 방 그래프(room graph)로 봐야 합니다.
노드는 방, 간선은 이동 가능한 연결을 뜻합니다. 시작점 S, 보스 B, 보상 R, 열쇠 K 같은 역할은 별도 속성으로 기록합니다.

동선 품질을 점수로 평가하기
생성 후보 G의 점수는 목적별 항목을 같은 기준 범위로 정규화한 뒤 가중합해 계산할 수 있습니다. 항목의 척도와 가중치 설정은 게임별로 정해야 합니다.
| 기호 | 의미 | 측정 예시 |
|---|---|---|
P | 주 경로 품질 | S에서 B까지 최단 경로 길이가 목표 범위에 드는 정도 |
B | 분기 품질 | 주 경로당 선택 분기 수와 재합류 비율 |
R | 보상 접근성 | 위험 방 이후 보상·회복 방까지의 거리 |
I | 정보 가독성 | 문, 잠금, 보상 아이콘 등 다음 목표의 가시성 |
D | 혼란도 | 막다른 길, 연속 분기, 불필요한 되돌아가기 비용 |
예를 들어 방 10개 안팎의 짧은 런이라면 주 경로 길이는 6~8, 주 경로 방 2개당 선택 분기는 1개 이하를 초기 목표로 잡을 수 있습니다.
물론 적당한 값은 장르와 이동 속도에 따라 달라집니다. 실제 플레이테스트를 돌리면서 조정해야 합니다.
AI 기반 PCG에서 플레이어 동선을 만드는 방법
AI가 완성된 던전을 한 번에 출력하게 하기보다 규칙 기반 생성과 평가 모델을 결합하는 편이 안전합니다.
LLM은 테마나 방 역할 후보를 제안하는 데 활용하고 실제 연결성과 난이도 검증은 결정론적 알고리즘으로 처리하는 식입니다.
flowchart LR
A[런 설정: 층·테마·목표 난이도] --> B[방 역할 그래프 생성]
B --> C[공간 배치와 연결]
C --> D[동선·위험 예산 평가]
D -->|통과| E[적·보상·이벤트 배치]
D -->|미달| B
E --> F[플레이 데이터 기록]
F --> G[다음 구간 DDA 조정]
Step 1. 방 역할 그래프부터 만든다
공간 좌표를 정하기 전에 Start → Combat → Choice → Reward → Elite → Rest → Boss처럼 역할의 흐름을 먼저 설계합니다.
선택 방은 단순히 경로를 늘리는 장식이 아닙니다. 서로 다른 비용과 보상을 제시해야 플레이어가 선택할 이유가 생깁니다.
| 경로 | 즉시 비용 | 기대 보상 | 적합한 플레이어 상태 |
|---|---|---|---|
| 안전 경로 | 낮은 전투 위험 | 낮은 보상 | 체력이 낮거나 초보인 경우 |
| 위험 경로 | 정예 적, 함정 | 희귀 장비·화폐 | 숙련자 또는 빌드가 완성된 경우 |
| 정보 경로 | 이동 시간 | 지도, 상점, 정찰 | 다음 선택의 불확실성이 큰 경우 |
열쇠가 필요한 문을 넣는다면 그래프상 열쇠 방이 잠금 방보다 앞에 있어야 합니다.
열쇠를 놓쳐도 보스에 도달할 수 있는지 우회 경로가 있는지도 생성 단계에서 확인해야 합니다.
Step 2. 위험 예산으로 전투와 회복을 배치한다
각 방에 위협 값 T_i와 회복 값 H_i를 부여합니다. 구간 k까지의 누적 위험은 다음처럼 계산할 수 있습니다.
Risk_k가 목표 위험 곡선보다 계속 높으면 회복할 틈도 없이 실패가 쌓입니다. 반대로 계속 낮으면 전투가 의미 없는 소모전이 됩니다.
생성기를 구현할 때는 각 구간의 Risk_k가 허용 범위 안에 들어오는지 확인하고, 범위를 벗어난 후보는 적이나 보상 배치를 바꿔 다시 평가하도록 설계할 수 있습니다.
위협 값은 적 체력의 합만으로 정하지 않습니다. 원거리 적, 좁은 전장, 상태 이상, 쿨다운 중인 플레이어 스킬, 시야 제한처럼 생존 판단을 어렵게 만드는 요소도 포함해야 합니다.

Step 3. 생성 후에는 다음 구간만 플레이 상태에 맞춰 조절한다
DDA는 플레이어의 실패를 즉시 없애는 장치가 아닙니다. 다음 방이나 전투 묶음의 파라미터를 조절하되 결과는 여전히 플레이어의 선택과 조작으로 달라질 수 있어야 합니다.
실력 추정치 s는 최근 전투 데이터의 지수이동평균(EMA)으로 계산할 수 있습니다. 이 글에서는 x_t와 s_t를 0~1 범위의 점수로 가정합니다.
여기서 x_t는 전투 성과 점수입니다. 피해 효율, 남은 체력 비율, 사망 횟수, 전투 시간을 게임에 맞는 방향과 가중치로 정규화해 만들 수 있습니다. α=0.2는 예시값이며, EMA는 한 번의 관측값이 추정치에 반영되는 폭을 제한하지만 적절한 값은 플레이테스트로 정해야 합니다.
목표 난이도 d_target과 현재 난이도 d_current는 0~1 범위로 정규화하고, 그 차이를 다음 방의 예산 조정값으로 바꿉니다.
clamp 범위를 작게 두는 것은 보정 변화가 과하게 느껴질 위험을 줄이기 위한 설계 선택입니다. 적 종류, 적 수, 회복 드롭 확률, 힌트 노출 중 한두 항목만 바꾸고 보스의 핵심 패턴이나 보상 규칙은 고정하는 편이 좋습니다.
동적 난이도 밸런싱에서 조절할 항목
| 조절 대상 | 권장도 | 이유 |
|---|---|---|
| 다음 방의 적 조합 | 높음 | 전투 리듬을 자연스럽게 조절할 수 있습니다. |
| 소모품·회복 드롭 | 높음 | 실패가 이어지는 상황을 끊으면서 선택권은 남겨둘 수 있습니다. |
| 선택 경로의 정보량 | 높음 | 실력 부족이 아니라 정보 부족에서 오는 좌절을 줄일 수 있습니다. |
| 적 체력만 일괄 증감 | 낮음 | 전투 시간만 늘어나 지루해지기 쉽습니다. |
| 이미 시작한 전투의 적 공격력 변경 | 매우 낮음 | 플레이어가 조작과 규칙을 믿기 어려워집니다. |
| 보스 핵심 패턴 제거 | 매우 낮음 | 학습과 숙련의 보상을 훼손할 수 있습니다. |
보정을 무조건 숨기기보다 플레이어가 선택할 수 있는 형태로 보여주는 방법도 있습니다.
예를 들어 연속으로 실패한 뒤 ‘보급 상인’, ‘정찰할 수 있는 위험 경로’, ‘안전하지만 보상이 적은 통로’를 제시하는 식입니다. 그러면 난이도 조절이 단순한 구제가 아니라 전략적 선택이 됩니다.
Unity에서 방 그래프와 DDA를 구현하는 예시
다음 C# 코드는 C# 9 문법을 사용하는 최소 예시입니다. Unity 2022.3 LTS와 Unity 6처럼 C# 9를 지원하는 에디터를 기준으로 하며, C# 9 미만의 언어 버전을 사용하는 에디터에서는 new()를 명시적인 생성자 호출로 바꿔야 합니다. 실제 프로젝트에서는 RoomNode에 좌표, 문 방향, 적 프리팹, 보상 테이블 등을 추가하면 됩니다.
using System.Collections.Generic;
using System.Linq;
public sealed class RoomNode
{
public string Id;
public float Threat;
public float Recovery;
public List<RoomNode> Links = new();
}
public static class DungeonEvaluator
{
public static bool IsValidMainPath(
IReadOnlyList<RoomNode> mainPath,
int minRooms,
int maxRooms,
float maxRisk)
{
if (mainPath.Count < minRooms || mainPath.Count > maxRooms)
return false;
float cumulativeRisk = 0f;
foreach (RoomNode room in mainPath)
{
cumulativeRisk += room.Threat - room.Recovery;
if (cumulativeRisk > maxRisk)
return false;
}
return mainPath.Select(room => room.Id).Distinct().Count() == mainPath.Count;
}
}
이 함수는 이미 정해진 주 경로 목록의 방 수, maxRisk 상한을 넘는 누적 위험, 중복 ID만 검사합니다. 위험도의 하한이나 구간별 목표 곡선은 확인하지 않습니다. Links가 실제로 경로를 잇는지, 시작 방에서 보스까지 도달 가능한지는 별도의 그래프 연결성 검사에서 확인해야 합니다.
난이도 파라미터는 생성 시점에 결정된 값을 로그로 남기는 것이 좋습니다.
seed, 방 역할 그래프, 선택 경로, s_t, 적용한 Δd, 사망 위치를 한 런 단위로 기록하면 불공정하게 느껴진 구간을 조사하는 데 도움이 됩니다. 다만 이 항목만으로 재현이 보장되지는 않습니다. 필요에 따라 생성기 버전과 설정, 난수 상태, 전투 이벤트와 플레이어 입력도 함께 기록해야 합니다.
자주 묻는 질문
AI가 던전 전체를 생성하게 해도 될까?
권장하지 않습니다. AI는 테마, 방 설명, 이벤트 후보를 만드는 데 유용하지만 연결성이나 잠금 해제 순서, 위험 예산은 그래프 탐색과 규칙 검증으로 확정해야 합니다.
DDA를 적용하면 게임이 쉬워지지 않을까?
항상 쉬워지는 것은 아닙니다. 목표는 승률을 일정하게 만드는 것이 아니라 실패 원인이 실력 부족인지 정보 부족인지 구분하고 회복할 수 없는 상황을 줄이는 데 있습니다. 상한과 하한을 두고 작은 폭으로 조절하는 것이 중요합니다.
플레이어가 난이도 보정을 눈치채면 어떻게 해야 할까?
전투 중에 보이지 않는 수치를 바꾸는 방식은 피하는 편이 좋습니다. 대신 다음 경로의 위험도나 보상, 정찰 정보처럼 플레이어가 읽고 선택할 수 있는 요소를 조절하면 공정성을 설명하기 쉽습니다.
정리
좋은 AI 기반 PCG가 만들어야 하는 것은 무한한 변형이 아니라 일관된 플레이 경험입니다.
방 그래프로 동선을 먼저 설계하고 위험 예산으로 전투와 회복의 리듬을 검증합니다. 그다음 최근 성과에 따라 다음 구간만 제한적으로 조절합니다.
이 세 단계가 갖춰지면 절차적 던전은 단순히 랜덤한 맵이 아니라 플레이어가 배우고 판단할 수 있는 선택의 공간이 됩니다.



