Shader Graph와 AI 노이즈 생성기로 만드는 Unity 필살기 연출 모듈
Unity Shader Graph와 AI 기반 노이즈 텍스처를 결합해 필살기의 충전·폭발·잔광을 재사용 가능한 모듈로 구현한다. 파라미터 설계, 마스크 수식, 성능 예산과 디버깅 기준까지 단계별로 정리한다.

핵심 요약
필살기 연출 모듈은 AI로 생성한 노이즈 맵을 그대로 효과의 핵심으로 쓰기보다 Shader Graph의 마스크·왜곡·발광 제어에 입력으로 사용하는 구조가 안정적이다. Unity URP 14 기준으로 Progress, NoiseScale, DistortionStrength, EmissionIntensity를 한 재질의 인스펙터 파라미터로 노출하면 충전부터 폭발, 잔광까지 같은 셰이더를 재사용할 수 있다.
필살기 VFX 모듈은 무엇을 해결해야 하는가?
필살기 연출은 한 번의 강한 화면 변화가 목적이지만 실제 제작에서는 캐릭터별 색상·범위·타이밍을 바꾸며 반복 사용해야 한다. 개별 이펙트를 매번 새 셰이더로 만들면 조정 비용과 머티리얼 수가 빠르게 늘어난다.
이 글의 목표는 다음 세 레이어를 느슨하게 결합하는 것이다.
| 레이어 | 역할 | 교체 빈도 |
|---|---|---|
| AI 노이즈 텍스처 | 불규칙한 경계와 내부 밀도 제공 | 낮음 |
| Shader Graph | 소멸, 왜곡, 발광, 림 마스크 계산 | 낮음 |
| VFX 제어 스크립트/타임라인 | 시간에 따른 파라미터 애니메이션 | 높음 |

AI 기반 노이즈 생성기는 어떻게 활용할까?
AI 이미지 생성기는 균일한 Perlin Noise보다 화염, 먹 번짐, 균열처럼 방향성과 덩어리감이 있는 노이즈 초안을 빠르게 만드는 데 유용하다. 다만 생성 결과를 런타임에 직접 호출하거나 원본 이미지를 그대로 사용하면 재현성과 메모리 관리가 어려워진다.
생성 프롬프트와 텍스처 정리 기준
생성 단계에서는 다음 제약을 명확히 둔다.
- 정사각형, 타일 가능, 중앙 피사체 없음
- 흑백 또는 낮은 채도의 단일 채널 질감
- 가장자리에 큰 명암 경계가 있고 미세 디테일은 과하지 않음
- 텍스트·문양·조명 방향처럼 반복 시 드러나는 요소 제외
가져온 텍스처는 Unity Import Settings에서 Wrap Mode: Repeat, Generate Mip Maps: On으로 설정한다. 마스크 전용이라면 sRGB (Color Texture)를 끄고 가능하면 R8 또는 플랫폼에 맞는 단일 채널 압축 포맷을 사용한다. 색 정보가 아니라 임계값 비교용 데이터이기 때문이다.
생성 노이즈를 마스크로 변환하는 수식
N을 0~1 범위의 노이즈 값, P를 0~1 범위의 진행도, W를 경계 폭이라고 하자. Shader Graph에서는 Sample Texture 2D 결과와 Smoothstep 노드로 다음 마스크를 만든다.
M은 내부를 남기거나 지우는 기본 마스크가 된다. W를 크게 하면 소멸 경계가 부드러워지고 작게 하면 찢기는 듯한 선명한 경계가 생긴다. 같은 노이즈를 UV 왜곡에도 쓰되 마스크 계산용 좌표와 왜곡용 좌표의 스케일을 다르게 두면 반복감이 줄어든다.
Shader Graph로 필살기 충전·폭발·잔광을 어떻게 구현할까?
URP Unlit Shader Graph 하나로 시작하는 편이 가장 단순하다. 조명 반응이 필요한 3D 충격파 메시만 Lit Graph로 분리하고 화면을 덮는 판형 이펙트와 스프라이트는 Unlit으로 유지한다.
Step 1. 재사용할 Blackboard 파라미터를 고정한다
처음부터 효과별 속성을 늘리지 말고 아래 공통 파라미터만 만든다.
| 프로퍼티 | 타입 | 권장 범위 | 용도 |
|---|---|---|---|
BaseMap | Texture2D | - | 기본 형상 또는 마스크 |
NoiseMap | Texture2D | - | AI 생성 노이즈 |
Progress | Float | 0~1 | 효과 진행도 |
NoiseScale | Float | 0.5~8 | 노이즈 반복 밀도 |
EdgeWidth | Float | 0.01~0.2 | 소멸·발광 경계 폭 |
DistortionStrength | Float | 0~0.1 | UV 왜곡 강도 |
EmissionColor | Color HDR | - | 필살기 색상 |
EmissionIntensity | Float | 0~20 | HDR 발광 세기 |
Progress는 항상 0~1로 정규화한다. 타임라인 길이와 셰이더 수식을 분리할 수 있어 0.4초짜리 짧은 폭발과 2초짜리 충전이 같은 Graph를 공유한다.
Step 2. 노이즈 마스크와 발광 테두리를 만든다
Graph에서 Tiling And Offset의 Tiling에 NoiseScale을 넣고 NoiseMap을 샘플링한다. 앞선 수식의 M을 Alpha에 연결하고 테두리는 안쪽과 바깥쪽 마스크의 차이로 계산한다.
여기서 M_outer는 EdgeWidth를 조금 크게, M_inner는 작게 계산한 마스크다. 최종 Emission에는 아래처럼 연결한다.
Emission = EmissionColor * E * EmissionIntensity
Alpha = M * BaseMapAlpha
이 방식은 별도 외곽선 텍스처 없이도 진행도에 따라 불꽃 테두리가 이동하는 느낌을 만든다.
Step 3. 왜곡은 화면 전체가 아닌 국소 영역에만 적용한다
왜곡 노이즈를 그대로 UV에 더하면 이펙트 바깥까지 흔들리거나 투명 경계에서 잡음이 눈에 띈다. M 또는 E를 왜곡 강도의 곱으로 사용한다.
N_rg는 노이즈 텍스처의 R, G 채널이다. 단일 채널 노이즈만 있다면 같은 텍스처를 서로 다른 Offset으로 두 번 샘플링해 2축 벡터를 만들 수 있다. 고비용 화면 왜곡은 꼭 필요한 순간에만 켜고 가능하면 별도 쿼드 또는 충격파 메시의 UV 왜곡으로 제한한다.
flowchart LR
A[AI 노이즈 텍스처] --> B[NoiseMap 샘플링]
C[Progress와 EdgeWidth] --> D[Smoothstep 마스크]
B --> D
D --> E[Alpha 소멸]
D --> F[발광 경계]
B --> G[UV 왜곡]
D --> G
F --> H[HDR Emission]
G --> H
필살기 타이밍은 어떤 순서로 제어해야 할까?
한 재질을 공유하되 개별 렌더러에는 MaterialPropertyBlock을 사용한다. renderer.material을 매번 호출하면 재질 인스턴스가 복제되어 배칭과 메모리 관리가 나빠질 수 있다.
- 충전:
EmissionIntensity를 올리고NoiseScale을 낮게 유지한다. 커다란 덩어리와 강한 발광이 읽히게 한다. - 발동:
Progress를 빠르게 변화시키고DistortionStrength를 짧은 구간만 올린다. 테두리E가 화면에서 가장 밝아지는 시점이다. - 잔광:
EmissionIntensity와 Alpha를 낮추며NoiseScale또는 UV Offset을 천천히 변화시킨다. 입자와 사운드는 이 구간에서 감쇠시킨다.
Unity C#에서는 최소한의 제어 코드만으로 충분하다.
using UnityEngine;
public sealed class FinisherVfxDriver : MonoBehaviour
{
[SerializeField] Renderer targetRenderer;
[SerializeField] float duration = 0.6f;
static readonly int Progress = Shader.PropertyToID("_Progress");
static readonly int EmissionIntensity = Shader.PropertyToID("_EmissionIntensity");
readonly MaterialPropertyBlock block = new();
void OnEnable() => Play();
public void Play()
{
StopAllCoroutines();
StartCoroutine(Animate());
}
System.Collections.IEnumerator Animate()
{
for (float time = 0; time < duration; time += Time.deltaTime)
{
var t = time / duration;
targetRenderer.GetPropertyBlock(block);
block.SetFloat(Progress, t);
block.SetFloat(EmissionIntensity, Mathf.Lerp(12f, 0f, t));
targetRenderer.SetPropertyBlock(block);
yield return null;
}
}
}

Shader Graph 필살기 이펙트의 성능은 어떻게 관리할까?
화려함보다 먼저 확인할 것은 화면 점유율과 오버드로우다. 투명 파티클과 큰 쿼드는 같은 픽셀을 여러 번 그리므로 노이즈 텍스처 해상도보다 블렌딩 횟수가 병목이 되는 경우가 많다.
| 점검 항목 | 기준 | 간단한 대응 |
|---|---|---|
| 투명 오버드로우 | 화면을 크게 덮는 레이어가 다수 | 지속 시간을 줄이고 큰 쿼드 수 축소 |
| 텍스처 샘플 수 | 픽셀당 3~4회 초과 여부 | 마스크와 왜곡 노이즈 재사용 |
| HDR Bloom | 밝은 영역이 과도하게 번짐 | EmissionIntensity 상한과 Bloom threshold 조정 |
| 머티리얼 수 | 캐릭터마다 중복 생성 | 공용 머티리얼 + MaterialPropertyBlock |
| 모바일 GPU | 화면 왜곡과 반투명 레이어 | 왜곡 비활성 변형을 별도 제공 |
Frame Debugger에서 드로우 호출 순서와 투명 레이어를 확인하고 RenderDoc 또는 Unity Profiler에서 GPU 시간이 상승하는 구간을 측정한다. 특정 기기에서만 문제가 난다면 노이즈 수식보다 해상도, Bloom, 파티클 오버드로우를 먼저 줄이는 편이 효과가 크다.
자주 묻는 질문 (FAQ)
AI 생성 노이즈를 매번 새로 만들어야 하나요?
아니다. 성격이 다른 노이즈 3~5종을 라이브러리로 관리하고 NoiseScale, Offset, 임계값을 바꾸는 편이 재현성과 아트 디렉션에 유리하다.
Shader Graph만으로 화면 굴절을 만들 수 있나요?
가능하지만 URP의 화면 색상 텍스처와 렌더링 설정이 필요하다. 먼저 메시 UV 왜곡으로 목표 인상을 만들고 화면 굴절은 필살기 발동의 짧은 순간에만 추가하는 것이 안전하다.
노이즈 경계가 계단처럼 보이는 이유는 무엇인가요?
EdgeWidth가 너무 작거나 노이즈 텍스처 해상도와 Mip Map 설정이 맞지 않는 경우가 많다. Smoothstep 폭을 늘리고 텍스처 압축·필터링을 확인한 뒤 화면에서 실제 크기로 검증한다.
정리
AI 노이즈는 빠르게 질감의 방향성을 얻는 입력 자산이고 최종 품질은 Shader Graph의 마스크 설계와 시간 제어에서 결정된다. Progress 기반의 공용 Graph, 노이즈 경계 발광, MaterialPropertyBlock 제어라는 세 가지만 고정하면 필살기마다 새 셰이더를 만들지 않고도 충분히 다른 인상을 만들 수 있다.



