~/prj/maple/7_unity_vfx/크롤해 둔 메이플 원본 이펙트(스킬·Effect 4.5만 프레임)를 기준(레퍼런스)으로 놓고, 서버의 Unity로 같은 느낌의 이펙트를 3가지 방식으로 만든 뒤, 원본과 나란히 놓은 비교 갤러리를 웹으로 낸다. 전부 헤드리스(모니터 없이) 자동 렌더·녹화라 "에이전트가 VFX를 만들고 검수한다"는 서사로 QA 에이전트 포트폴리오에 붙는다.
~/Unity/Hub/Editor/), batchmode 빌드 절차 검증됨. 에디터 GUI가 VNC :1(1312×790)에서 구동 중(pid 2735854) — batchmode와 동시 실행 금지
기존 프로젝트qa_agent/UnityProject — 빌트인 렌더 파이프라인, 패키지는 ugui + MCP for Unity뿐. URP·Shader Graph·VFX Graph 없음
기존 VFX 코드Assets/MapleDemo/MapleFx.cs(158줄) — 초승달 슬래시를 Texture2D로 절차 생성, 피해 숫자. 헤네시스 데모에 이미 쓰임
원본 이펙트~/data_ssd/public/datasets/maplestory_io/KMS_389/wz/ — Skill 300 img · effect PNG 45,665장, Effect/*.img(BasicEff·MobEff·particle…), Map. 몹 프레임 42만 장
GPURTX PRO 6000 96GB (Unity 렌더 + 검수 VLM 동시 가능)
MCPUnity MCP(execute_code)로 에디터를 코드로 조작 가능 — 8월 QA PoC에서 씬 조립·빌드 314회 실사용
crawl_wz.py:17가 origin·delay를 제외하고 캔버스 PNG만 저장했다. 프레임 크기가 제각각(예: 스킬 0000100은 16×51 → 390×341)이라 origin(기준점) 없이는 프레임이 화면에서 튄다. 선정한 스킬 20~30개만 WARP 프록시로 origin/delay를 다시 받으면 된다(수천 요청, 수십 분).prepare_*.sh로 데이터셋에서 복사), 비교 페이지는 dev(LAN 전용)에만 둔다.| 트랙 | 방법 | 얻는 것 | 난이도 |
|---|---|---|---|
| A스프라이트 재생 | 원본 프레임 시퀀스 + origin/delay → Unity SpriteRenderer 애니메이터. MapleFx.cs 방식 확장 | 정답지. 원본과 100% 일치하는 기준 영상. 이후 B·C의 채점 기준 | 낮음 |
| B파티클(Shuriken) | Unity 내장 Particle System을 C# 코드로만 구성(에디터 GUI 없이). 히트 스파크·레벨업 기둥·버프 오라·회복 링·투사체 궤적 | "진짜 VFX 제작". 빌트인 파이프라인에서 바로 됨. 파라미터(수명·색·크기 커브)를 JSON으로 빼서 에이전트가 튜닝 가능 | 중 |
| C셰이더 | 디졸브(사라짐)·왜곡(히트 시 화면 일그러짐)·글로우. 빌트인용 HLSL 직접 작성(Shader Graph는 URP 필요 → 후순위) | 원본에 없는 "현대적" 연출. 원본 스프라이트에 셰이더를 얹는 하이브리드가 가장 보기 좋음 | 중~높음 |
추천 순서: A → B → C. A가 없으면 B·C를 "닮았는지" 잴 기준이 없다. C는 셰이더 파일 몇 개면 되므로 별도 URP 프로젝트를 새로 파지 않는다(에디터 GUI가 이미 떠 있는 기존 프로젝트를 건드리는 것도 피하려고 7_unity_vfx/UnityProject를 새로 만들되 빌트인 파이프라인 유지).
| # | 이펙트 | 원본 소스(레퍼런스) | B 파티클 설계 | C 셰이더 |
|---|---|---|---|---|
| 1 | 타격 히트 | Skill/*/hit/, Effect/BasicEff.img 중 히트류 | 버스트 12~20개 스파크, 방사형 속도, 0.2s 수명, 흰→청 색 커브 | 히트 순간 왜곡(GrabPass) |
| 2 | 레벨업 | BasicEff.img/LevelUp_Fast | 바닥 링 + 위로 솟는 기둥 두 계층, 금색 | 글로우(가산 블렌드) |
| 3 | 버프 오라 | BasicEff.img/ZeroAura0, 스킬 effect | 캐릭터 주위 루프 파티클(궤도 속도), 무한 지속 | — |
| 4 | 회복(HP 포션) | BasicEff.img 회복류 | 위로 떠오르는 십자·반짝이, 초록 | — |
| 5 | 투사체(마법 구슬) | 초급 마법사 스킬(Skill/2001.img 계열) ball/ | 트레일 렌더러 + 머리 파티클, 명중 시 1번 히트 재사용 | 디졸브로 소멸 |
몹 사망 디졸브(트랙 C를 몹 프레임 42만 장에 적용)는 6번 보너스.
KMS_389/wz (원본 PNG) ─┐
origin/delay 재크롤 ────┼─▶ prepare_fx.py ─▶ UnityProject/Assets/Fx/{Resources, sheets.json} (git 제외)
│
효과 파라미터 fx/*.json ┘ │
▼
Unity batchmode -executeMethod FxBuilder.BuildAll ─▶ Build/fxlab.x86_64
│
DISPLAY=:1 ./fxlab.x86_64 --fx levelup --mode A|B|C --out /abs/path ─▶ 60fps 프레임 PNG (ScreenCapture)
│
ffmpeg ─▶ mp4/gif + 몽타주 ─▶ compare.py (원본 vs A/B/C 나란히, SSIM·픽셀 차) ─▶ web/gallery/
│
(선택) VLM 판정: "원본과 같은 종류의 이펙트인가? 색·타이밍 어긋남은?" ─▶ QA 리포트 JSON
ScreenCapture.CaptureScreenshot 또는 RenderTexture로 프레임을 직접 저장한다. x11grab 녹화보다 타이밍이 정확하고 VNC 없이도 된다(-batchmode 플레이어 + 오프스크린 렌더 시도, 안 되면 기존 방식 DISPLAY=:1).| 단계 | 할 일 | 완료 기준(검증) | 기간 |
|---|---|---|---|
| 0 준비 | 새 Unity 프로젝트 생성(빌트인), 선정 스킬 30개 origin/delay 재크롤, prepare_fx.py | batchmode 빈 씬 빌드 성공 로그, sheets.json에 30개 시퀀스 | 0.5일 |
| 1 트랙 A | 스프라이트 시퀀스 플레이어 + 녹화기 + ffmpeg 몽타주 | 원본 5종을 Unity에서 재생한 mp4가 웹에 뜸. 원본 gif와 프레임 단위 픽셀 일치 | 1일 |
| 2 트랙 B | 파티클 5종 코드 구성 + JSON 파라미터화 | 5종 mp4 + 원본 나란히 갤러리. 각 이펙트 30~60프레임 몽타주 | 1.5일 |
| 3 트랙 C | 빌트인 HLSL 셰이더 3종(글로우·디졸브·왜곡), 원본 스프라이트에 적용 | 셰이더 적용 전/후 나란히. 몹 사망 디졸브 보너스 | 1일 |
| 4 비교·검수 | compare.py(SSIM·색 히스토그램·타이밍) + VLM 판정 리포트 | 5종 × 3트랙 채점표, "어디가 어긋났나" 텍스트 | 0.5일 |
| 5 에이전트 루프 | 파라미터 튜닝 자동화: 판정 → JSON 수정 → 재렌더 2~3회 | 튜닝 전/후 점수 변화 그래프. 허브 카드·README·메모리 갱신 | 1일 |
7_unity_vfx/
├── README.md
├── web/ 이 플랜 + 갤러리(gallery/)
├── tools/
│ ├── recrawl_meta.py 선정 스킬의 origin/delay 재수집 (WARP 경유)
│ ├── prepare_fx.py 데이터셋 → Assets/Fx 복사 + sheets.json
│ ├── record.sh 빌드·구동·프레임 저장·ffmpeg
│ └── compare.py 원본 vs A/B/C 정량 비교 + 몽타주
├── fx/ 이펙트 파라미터 JSON (hit.json, levelup.json …)
└── UnityProject/ 새 프로젝트(빌트인). Assets/Fx/{SpriteSeq.cs, FxParticles.cs, Shaders/, FxBuilder.cs(Editor)}
Assets/Fx/Resources/ 는 .gitignore