로컬 전투 프로토타입 원본 로비와 전투 HUD를 다시 연결하기
원본 UI를 플레이 흐름에 연결하기
기존 검토본에서 카메라와 UI가 원작과 다르다는 피드백을 받아, 배포 자료의 NGUI 계층·스프라이트·폰트·클리핑 정보를 다시 확인했습니다. 회수한 배치를 Unity의 편집 가능한 uGUI로 옮기고, 장비 선택과 로비에서 전투로 넘어가는 흐름에 연결했습니다.
공개 글에는 원작명이 포함된 실행 화면을 게시하지 않습니다. 실제 화면 대조 자료는 작업 원본에 보존했습니다.
원본 배포 자료에서 가져온 모델·텍스처를 다시 연결한 작업입니다. 새로 직접 조형한 장비로 소개하지 않습니다. 원본 자료는 보존하고, 호환 코드와 수정 재질·프리팹은 프로젝트 소유 파생 자산으로 저장했습니다.
로비 화면에서 무기를 고르면 모델과 공격력이 함께 바뀌고, 전투에 들어갔다 돌아와도 선택이 유지됩니다. Build19를 실제 Windows에서 조작해 무기10140에서10120으로 바꾼 뒤 Arena 진입과 Lobby 복귀를 확인했습니다. 일부 프리팹 내부 글자와 레이어 수정이 저장되지 않는 현상은 플레이용 로비를 씬으로 풀어 저장한 다음 새 빌드에서 확인했습니다.
로비 캐릭터가 등을 보이던 문제도 원작 배치만 추정해서 해결하지 않았습니다. LobbyHeroController의 자세 초기화 코드에서180도 회전을 확인하고 원작 카메라와 무기군별 대기 클립을 함께 연결했습니다. 로비 캐릭터 카메라의20도 FOV와 전투 카메라의26.1도 FOV를 구분했습니다.
전투 HUD와 입력
Build20에서는 원본 체력 구간·시간·생존자 표시와 버튼 배치를 연결했습니다. 원작 HeroInfoUI 실행 코드에서 한 구간이30HP인 것을 확인해, 체력390일 때13칸을 표시합니다. 실제 전투 중390→66→0으로 체력이 줄면서 파란 구간도 줄었습니다. 0HP 상태도 확인했으며 사망 자세와 결과 화면은 아직 추가 복원이 필요합니다.
원본 조이스틱 그림은 드래그 입력에 연결했습니다. 화면 좌표를 조이스틱의 로컬 좌표로 바꿔 반경 안으로 제한하고, 카메라 방향에 맞춰 이동 입력으로 전달합니다. 포인터를 놓거나 UI가 비활성화되면 입력과 손잡이를 초기화합니다.
flowchart TD
A[PointerDown] --> B[포인터 소유권 기록]
B --> C[로컬 좌표와 반경으로 입력 계산]
C --> D[카메라 기준 이동]
B --> E[PointerUp 또는 비활성]
E --> F[입력과 손잡이 초기화]
다음은 조이스틱 컴포넌트 전체입니다. 공개 예제의 네임스페이스는 Prototype으로 익명화했으며 실제 프로젝트 소스는 보존했습니다.
using UnityEngine;
using UnityEngine.EventSystems;
namespace Prototype
{
/// <summary>
/// 하나의 포인터를 소유하여 원작 스틱 표시와 전투 이동 입력을 함께 갱신한다.
/// </summary>
public sealed class RestoredMoveStick : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
{
public RectTransform knob, arrow;
public float radius = 60;
private int _pointer = int.MinValue;
/// <summary>
/// 화면이나 오브젝트가 비활성화될 때 남아 있는 이동 입력을 해제한다.
/// </summary>
private void OnDisable()
{
Release();
}
/// <summary>
/// 소유 중인 포인터가 없으면 누른 포인터를 연결하고 첫 이동값을 적용한다.
/// </summary>
public void OnPointerDown(PointerEventData data)
{
// 두 번째 손가락이 기존 이동 방향을 덮어쓰지 못하도록 소유권을 유지한다.
if (_pointer != int.MinValue)
{
return;
}
_pointer = data.pointerId;
OnDrag(data);
}
/// <summary>
/// 연결된 포인터의 UI 로컬 좌표를 반경 안의 이동값과 방향 표시로 변환한다.
/// </summary>
public void OnDrag(PointerEventData data)
{
var session = ArenaSession.Instance;
if (_pointer != data.pointerId || session == null || !session.IsFighting)
{
return;
}
if (!RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)transform, data.position, data.pressEventCamera, out var point))
{
return;
}
// 입력 크기를 1로 제한하여 스틱 밖을 끌어도 이동 속도가 증가하지 않게 한다.
var value = Vector2.ClampMagnitude(point / radius, 1);
session.TouchMove = value;
knob.anchoredPosition = value * radius;
arrow.gameObject.SetActive(value.sqrMagnitude > .01f);
arrow.localRotation = Quaternion.Euler(0, 0, Mathf.Atan2(value.y, value.x) * Mathf.Rad2Deg - 90);
}
/// <summary>
/// 소유한 포인터가 떼어졌을 때만 이동과 스틱 표시를 초기화한다.
/// </summary>
public void OnPointerUp(PointerEventData data)
{
if (_pointer == data.pointerId)
{
Release();
}
}
/// <summary>
/// 포인터 소유권을 반환하고 남은 이동값과 방향 표시를 제거한다.
/// </summary>
private void Release()
{
_pointer = int.MinValue;
if (ArenaSession.Instance != null)
{
ArenaSession.Instance.TouchMove = Vector2.zero;
}
if (knob != null)
{
knob.anchoredPosition = Vector2.zero;
}
if (arrow != null)
{
arrow.gameObject.SetActive(false);
}
}
}
}
Windows에서 조이스틱 드래그와 회피 버튼을 직접 조작하고 위치 변화를 관찰했습니다. 다만 입력별 이동량·명중·쿨다운 정확도는 별도 검증이 남았습니다. 스킬 버튼은 캐릭터 사망 후 눌려 해당 실행에서는 효과를 확인하지 못했습니다.
Excel 수식과 DDT 계산
데이터 편집 원본은 수식이 있는 XLSX로 바꿨습니다. 기본 수치와 성장 표, 장비 표시 데이터가 ID 조회 수식으로 연결되고, 기존 DDT 리더와 수식 엔진으로 계산해 게임용 바이너리를 만듭니다.
실제 Unity 메뉴에서 XLSX를 읽고 메모리상의 배율을1에서1.1로 바꿨습니다. 무기10750의 기본 공격력은120에서132, 성장 포함 미리보기는203에서215로 바뀌었습니다.38개 Gear 행을 암호화 DDT 바이너리로 써서 다시 읽은 값도132였습니다. 입력을 복원한 뒤 미리보기는203으로 돌아왔고 원본 XLSX 바이트는 동일했습니다. 전체26개 표·6,525행 재컴파일 전후 바이너리 해시도 모두 같았습니다.
이 검사는 DDT 엔진 내부의 입력 변경·계산·바이너리 소비 경로를 확인한 것입니다. 저장된 XLSX 변경이 Windows 공격력 표시까지 이어지는 검사와는 구분합니다.
샘플 기준 코드 작성과 개발 다큐먼트
코드 규칙은 SampleProjectForUnity의 작성 문서와 실제 SceneEntry 코드를 함께 확인했습니다. 로컬 참조 커밋은 c7b40e5cff3f8310d6f58fa51e54d77dc507bd31입니다. 로비 제어·카메라·장비 카드·전투 HUD·가상 스틱의 5개 컴포넌트부터 3줄 XML 요약, 한국어 계약·처리 이유 주석, 생명주기 함수 우선 배치와 중괄호 형식을 적용했습니다. 포인터 소유권, 원작 좌표계 환산, 30HP 구간, 장비 선택 API가 차이를 입력받는 이유를 코드에 남겼습니다.
개발 문서는 프로젝트 구조 → 흐름 다이어그램 → 개발된 기능과 사용법 → 작성 규칙 → 갱신 기록으로 나눴습니다. 원작과 일치하지 않은 셰이더, 미연결 메뉴, 실제 실행하지 않은 범위를 함께 기록합니다. Unity에서18:53:36 KST에 컴파일된 런타임 어셈블리를 확인하고18:54:13 KST에 로비 Play에 재진입했습니다. 전체 전투 코드와 에디터 도구의 규칙 적용은 계속 진행합니다.
개발 문서 원문과 적용한 컴포넌트 전체 소스는 프로젝트 내부에 보존했습니다.
장비 표는 사용자 설명대로 Equipment가 공통 마스터입니다. 무기와 방어구119종의 공통 속성을 담으며, Gear38행과 Armor81행이 같은 ID의 상세 데이터를 제공합니다. XLSX 내부를 직접 읽어 확인한 시트 수는31개이며,31개 미리보기 이미지가 존재합니다. 모든 시트의 시각 검토는 아직 마치지 않았습니다.
후속 복원 범위
이전 고정 Build11의10시간 검증은36,000.0195초와350경기로 종료됐습니다. 무기38종·방어구81종 및38종의 공격·스킬 명령 기록을 확인했습니다. 시작 시 기록한 해시는2개만 대조했고, 원작 FX의 누락 스크립트 경고1건은 알려진 항목으로 남았습니다. 새 Build20의 짧은 수동 검증을10시간 검증 결과로 합치지 않았습니다.
장비 카드 스크롤과 일부 글자 잘림, 임시 통화·알림, 미니맵·버프·피격 잔상·결과 UI를 이어서 복원해야 합니다. 원작 파티클은 모듈과 의존 자산을 연결해6개 시스템의 프리뷰 재생을 확인했으며 실제 무기 이벤트 연결과 셰이더·음향 대조는 진행 중입니다. 카메라 수치와 UI가 연결됐다는 이유만으로 원작 조작감 전체가 같다고 판정하지 않습니다.
로비 회차는16:52–17:49 KST 약57분, HUD 구현·Windows 실행 구간은17:50–18:07 KST 약17분이었습니다. 제안 시간은 각각30–60분과45–75분이었으며, 후자는 장비 화면 후속 작업을 포함해 계속 진행 중입니다. DDT 수식 검증은18:17에 시작해18:24:49 KST에 확인을 마쳤습니다.
장비 열람과 착용 분리·사망 포즈 후속 확인
후속 구현은 2026-11-13 19:11:05 KST에 시작했습니다. 제안 시간은40~60분이었고, Windows 실행 확인은19:44:06 KST에 끝났습니다(33분1초). 문서·게시 준비는 별도 구간입니다.
장비 화면은 동일 크기 카드 나열에서 중앙 카드와 작은 인접 카드가 보이는 가로 캐러셀로 바꿨습니다. 원작 직렬화 자료에서 카드 간격210과 중앙 정렬 강도16을 확인했습니다. 옆 카드 축소율0.65는 공개 화면 대조에 따른 대응값이며 원작 상수로 확인한 값은 아닙니다. 고정 카드10개를 재사용하고 범위 밖 카드는 숨깁니다.
flowchart TD
A[클릭·휠·드래그] --> B[열람 인덱스 변경]
B --> C[카드 풀 재연결·위치와 크기 계산]
D[장착 버튼] --> E[세션 장비 변경]
E --> F[모델·능력치·장착 표시 갱신]
다음은 카드 배치 핵심 메서드 전체입니다. 제품 식별 이름을 포함하지 않는 공개 예제이며 카드 슬롯과 데이터 인덱스를 분리합니다.
private void UpdateLayout()
{
if (items == null)
{
return;
}
int center = items.Length / 2;
for (int index = 0; index < items.Length; index++)
{
int dataIndex = _focus + index - center;
var item = items[index];
item.gameObject.SetActive(dataIndex >= 0 && dataIndex < _count);
float distance = dataIndex - _position;
item.anchoredPosition = new Vector2(distance * cellWidth, 0);
item.localScale = Vector3.one * Mathf.Lerp(1, neighborScale, Mathf.Clamp01(Mathf.Abs(distance)));
}
}
실제 Windows Build22에서 휠·클릭으로 열람만 할 때는 실제 무기와 공격력이 유지됐습니다. 장착 버튼을 누르면 모델과 공격력이50에서158로 바뀌었고, 원래 무기로 다시 착용하면50으로 돌아왔습니다. 실제 Unity 레이캐스트와 EventSystem을 통한 드래그 이벤트 재생은0→1 이동을 확인했습니다. OS 마우스 자동 드래그에서는 시작·종료 로그가 없어 성공을 확인하지 못했습니다. 이 두 검증은 구분합니다. 원작 관성 곡선·열람 중 캐릭터 미리보기·전체119개 화면 전수 검토는 남았습니다.
사망 시에는 영웅과 다른 뼈 경로의 공통 클립이 연결되어 있었습니다. 기존330개 커브가 영웅 리그에서 모두 미연결인 것을 Unity API로 확인하고,8개 무기군별 사망 클립과 확인되는 전설 전용 클립으로 참조를 교체했습니다. 원본은 수정하지 않았습니다.
flowchart LR
A[HP0 Dead 진입] --> B[상태 시작 시각 기록]
B --> C[무기군별 사망 클립 선택]
C --> D[진입 후 경과 시간으로 재생]
D --> E[끝 자세 유지]
지속 시간이0인 사망 상태에서는 정규화 진행률 대신 진입 후 경과 시간을 사용합니다. 남녀·일반·전설을 합친18경우 모두 포즈 변화가 있었고13경우는 전체 커브가 연결됐습니다. 나머지5경우의 추가 머리카락·성별 뼈·미회수 해시 경로는 그대로 기록했습니다. 실제 Windows 경기에서는 남성 검·방패 캐릭터의0HP 사망 자세를 확인했습니다. 다른 무기군·성별의 실제 경기, 사망 FX·페이드·결과 화면은 남습니다.
개발 문서에는 장비·사망 처리의 책임과 흐름, 원작에서 확인한 값과 대응값, 검증 한계를 추가했습니다. 새 코드에는 한국어 XML 요약과 포인터 소유권·UI 좌표·원본 보존 이유 주석을 남겼습니다. 기존 압축 작성 코드까지 모두 정리한 상태는 아닙니다.
보고용 실제 캡처5장은 Affinity3.3.3 GUI에서1600×900 고품질 WebP로 내보냈습니다. 약135~170KB이며 원본 PNG와 별도 편집 원본5개를 보존했습니다. 저장한 문서를 실제 닫았다가 재열고 clean 상태를 확인했습니다. SDK 저장·내보내기는 PERMISSION_DENIED로 실패했으며 보안 설정을 바꾸지 않고 GUI 경로를 사용했습니다. 이 공개 글에는 익명 게시 기준에 따라 해당 실행 화면을 싣지 않습니다. 기존 썸네일은 책임 분리를 설명하는 도식이며 실제 실행 증거가 아닙니다.
새 Build22에서10시간 검증은 수행하지 않았습니다. 이전 고정 빌드의 장시간 결과와 합치지 않습니다.


댓글
이 글에 대한 생각을 남겨 주세요.