프로젝트 개요
플레이어가 직접 조작하지 않는 게임 캐릭터인 NPC 다섯 명이 게임 시간과 플레이어의 상태에 따라 행동하는 Unreal Engine 5.4.4 기반 개인 프로젝트입니다. 각 NPC의 시간표와 순찰, 상황별 대화, 퀘스트, 거래, 신뢰도 및 동행을 연결했습니다. 플레이어가 지치면 피로에 관한 대화를 먼저 하고, 거래와 퀘스트로 신뢰도가 높아지면 동행이나 특별한 상품을 이용할 수 있도록 관계의 변화를 실제 플레이에 반영했습니다.
실제 게임은 직접 작성한 규칙과 행동 트리(Behavior Tree), 상태를 공유하는 블랙보드(Blackboard), 설정을 표로 관리하는 데이터 테이블(Data Table)로 동작합니다. 행동 트리는 조건에 따라 순찰이나 동행처럼 실행할 행동을 고르고, 블랙보드는 현재 목표와 상호작용 상태를 전달합니다. 데이터 테이블에는 NPC별 활동 시간과 아이템 및 퀘스트 정보를 담았습니다. 게임 시간과 스태미나, 소지금에 따라 행동과 대화가 바뀌고, 그 결과가 신뢰도와 보유 아이템 목록인 인벤토리에 반영됩니다.
대화와 이동이 충돌하지 않도록 대화 우선순위와 상호작용 도중의 귀가 조건을 명확히 했습니다. 게임 로직은 노드를 연결해 동작을 작성하는 Unreal Engine의 시각적 프로그래밍 도구인 Blueprint로 구현했습니다. 실제 Blueprint를 실행하는 에디터 검증 플러그인과 전체 프로젝트의 복원 도구를 통해 소스와 실행 결과를 대조할 수 있도록 구성했습니다.
핵심 결과
상태 검증은 스태미나나 대화 중 여부처럼 입력 상태를 정한 뒤 기대한 대사와 행동이 나오는지 확인하는 검사입니다. 대상 선택은 주변에 여러 NPC가 있을 때 의도한 캐릭터를 고르는지 검사합니다. 아래의 Actor는 게임 공간에 배치된 객체를 뜻하며, 플레이어 Actor의 회전은 캐릭터가 바라보는 방향을 바꾸는 것입니다.
- 동일한 상태 검증 항목
- 78 / 78
- 대화와 귀가 조건 수정 전 69개, 수정 후 78개 통과
- 사전에 정한 대상 선택 조건
- 30 / 30
- NPC 3명의 위치를 고정하고 플레이어 Actor만 회전
- 조건을 충족한 퀘스트 제안
- 10.03%
- 실제 대화 함수 10,000회 중 1,003회
- 희귀 아이템 선택
- 9.76%
- 실제 아이템 선택 함수 10,000회 중 976회
| 확률 측정 항목 | 관측 횟수 / 함수 호출 | 관측 비율 | Wilson 95% 구간 | 목표 임계값 |
|---|---|---|---|---|
| 조건을 충족한 퀘스트 제안 | 1,003 / 10,000 | 10.03% | 9.46–10.63% | 10% |
| 희귀 아이템 선택 | 976 / 10,000 | 9.76% | 9.19–10.36% | 10% |
목표 임계값은 난수로 퀘스트나 희귀 아이템을 선택하도록 설정한 기준 확률입니다. 관측 비율은 실제 호출에서 발생한 횟수로 계산하므로 목표값과 조금 다를 수 있습니다. Wilson 95% 구간은 제한된 관측 횟수로 발생률을 추정할 때의 불확실성을 나타냅니다. 두 구간 모두 목표 확률을 포함하지만, 이것만으로 모든 플레이 조건에서 같은 비율이 유지된다고 판단하지 않습니다.
퀘스트 측정은 실제 대화창을 열고 스태미나 100, 소지금 1,000과 활성 퀘스트가 없는 상태를 설정한 뒤, 호출마다 InteractionEnd=false로 초기화한 조건부 퀘스트 제안입니다. 희귀 아이템 측정은 실제 선택 함수와 원본 Data Table의 행을 확인합니다. 각 10,000회는 함수 호출 수이며 전체 대화나 퀘스트 완료 또는 플레이 세션의 수와 구분합니다.
해결하려던 문제
게임 속 NPC가 상황과 관계의 변화를 반영하지 못한 채 같은 대사를 반복하면 세계가 정적으로 느껴진다고 생각했습니다. 이에 시간표에 따른 일과와 플레이어 상태, NPC별 관계를 하나의 흐름으로 연결해 대화와 퀘스트, 거래 및 동행이 서로 영향을 주는 시스템을 만들고자 했습니다.
이렇게 연결한 기능이 자연스럽게 이어지려면 상황에 맞는 판단 순서도 필요했습니다. 비교한 구현에서는 활성 퀘스트가 없을 때 새 퀘스트를 제안하는 난수 판단이 피로와 소지금 부족에 관한 일반 대화보다 먼저 실행됐습니다. 또 활동 시간이 끝나면 상호작용 중에도 귀가 의도가 설정될 수 있었습니다.
게임의 기본 기능과 데이터 구조를 유지하면서 이 두 판단 조건을 수정하고, 실제 Actor와 원본 Blueprint 실행 경로를 대상으로 동작을 검증했습니다. 원본 전체 프로젝트와 작은 핵심 에셋 ZIP의 역할도 구분해 실행에 필요한 자료를 함께 안내했습니다.
시스템 구조와 구현
- 시간과 상태
게임 시간, 스태미나, 소지금과 NPC별 관계 상태 확인
- 행동과 대상 판단
시간표와 Blackboard, 실제 겹침 및 Actor 전방 방향 평가
- 상호작용 실행
기존 Blueprint에서 대화, 퀘스트, 거래 및 동행 처리
- 결과 반영
인벤토리, 보상과 NPC별 신뢰도를 Data Table과 연결
- 행동 전환
상호작용 상태를 반영해 순찰, 동행과 귀가 결정
| 구성 | 역할 |
|---|---|
| 게임 상태와 NPC | 공통 시간과 플레이어 상태, NPC별 신뢰도 및 퀘스트 상태 관리 |
| Behavior Tree와 Blackboard | 순찰, 동행, 귀가 및 상호작용 상태 평가 |
| Data Table | NPC의 활동 시간과 관계 조건, 아이템 및 퀘스트 정보 정의 |
| 상호작용과 UMG | 상호작용 처리와 화면 제작 도구를 연결해 대상 선택, 대화창, 거래 및 아이템 사용 지원 |
| 에디터 검증 플러그인 | 실제 게임 객체와 Blueprint 호출, 이동 상태 및 측정 결과 기록 |
| 소스 복원 도구 | 원본 전체 압축 파일과 명시적 수정 파일을 결합하고 해시 검증 |
상호작용할 대상은 대화할 수 있는 거리 안에 들어와 플레이어의 감지 영역과 겹치는 NPC 중 플레이어 Actor의 전방 방향을 기준으로 계산한 점수가 가장 높은 NPC입니다. 즉 가까이에 있는 후보 중 캐릭터가 바라보는 방향에 가장 잘 맞는 대상을 고릅니다. 30개 검증 조건에서는 원본 NPC 3명의 위치를 고정하고 세 명이 실제 겹침 목록에 있는지 확인한 뒤 플레이어 Actor의 회전만 바꿨습니다. 방향 점수가 정확히 같은 경우는 제외하고 기대 대상을 미리 지정했습니다.
게임에 배치된 원본 Behavior Tree의 순찰과 동행 작업 인스턴스는 각각 속도 150을 사용합니다. 실제 실행에서도 두 경로의 CharacterMovement.MaxWalkSpeed=150을 확인했으며, 원래 작업 인스턴스와 이동 설정을 유지했습니다.
실험과 검증
| 확인 영역 | 실행 방식과 범위 |
|---|---|
| 상태 검증 | 실제 원본 맵의 플레이어와 NPC, 동일한 기대 조건 78개 |
| 대상 선택 | 실제 겹침 상태와 사전에 정한 Actor 방향 조건 30개 |
| 거래와 아이템 사용 | 실제 UMG 버튼 이벤트와 소지금, 수량, 신뢰도 및 스태미나 확인 |
| 퀘스트 상태 | 원본 Data Table 행을 사용한 요구 조건과 보상 상태 확인 |
| 확률 측정 | 실제 대화와 아이템 선택 함수 각각 10,000회 |
| Blueprint 컴파일 | 46/46개 통과, 오류 0개와 경고 0개 |
| 실제 이동 | 원본 맵과 Behavior Tree의 순찰, 동행 및 귀가 3/3단계 통과 |
| 실제 입력과 재등장 | PlayerController의 E 입력 경로, 신뢰도 경계 및 60초 재등장 6/6항목 통과 |
| NPC 수에 따른 부하 | NPC 5명, 20명과 50명을 각각 3회 실행해 9/9회 측정 조건 충족 |
개발 보고서에는 기능 검사 11개와 100회 확률 측정이 기록돼 있습니다. 이 측정의 관측값은 퀘스트 11/100회와 희귀 아이템 14/100회였습니다. 여기서 제시한 상태 검증과 10,000회 함수 측정은 보고서와 조건 및 분모가 다른 별도 실험이며, 보고서의 기록도 그대로 보존합니다.
실제 이동 검증은 순찰, 동행과 귀가 3개 단계 모두 통과했습니다. 원본 맵과 Behavior Tree를 실행해 엔진이 계산한 경로를 따라 실제로 이동하는지 확인하고, 목적지에 도착했을 때 발생하는 콜백 신호도 검사했습니다. 아래의 uu는 Unreal Engine 공간의 길이 단위이며, 2D 변위는 시작점에서 수평 방향으로 얼마나 떨어졌는지를 나타냅니다.
| 이동 단계 | 실제 관측 결과 |
|---|---|
| 순찰 | 유효한 경로를 따라 이동하며 최대 2D 변위 260.63uu 관측 |
| 동행 | 플레이어와의 거리 800.00uu에서 511.90uu로 감소, NPC 최대 2D 변위 293.17uu 관측 |
| 귀가 | 최대 2D 변위 390.32uu와 이동 성공 콜백, 이후 Actor 숨김 및 충돌 비활성화 확인 |
변위는 단계 시작 위치로부터의 최대 거리입니다. 귀가는 약 400uu 떨어진 도달 가능한 위치를 시험 목적지로 제공해 원래 귀가 경로를 실행했으며, 작성된 모든 귀가 좌표의 도달 가능성까지 확인한 범위는 아닙니다.
실제 입력과 인벤토리 검증은 6/6항목을 통과했습니다. 플레이어의 입력을 처리하는 PlayerController의 InputKey에 E 누름과 해제를 전달해 새 아이템 묶음과 기존 묶음의 수량 증가를 확인했습니다. 실제 Charles 거래 화면은 신뢰도 99에서 상품 3개, 100과 101에서 4개를 표시했습니다. 아이템은 두 번째 획득 후 게임 시간 60.005초에 다시 표시되고 충돌이 활성화돼 원래 60초 재등장 경로도 확인했습니다. 검증 범위는 엔진의 입력 처리 경로와 실제 위젯입니다.
NPC 5명, 20명과 50명을 각각 3회 실행한 부하 측정 9회가 모두 측정 조건을 충족했습니다. Unreal Engine 5.4.4, Intel Core i7-11800H와 NVIDIA GeForce RTX 3060 Laptop GPU에서 D3D12로 실행했으며, 실제 게임 뷰포트는 1280 × 720입니다. 각 실행에서 10초간 준비한 뒤 15초간 수집했습니다.
월드 Actor Tick은 한 프레임에서 게임 객체의 상태를 갱신하는 처리 구간이고, 에디터 프레임 간격은 화면이 다음 프레임으로 넘어가기까지 걸린 시간입니다. 두 값 모두 작을수록 해당 구간의 처리 시간이 짧습니다. 아래 중앙값은 측정값을 작은 순서로 나열했을 때 가운데에 해당하는 값입니다.
| NPC 수 | 월드 Actor Tick 중앙값 (ms) | 실행별 중앙값 범위 (ms) | 에디터 프레임 간격 중앙값 (ms) | 실행별 중앙값 범위 (ms) |
|---|---|---|---|---|
| 5 | 4.7614 | 4.6336–4.9032 | 15.1708 | 15.0291–15.1734 |
| 20 | 8.7988 | 8.6760–8.8901 | 15.6843 | 15.6178–15.8183 |
| 50 | 16.7516 | 16.3960–16.9055 | 23.8683 | 23.5253–24.1792 |
대표값은 실행별 중앙값 3개의 중앙값이며, 범위는 그 3개 중앙값의 최솟값과 최댓값입니다. 모든 실행에서 같은 NPC의 25uu 초과 변위와 이동 중인 유효 경로를 함께 관측해 실제 이동이 포함된 부하임을 확인했습니다. 원래 대기 행동도 유지하므로 모든 NPC가 계속 걷는 조건은 아닙니다.
오류 분석과 개선 범위
| 재현한 문제 | 수정 및 확인 방식 |
|---|---|
| 활성 퀘스트가 없을 때 퀘스트 제안이 긴급 대화보다 우선 | 진행 중인 퀘스트 처리는 유지하고, 그 외에는 스태미나 30 이하와 소지금 0을 확인한 뒤 설정한 퀘스트 확률 판단 실행 |
| 상호작용 중 활동 시간이 끝나면 귀가 의도가 설정됨 | IsInteracting 동안 새 귀가 의도를 설정하지 않고 상호작용 종료 후 원래 흐름 재개 |
| 에디터에서 마을 지형이 로드되지 않은 채 빈 내비게이션 생성 | 실제 내비게이션 영역과 LevelInstance를 로드한 뒤 생성하고 유효한 범위 및 실제 타일 확인 |
| 외부 Butterfly 에셋의 생성 스크립트에서 비권장 애니메이션 호출 | 원래 애니메이션 선택과 재생률 계산을 유지하며 생성 스크립트용 OverrideAnimationData로 교체 |
| 핵심 에셋 압축 파일만으로 전체 게임 실행이 어려움 | 별도 원본 전체 압축 파일, 명시적 수정 파일과 복원 도구의 역할 분리 |
게임 기능의 변경은 대화 우선순위와 상호작용 중 귀가 조건에 한정합니다. 지형 로드와 NPC가 이동할 수 있는 영역을 준비하는 내비게이션 처리는 원본 설정을 유지한 에디터 생성 절차이며, 검증 플러그인은 실제 게임 객체를 호출합니다. 원본 코드와 실험 결과는 보존하고, 적용한 파일의 목록과 내용 확인값을 담은 manifest로 수정 파일을 대조할 수 있게 했습니다. 이 확인값인 해시는 내려받거나 복원한 파일의 내용이 기록과 같은지 검사하는 데 사용합니다.
개발 중 별도로 진행한 Qwen 대화 생성 실험은 게임의 제약 조건을 일관되게 따르지 못해 본 게임에 통합하지 않았습니다. 실제 게임의 대화와 행동은 직접 작성한 규칙 기반 AI로 동작합니다.
실행 화면과 재현 방법



먼저 전체 프로젝트 복원과 검증 ZIP을 받고, 원본 전체 Project.zip을 별도로 다운로드합니다. 원본 압축 파일은 2,257,866,122바이트로 약 2.26GB이며 작은 검증 ZIP에 포함하지 않습니다. 작은 ZIP은 수정 파일과 도구를 담으며 전체 프로젝트는 두 자료를 결합해 복원합니다.
압축을 해제한 검증 ZIP의 루트에서 Python 3.10 이상으로 다음을 실행합니다. 예시는 원본 전체 압축 파일을 상위 폴더에 둔 경우입니다.
python -X utf8 -B tools/verify_bundle.py --expected-source-version 1
python -X utf8 -B tools/restore_project.py --archive "../Project.zip" --output "../NPC-Verify" --expected-source-version 1
출력은 존재하지 않는 새 폴더로 지정합니다. 이후 README의 절차에 따라 Unreal Engine 5.4.4와 호환되는 C++ 도구로 소스부터 빌드하고 실제 엔진 검증을 실행합니다. Python 도구의 Windows 및 Linux 검사는 파일 검증과 복원 도구의 범위이며 실제 게임 실행 검증 환경은 Windows입니다.
새 폴더에서 프로젝트 소스 트리의 파일 2,371개를 복원하고 해시를 확인했습니다. 최초 소스 빌드는 작업 29개를 53.02초에 완료했으며, 이어 같은 복원본에서 Blueprint 46개가 오류 0개와 경고 0개로 컴파일되고 실제 게임 검증 7종도 모두 통과했습니다. 이는 기록한 Windows 환경에서 같은 컴퓨터의 새 폴더로 재현한 결과이며 다른 컴퓨터에서의 독립 검증과는 구분합니다.
새 복원본 검증 보고서에서 후속 빌드 확인, Blueprint 컴파일과 실제 게임 검증 7종의 실행 결과를 확인할 수 있습니다.
소스 코드와 검증 자료
저장소 문서는 영어를 기본으로 한국어도 제공합니다. 원본 핵심 에셋 30개와 보고서는 개발 기록으로 보존하고, 실행에 필요한 수정 파일과 검증 플러그인 소스, 도구 및 manifest는 별도로 정리했습니다. 핵심 에셋 ZIP만으로 전체 게임을 실행할 수 없으며 전체 프로젝트 복원에는 위의 원본 압축 파일이 필요합니다.
전체 프로젝트 복원과 검증 ZIPGitHub에서 소스 코드 보기

