언리얼 엔진 C++·블루프린트 분석 사례
실시간 데모나 IDE를 재현한 화면이 아닌 기록된 MCP 호출입니다. NarshaMCP v0.13.7, Lyra Starter Game, UE 5.8.1, 에디터 종료 상태에서 수집했습니다. 해당 실행의 결과를 보여주며, 모든 에셋의 지원 범위나 성능을 보증하는 벤치마크가 아닙니다.
웹사이트 빌드 시 저장소의 공개 README를 읽어 아래 JSON/JSONC 발췌와 생략 주석을 그대로 표시합니다. 공개된 발췌 전체이며, 생략 전 런타임 응답 전체는 아닙니다. 링크된 공개 README는 이 사이트 빌드 이후 변경될 수 있습니다.
오프라인 파싱으로 무엇이 달라지나요?
섹션 제목: “오프라인 파싱으로 무엇이 달라지나요?”이 기록에서 확인되는 개선은 에이전트가 소스 텍스트 밖의 프로젝트 맥락까지 확인할 수 있다는 점입니다. 제품이 반환한 실제 응답이며, 독립적인 정확도 평가나 모든 MCP를 대상으로 한 비교 실험은 아닙니다.
- 저장된 값 확인: 소스 검색에서는
FireDelayTimeSecs를 찾지 못했지만, 바이너리 분석은GA_Weapon_Fire의 기본값 0.1을 반환했습니다. 에이전트가 검토할 수 있는 구체적인 저장값이며, 실행 중 평가한 핀 값은 아닙니다. - C++과 Blueprint의 호출 관계 연결: 소스 검색은
StartRangedWeaponTargeting의 C++ 선언과 정의를 찾았습니다. MCP 응답은 호출을 포함한 이벤트와 함께 Blueprint 호출 지점 2개를 추가로 보여줍니다. qualified 매칭, 점수 0.75이며 정확도 비율은 아닙니다. - 동작 구조 조사: StateTree 응답은 상태 9개와 프로퍼티 바인딩 19개를 보고했습니다. 에이전트는 편집에 앞서 반환된 태스크와 전환을 확인할 수 있습니다. 공개 발췌는 트리 전체가 아닌 선택한 상태를 표시합니다.
비교 범위
섹션 제목: “비교 범위”소스 검색은 샘플 프로젝트의 Source/와 Plugins/ 아래에서 읽을 수 있는 .h·.cpp 파일을 대상으로 했습니다. 소스 텍스트 기준선이며 AI 에이전트의 실패율 측정이 아닙니다. 바이너리에도 읽을 수 있는 문자열이 있을 수 있지만, 문자열 검색만으로 그래프나 타입이 있는 값을 복원하지는 못합니다.
MCP 읽기는 설치·인덱싱 이후 에디터 종료 상태에서 기록했습니다. 지원되는 디스크 읽기는 리서치 과정에서 에디터·커맨드릿을 실행하는 단계를 없앱니다. 초기 설치·프로젝트 빌드·인덱싱은 여전히 필요합니다. 일부 응답은 바이너리 파싱으로 생성한 메타데이터 캐시를 사용하며, 모든 요청이 패키지를 처음부터 다시 파싱하는 것은 아닙니다. 에디터에서 아직 저장하지 않은 변경은 디스크 파일에 포함되지 않습니다.
이 기록에서 측정하지 않은 항목: 소요 시간·최대 메모리·토큰 절감과 AI 답변 정확도 개선. 이를 비교하려면 같은 에셋·질문·응답 범위로 초기 상태와 캐시가 준비된 상태를 나누고, 설치·인덱싱 비용까지 명시해야 합니다. 아래에는 기존 실행 조건과 생략 표시를 유지한 원문을 제공합니다.
C++ ↔ Blueprint
섹션 제목: “C++ ↔ Blueprint”이 C++ 함수를 호출하는 Blueprint는?
호출을 포함한 Blueprint 이벤트와 매칭된 C++ 심볼을 찾습니다. NarshaMCP v0.13.7 · Lyra Starter Game · UE 5.8.1 · 에디터 종료 상태.
출처: 공개 README의 기록된 실행 결과. 다음 블록은 원문의 요청과 응답 발췌를 그대로 표시하며, // 주석은 생략된 키와 배열 요소를 나타냅니다.
find_cpp_to_bp — 요청과 응답 펼치기
MCP 요청
{"name": "ue_analyze_symbols", "arguments": {"operation": "find_cpp_to_bp", "function_name": "ULyraGameplayAbility_RangedWeapon::StartRangedWeaponTargeting", "limit": 5}}기록된 응답 발췌
{ "function_name": "ULyraGameplayAbility_RangedWeapon::StartRangedWeaponTargeting", "total_callers": 2, "truncated": false, "blueprint_callers": [ { "blueprint_name": "GA_Weapon_Fire", "blueprint_path": "/Game/Weapons/GA_Weapon_Fire", "owning_function": "K2_ActivateAbility", "node_name": "K2Node_CallFunction_31", "match_tier": "qualified", "confidence": 0.75 }, { "blueprint_name": "GA_WeaponNetShooter", "blueprint_path": "/ShooterCore/Weapons/NetShooter_PROTO/GA_WeaponNetShooter", "owning_function": "K2_ActivateAbility", "node_name": "K2Node_CallFunction_31", "match_tier": "qualified", "confidence": 0.75 } ] // [truncated] blueprint_callers[] fields omitted: call_type, is_pure; keys omitted: operation, skip_dedup, success}find_bp_to_cpp — 요청과 응답 펼치기
MCP 요청
{"name": "ue_analyze_symbols", "arguments": {"operation": "find_bp_to_cpp", "blueprint_name": "GA_Weapon_Fire", "limit": 2, "offset": 18}}기록된 응답 발췌
{ "blueprint_name": "GA_Weapon_Fire", "total_calls": 33, "offset": 18, "truncated": true, "cpp_calls": [ { "full_name": "LyraGameplayAbility_RangedWeapon::StartRangedWeaponTargeting", "owning_function": "K2_ActivateAbility", "node_name": "K2Node_CallFunction_31", "is_pure": false }, { "full_name": "KismetSystemLibrary::SetTimerDelegate", "owning_function": "K2_ActivateAbility", "node_name": "K2Node_CallFunction_4", "is_pure": false } ] // [truncated] cpp_calls[] fields omitted: function_name, owner_class; keys omitted: operation, returned, success, total_count}trace_hierarchy — 요청과 응답 펼치기
MCP 요청
{"name": "ue_analyze_symbols", "arguments": {"operation": "trace_hierarchy", "class_name": "ALyraCharacter", "direction": "down"}}기록된 응답 발췌
{ "class_name": "ALyraCharacter", "cpp_descendants_count": 1, "bp_descendants_count": 10, "descendants": [ {"depth": 1, "name": "ALyraCharacterWithAbilities", "relation": "child", "source": "pdb"}, {"depth": 1, "name": "Character_Default", "relation": "child_blueprint", "source": "blueprint"}, {"depth": 2, "name": "B_Hero_Default", "relation": "child_blueprint", "source": "blueprint"}, {"depth": 2, "name": "B_ShootingTarget", "relation": "child_blueprint", "source": "blueprint"} ], "interface_parents": ["IAbilitySystemInterface", "IGameplayCueInterface", "IGameplayTagAssetInterface", "ILyraTeamAgentInterface"] // [truncated] descendants: 4 of 11 elements; descendants[] fields omitted: parent; keys omitted: 13 of 18}정방향 조회는 Blueprint 호출 지점 2개를 반환하며 match_tier: "qualified", confidence: 0.75를 포함합니다. 도구의 매칭 점수이며 별도로 측정한 정확도 비율이 아닙니다. 역방향 조회는 총 33개 호출 중 offset 18부터의 발췌이며 2개 호출만 표시합니다. 클래스 계층은 하위 클래스 11개 중 4개를 표시합니다.
Blueprint 내부
섹션 제목: “Blueprint 내부”GA_Weapon_Fire 안에는 무엇이 있을까?
에셋에서 이벤트, 변수 기본값, 노드 연결을 읽습니다. NarshaMCP v0.13.7 · Lyra Starter Game · UE 5.8.1 · 에디터 종료 상태.
출처: 공개 README의 기록된 실행 결과. 다음 블록은 원문의 요청과 응답 발췌를 그대로 표시하며, // 주석은 생략된 키와 배열 요소를 나타냅니다.
get_event_graph — 요청과 응답 펼치기
MCP 요청
{"name": "ue_manage_blueprint", "arguments": {"operation": "get_event_graph", "blueprint_name": "GA_Weapon_Fire"}}기록된 응답 발췌
{ "blueprint_name": "GA_Weapon_Fire", "count": 5, "events": [ {"node_title": "FireComplete", "node_class": "K2Node_CustomEvent"}, {"node_title": "FailureMontage Delay Complete", "node_class": "K2Node_CustomEvent"} ] // [truncated] events: 2 of 5 elements; events[] fields omitted: node_id, owning_function; keys omitted: operation, success}search_variables — 요청과 응답 펼치기
MCP 요청
{"name": "ue_manage_blueprint", "arguments": {"operation": "search_variables", "blueprint_name": "GA_Weapon_Fire", "pattern": "*Fire*"}}기록된 응답 발췌
{ "parent_class": "LyraGameplayAbility_RangedWeapon", "total_count": 2, "results": [ { "name": "CharacterFireMontage", "default_value": "AM_MM_Rifle_Fire", "default_value_type": "Object", "edit_condition": "EditDefaultsOnly" }, { "name": "FireDelayTimeSecs", "default_value": "0.1", "default_value_type": "Double", "edit_condition": "EditDefaultsOnly" } ] // [truncated] results[] fields omitted: 9 of 13; keys omitted: 14 of 17}get_raw_nodes — 요청과 응답 펼치기
MCP 요청
{"name": "ue_manage_blueprint", "arguments": {"operation": "get_raw_nodes", "blueprint_name": "GA_Weapon_Fire", "page": 1, "page_size": 1}}기록된 응답 발췌
{ "total_nodes": 98, "has_more": true, "nodes": [ { "id": "K2Node_AsyncAction_ListenForGameplayMessages_0", "node_class": "K2Node_AsyncAction_ListenForGameplayMessages", "owning_function": "K2_OnAbilityAdded", "pins": [ { "name": "execute", "category": "exec", "direction": "input", "linked_to": [ {"node_id": "K2Node_Event_1", "pin_name": "then", "export_index": 70} ] }, {"name": "then", "category": "exec", "direction": "output", "linked_to": []} ] } ] // [truncated] nodes[].pins: 2 of 12 elements; nodes[].pins[].linked_to[] fields omitted: owning_function; nodes[].pins[] fields omitted: container_type, default_value, pin_id, sub_category; nodes[] fields omitted: 5 of 9; keys omitted: 10 of 13}이벤트 발췌에는 총 5개 중 2개가 표시됩니다. 변수 결과에는 기본값 2개가 포함됩니다. 노드 요청은 페이지 단위로 조회하며, 공개된 발췌에서는 주석에 표시한 일부 필드를 생략했습니다. 홈과 발췌가 전체 그래프를 나타내지는 않습니다. 데이터 핀은 연결만 반환하며 값을 평가하지 않습니다. 실행 순서만 추적합니다.
StateTree 구조
섹션 제목: “StateTree 구조”이 StateTree는 어떻게 상태를 전환할까?
에디터를 열지 않고 태스크와 상태 전환을 확인합니다. NarshaMCP v0.13.7 · Lyra Starter Game · UE 5.8.1 · 에디터 종료 상태.
출처: 공개 README의 기록된 실행 결과. 다음 블록은 원문의 요청과 응답 발췌를 그대로 표시하며, // 주석은 생략된 키와 배열 요소를 나타냅니다.
get_summary — 요청과 응답 펼치기
MCP 요청
{"name": "ue_manage_ai", "arguments": {"operation": "get_summary", "ai_type": "statetree", "asset_name": "L_STT_FollowPlayer"}}기록된 응답 발췌
{ "asset_name": "L_STT_FollowPlayer", "root_state": "Root", "state_count": 9, "property_binding_count": 19, "states": [ { "name": "Wait 3s Follow", "tasks": ["StateTreeDebugTextTask", "StateTreeDelayTask"], "transitions": [ {"trigger": "OnStateCompleted", "to_state": "Wait 3s Follow TooClose"}, {"trigger": "OnStateCompleted", "to_state": "Follow"} ] }, { "name": "Follow", "tasks": ["STT_Follow"], "transitions": [ {"trigger": "OnStateSucceeded", "to_state": "Root"}, {"trigger": "OnStateFailed", "to_state": "Wait 3s FailFollow"} ] } ] // [truncated] states: 2 of 9 elements; states[] fields omitted: conditions, enabled, state_type; keys omitted: 11 of 16}이 에셋의 상태 수는 9개, 프로퍼티 바인딩 수는 19개입니다. 발췌에는 상태 2개가 포함되며 조건과 다른 필드의 생략이 표시되어 있습니다. 홈에서는 Wait 3s Follow → Follow → Root 경로만 그립니다. 대체 경로와 실패 전환은 기록된 발췌에서 확인할 수 있습니다. 구조 데이터이며 런타임 동작의 시뮬레이션은 아닙니다.
결과 해석 시 확인할 내용
섹션 제목: “결과 해석 시 확인할 내용”- 매칭 결과는 소스, PDB, 지원되는 에셋 데이터에 영향을 받습니다. PDB 분석에는 성공한 빌드가 필요하며 엔진 클래스를 포함하려면 엔진 심볼도 필요합니다.
- Cooked 에셋은 읽지 못합니다. Latent·비동기·delegate 연결은 근사 처리합니다.
- 큰 결과는 로컬 파일을 가리키는
detail_handle로 반환될 수 있습니다.ue_cache_control/resolve_detail_handle로 읽거나limit등으로 범위를 줄이세요. - 에셋 수정에는 실행 중인 에디터가 필요합니다. 이 읽기 사례는 수정 기능을 검증하지 않습니다.