Senior UI/UX designer with 10+ years across AAA live-service titles on Unreal Engine — Blade & Soul 2, Lineage W/2M, BnS NEO, Battle Crush (PC · console · mobile). I take a feature from problem definition and UX flows, through Figma wireframes and polished visual design (Photoshop, Illustrator), all the way to front-end implementation in-engine (UMG) and HTML5/CSS. My differentiator is range: a UI/UX designer who also brings real-time VFX and technical-art depth. I design the flow, animate the motion, author the shaders & effects, and ship the screen in-engine myself — one designer, the full visual stack.
※ A designer who implements. Live UI motion on this page plays in real time via a flipbook engine I built; the playable games are real front-end builds. Technical-art / VFX depth is shown in the VFX/TA section below — proof I can build what I design.
I design the experience, draw the screens, and implement them in-engine. The motion and technical-art craft is what makes the result feel right.
Problem → user flow → wireframe → visual comp → in-engine screen. UX thinking first; the pixels follow the decisions.
From a single button press to the catharsis of a reward, I direct every motion that happens on the UI.
Grayscale, RGBMask Dissolve)My real differentiator is range — I don’t just spec the screen: I animate the motion, author the shaders & VFX, and build it in-engine. The rare designer who covers UI, motion and technical art in one pair of hands.
All AAA live-service on Unreal Engine. The core is UMG UI design & direction — I built the enhance, menu and HUD screens on Blade & Soul 2 · BnS NEO · Lineage W/2M · Battle Crush. Seven Knights 2 was a VFX (skill-direction) contribution, included to show real-time combat direction that ties directly to in-match HUD readability. Every capture below is from my own showreels; use the button on each card to watch the full video. Across these titles the UX craft is the same: a clear information hierarchy, readability under heavy combat FX, and console gamepad-focus & title-safe layouts on the titles that shipped to console.
The UX brief on these screens: make high-stakes economy actions — enhance · fusion · summon — read at a glance. Cost and outcome legible first; the result reveal then carries the emotional payoff. The motion follows that hierarchy, not decoration.



LIVE
LIVE
LIVE
LIVE
LIVE
LIVE
LIVE
LIVE
LIVE



LIVE
LIVE
LIVE
LIVE
LIVE
LIVE
LIVE
LIVE

LIVE
LIVE
LIVE
LIVE
LIVE
LIVE
LIVE
LIVE
A vampire-themed mobile tower defense. Varying a single “blood” theme across 122 VFX prefabs and 60+ shader graphs without losing readability was the challenge. Hit effects for 9 enemy types (assassin, hunter, lancer, priest, witch, etc.) were systematized by an element system, and the core reward loop (collect blood orb → upgrade altar) was directed by connecting world → UI seamlessly with UIParticle.
VFX.Hit.* 50+ variants run per enemy type while materials/textures combine from a shared pool. Status effects (burn/freeze/shock) are split into VFX.Status* families so they can stack visually.
RadialShockwave (shockwave distortion), VerticalPannerWithSideFade (blood pillar), URPStylizedLava, and UI-side RGBMask Dissolve — what shader graph can’t do is written directly in HLSL.
mob-sakai ParticleEffectForUGUI based. Shared/Prefabs/UI 366 prefabs (buttons, gauges, badges, currency motion) run under one system; I solved Canvas sorting/masking conflicts in the currency-fly motion and synced a gauge punch-scale to the collect timing.
// Use particle vertex-color alpha as “time” → drive ring expansion // from Color-over-Lifetime alone, with no material duplication float waveRadius = input.color.a; // Polar sampling: distort radius per angle to make an “organic” ring float2 polarUV = float2(dist, normalizedAngle) * _MainTex_ST.xy + _MainTex_ST.zw; float radiusDistortion = (tex.r - 0.5) * _Distortion; float distToWave = abs(dist - (waveRadius + radiusDistortion)); // ring width + front/back edge fade + circular mask float ringMask = 1.0 - smoothstep(0.0, _Width, distToWave); float waveMask = ringMask * frontSoftness * backSoftness * circleMask;
In casual puzzles, effects ARE game feel. From the short impact of a single match to the afterglow of reward motions like order-complete and season progress — all designed as feedback that tells the player “your finger was right”. Alongside the motion work, I owned the editor tooling that sped up art/design iteration.
A three-layer tempo: impact (~0.1s) → reward (0.3–0.4s) → mood loop (2s). Fast feedback short and strong, rewards with afterglow.
FlyEffectTestMenu (instant motion testing), TMPFontResamplerWindow (font resampling), StageEditor (level editing), AutoPlayEditor (autoplay verification) — tools that raise art/design iteration speed.
Season-progress HUD in the food-truck lobby, order-take/clear feedback on the order board — motion is verified in the live build, not a mockup.


A casual puzzle starring a yarn dragon. The same game was built two ways — Unity (native) and PixiJS (web) — and keeping the same visual identity across platforms was the core challenge. The Unity side got a custom shader for wool texture; the web side got 44-frame flipbook VFX.
Standard Lit makes wool look like glossy plastic. Wrapped Lambert (soft light/shadow boundary) + Fresnel Rim (fluff light on the silhouette) + a matte finish express the fiber texture. Full URP support including ShadowCaster/DepthOnly passes.
A two-layer particle (fluff puff + sparks) generated in code without prefabs. Color tint is linked to game logic (yarn color), handling 9 color variants with no extra assets.
HudController.cs — HP/yarn gauges, the puzzle grid, and win/lose modals all generated at runtime. Includes state motion like a wildcard pulse ring. A UI workflow with no prefab-merge conflicts.
// Wrapped Lambert — soften the light/shadow boundary, mimic light bleed inside fibers float wrapped = saturate((NdotL + _Wrap) / (1.0 + _Wrap)); half3 diffuse = baseRGB * mainLight.color * (wrapped * shadow + _AmbientStrength); // Fresnel rim — bright at the silhouette, falling off inward. // Tint the rim with base color too, for a “wool holding light” feel. float fresnel = pow(1.0 - saturate(dot(N, V)), _RimPower); half3 rim = fresnel * _RimColor.rgb * _RimIntensity * baseRGB; return half4(diffuse + rim, _BaseColor.a);










A vampire-survivors-like HTML5 game. On a screen flooded with hundreds of enemies, the UI responds instantly with 0.12s transitions without obscuring combat. Canvas (combat) and DOM (HUD) are separated so each uses its best tech — HP/XP bars via CSS gradients + transitions, the level-up roulette via DOM overlay, combat effects via Phaser particles.
Combat (hundreds of entities) on a Phaser canvas, HUD on DOM. The HP-bar width .12s transition, the equipped-artifact inset glow glow — whatever CSS does better, goes to CSS.
A beat of combat-pause → roulette spin → winning-slot highlight. Reworked from card-pick to roulette to raise anticipation at every level-up, with a tier color system (Common–Legendary) applied consistently across slots, chips, and icons.
Six hub screens (character/zone/research/shop/journal) under one overlay system — unifying enter/exit motion direction to give a sense of space.
























Even prototypes are managed as runnable builds, not design docs. Grid Rush is a block puzzle with 4 modes plus records and a daily meta loop — every capture below is actual gameplay, and it plays right here.
Instant feedback from piece placement → line clear → combo. The puzzle game-feel honed on K2, extended into my own title.
Classic (endless) · Stage 48 · Time Attack (60s) · Daily Challenge. A meta design where BEST records and daily missions drive return visits.
LINE (row clear) · BOMB (area blast) items — board-splitting clear motion and slot-gauge feedback design the feel of a comeback.


The games below ship as actual builds in this portfolio folder. Dungeon Survivors · Grid Rush play instantly by double-clicking index.html, and WoolSaga dynamically loads assets, so run it via START_PORTFOLIO.bat (local server) or a hosted URL.

PixiJS 8 web build. A yarn-dragon puzzle — 100-stage map, flipbook VFX, UI motion. (play via server/host — START_PORTFOLIO.bat)

A full Phaser 3 game (8 characters · 5 zones · meta progression). Verify the dungeon-hub motion, level-up spin roulette, and hybrid HUD by playing.
▶ Play
HTML5 web build. A block puzzle with 4 modes · NEXT queue · LINE/BOMB items · daily meta loop — plays right here.
▶ PlayThis is the other half of how I work — the VFX & technical-art depth under the UI/UX above. Designing the screen and building the effects, shaders and tooling behind it, in one pair of hands, is exactly my differentiator.
Alongside the effect/UI work on those live titles, I built a pipeline that captures & classifies in-game effects automatically. It auto-captures 3,815 effects and auto-classifies 3,087 of them into 13 categories into a searchable/playable/exportable library (VFX Library v3) — see the real screens below. A system that answers “how did this effect look in another game?” within 3 seconds.
Resident Unity Editor recorder. _VfxBatchTrigger.json detected → spawn, play & frame-capture VFX prefabs. Resolution/FPS/length configurable.
TypeScript CLI. Unity YAML/.meta parsing → GUID map → texture tracing. UE5 projects supported too.
Auto-trim transparent padding → auto-compute N×N grid → export sheet (original + 50%). Sharp-based image processing.
3,815 captured → 3,087 classified. Search/play/export web viewer, self-improved over 3 iterations.
Hunting for effect references ate 30% of work time. Effects scattered across games are captured once and reused forever — building a moodboard for a new project dropped from days to minutes.
v1 (5.3GB static HTML) was heavy; v2 (metadata + server) gained manageability but was slow. v3 split thumbnails and lazy-loaded to shrink the core to 184MB. I iterate on tools like products too.
The flipbook player, sequence playback, and viewport-based playback control on this very page are all a custom engine written with the same pipeline philosophy.


// Artists only write the prefab path into JSON. // The resident editor recorder detects it and captures automatically. { "prefabs": ["Assets/.../VFX.BloodSurge.prefab"], "width": 512, "height": 512, "fps": 30, "duration": 5.0, "background": "transparent" }
for (int f = 0; f < frameCount; f++) { yield return new WaitForEndOfFrame(); RenderTexture.active = rt; GL.Clear(true, true, new Color(0,0,0,0)); // preserve alpha cam.Render(); readTex.ReadPixels(new Rect(0, 0, w, h), 0, 0); File.WriteAllBytes( Path.Combine(dir, $"frame_{f:D4}.png"), readTex.EncodeToPNG()); }