Unity에서 AI 기반 2D 애니메이션 자동 보간 프레임워크 구현하기
Unity 2D 게임에서 낮은 시뮬레이션 프레임을 AI 프레임 보간으로 보완하는 방법을 다룬다. Optical Flow, 가림 마스크, RenderTexture 이중 버퍼와 C# 렌더링 루프를 이용해 부드러운 애니메이션을 구현한다.

2D 애니메이션 자동 보간은 직전 프레임과 현재 프레임 사이의 움직임을 추정해 중간 이미지를 합성하는 렌더링 기법이다. Unity에서는 게임 로직의 고정 업데이트 주기를 유지한 채 두 장의 RenderTexture를 AI 추론 또는 셰이더에 전달하면 된다. 핵심은 단순 알파 블렌딩이 아니라 Optical Flow와 가림(occlusion) 정보를 사용해 픽셀을 이동시키고 실패 시 원본 프레임으로 안전하게 되돌리는 것이다.
AI 기반 2D 프레임 보간은 왜 필요한가?
2D 캐릭터, 컷신, UI 연출은 보통 12~30fps 소스 애니메이션으로도 제작할 수 있다. 하지만 고주사율 디스플레이에서는 프레임 간 위치 변화가 크게 보이며 특히 카메라 팬이나 빠른 검 휘두르기에서 끊김이 눈에 띈다.
전통적인 해결책은 원본 스프라이트 프레임을 늘리는 것이다. 다만 아트 제작량과 메모리 사용량이 함께 증가한다. AI 기반 프레임 보간은 기존 프레임 두 장으로 중간 프레임을 생성하므로 원본 에셋을 다시 제작하지 않고도 표시 프레임의 시간 해상도를 높일 수 있다.
| 방식 | 원리 | 장점 | 주의점 |
|---|---|---|---|
| 선형 블렌딩 | 두 프레임의 색을 섞음 | 매우 저렴함 | 이동 물체에 고스트가 생김 |
| Transform 보간 | 위치·회전·스케일을 보간 | SpriteRenderer에 간단함 | 변형 애니메이션과 가림을 처리하지 못함 |
| Optical Flow 보간 | 픽셀 이동 벡터로 이미지를 워핑 | 복잡한 2D 움직임에 강함 | 가림과 모델 추론 비용을 관리해야 함 |
| AI 프레임 보간 | Flow와 가림 마스크를 신경망이 예측 | 중간 프레임 품질이 높음 | 장면 종류별 품질 검증이 필요함 |

자동 보간 렌더링은 어떻게 동작하는가?
프레임 시간 와 의 이미지를 각각 , 이라고 하자. 표시하려는 시점의 정규화된 위치를 로 두면 이다. Optical Flow 모델은 각 픽셀이 어느 방향으로 이동했는지 나타내는 벡터장 을 예측한다.
중간 프레임은 두 입력 이미지를 반대 방향으로 워핑한 뒤 가림 마스크 으로 합성한다.
여기서 는 UV 좌표를 이동해 텍스처를 샘플링하는 함수다. 가림 마스크가 없다면 캐릭터 뒤로 지나간 배경이나 새로 드러난 영역에서 잔상이 생기기 쉽다.
flowchart LR
A[2D 카메라 렌더] --> B[이전 RenderTexture]
B --> C[현재 RenderTexture]
C --> D[Optical Flow·가림 마스크 추론]
D --> E[워핑 및 합성 셰이더]
E --> F[화면 출력]
E --> G{품질 검사 실패?}
G -- 예 --> H[현재 원본 프레임 출력]
G -- 아니오 --> F
이 구조에서 게임플레이는 원래의 Update 및 FixedUpdate 주기로 실행된다. 보간기는 표시 직전 단계에서만 동작하므로 충돌 판정, 입력 처리, 네트워크 동기화에 가짜 중간 상태를 사용하지 않는다.
Unity 2D 자동 보간 프레임워크를 어떻게 구현할까?
1. 보간 전용 카메라와 RenderTexture를 분리한다
월드 전체를 무조건 보간하면 HUD 텍스트와 픽셀 아트까지 흐려질 수 있다. 보간 대상인 배경·캐릭터 레이어만 별도 카메라로 렌더링하고 UI는 최종 합성 뒤 일반 Canvas로 출력하는 편이 안전하다.
InterpolatedWorld레이어: 배경, 캐릭터, 이펙트UI레이어: 체력 바, 글자, 조작 버튼- 보간 카메라:
InterpolatedWorld만 Culling Mask에 포함 - UI 카메라 또는 Screen Space Canvas: 보간 결과 위에 표시
RenderTexture는 화면과 같은 해상도로 시작하되 모바일에서는 절반 또는 4분의 1 해상도 추론을 먼저 검토한다. 업스케일된 Flow가 완벽하지 않아도 작은 해상도의 2D 연출에서는 비용 대비 효과가 좋을 수 있다.
2. 프레임 쌍과 보간 비율을 C#에서 관리한다
아래 코드는 프레임 쌍을 교체하고 렌더링 시점의 보간 비율만 머티리얼에 전달하는 최소 구성이다. sourceCamera는 보간 대상 레이어만 렌더링해야 한다.
using UnityEngine;
public sealed class FrameInterpolationRenderer : MonoBehaviour
{
[SerializeField] Camera sourceCamera;
[SerializeField] RenderTexture previousFrame;
[SerializeField] RenderTexture currentFrame;
[SerializeField] Material interpolationMaterial;
[SerializeField, Range(1, 60)] int sourceFps = 20;
float nextCaptureTime;
void OnEnable()
{
nextCaptureTime = Time.unscaledTime;
}
void Update()
{
if (Time.unscaledTime < nextCaptureTime) return;
Graphics.Blit(currentFrame, previousFrame);
sourceCamera.targetTexture = currentFrame;
sourceCamera.Render();
sourceCamera.targetTexture = null;
nextCaptureTime += 1f / sourceFps;
}
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
float frameDuration = 1f / sourceFps;
float tau = Mathf.Clamp01((Time.unscaledTime - (nextCaptureTime - frameDuration)) / frameDuration);
interpolationMaterial.SetTexture("_PreviousFrame", previousFrame);
interpolationMaterial.SetTexture("_CurrentFrame", currentFrame);
interpolationMaterial.SetFloat("_Interpolation", tau);
Graphics.Blit(source, destination, interpolationMaterial);
}
}
이 코드는 Built-in Render Pipeline의 OnRenderImage 예시다. Unity 6에서 OnRenderImage는 Scriptable Render Pipeline에서 지원되지 않는다. URP에서는 ScriptableRenderPass, HDRP에서는 Fullscreen Custom Pass로 합성 단계를 구현해야 한다. 렌더 파이프라인별 진입점과 타깃 처리 방식은 다를 수 있다. Unity 6 OnRenderImage 문서
3. AI 추론 결과를 셰이더 입력으로 연결한다
AI 모델은 ONNX 형식으로 준비하고 Unity Sentis 같은 ONNX 실행 경로에서 입력 프레임 두 장을 처리할 수 있다. 모델 출력은 최소한 다음 중 하나여야 한다.
| 모델 출력 | 용도 | 없을 때의 대안 |
|---|---|---|
| Forward Flow | 이전 프레임을 중간 시점으로 워핑 | 단순 UV 이동 |
| Backward Flow | 현재 프레임을 역방향 워핑 | 현재 프레임 블렌딩 |
| Occlusion Mask | 가려진 픽셀의 기여도 조절 | 차이값 기반 신뢰도 감소 |
| Confidence Map | 불안정한 결과를 원본으로 폴백 | 전역 임계값 폴백 |
셰이더에서 핵심은 두 텍스처를 같은 좌표에서 섞는 것이 아니라 Flow를 이용해 서로 다른 UV에서 샘플링하는 점이다.
float4 BlendInterpolated(float2 uv)
{
float2 flowForward = SAMPLE_TEXTURE2D(_FlowForward, sampler_FlowForward, uv).rg * 2.0 - 1.0;
float2 flowBackward = SAMPLE_TEXTURE2D(_FlowBackward, sampler_FlowBackward, uv).rg * 2.0 - 1.0;
float4 fromPrevious = SAMPLE_TEXTURE2D(_PreviousFrame, sampler_PreviousFrame, uv - flowForward * _Interpolation);
float4 fromCurrent = SAMPLE_TEXTURE2D(_CurrentFrame, sampler_CurrentFrame, uv + flowBackward * (1.0 - _Interpolation));
float mask = SAMPLE_TEXTURE2D(_OcclusionMask, sampler_OcclusionMask, uv).r;
return lerp(fromCurrent, fromPrevious, mask);
}

고스트와 왜곡은 왜 발생하는가?
고스트는 대개 색상 보간을 움직임 추정으로 착각해서 발생한다. 서로 다른 위치의 캐릭터 픽셀을 섞으면 반투명한 이중 윤곽이 만들어진다. Flow를 사용해도 다음 상황에서는 잘못된 결과가 나올 수 있다.
- 순간이동, 스프라이트 교체, 카메라 컷처럼 연속된 움직임이 없는 경우
- 투명 파티클, 발광 효과, 모션 블러처럼 픽셀 대응 관계가 약한 경우
- 캐릭터가 배경 뒤로 들어가거나 새 배경이 드러나는 가림 변화
- 픽셀 아트의 최근접 샘플링과 서브픽셀 워핑이 충돌하는 경우
따라서 프레임 차이와 모델 신뢰도를 함께 확인해 폴백해야 한다. 예를 들어 화면 평균 차이가 임계값보다 큰 장면 전환에서는 보간을 건너뛰고 현재 원본 프레임을 출력한다. 이는 품질이 낮은 합성 프레임을 표시하는 것보다 낫다.
bool ShouldBypassInterpolation(float meanDifference, float confidence)
{
return meanDifference > 0.35f || confidence < 0.60f;
}
성능을 어떻게 예산 안에 맞출까?
AI 프레임 보간은 렌더링 단계에 추가되는 작업이다. 먼저 GPU 프로파일러에서 카메라 렌더, 텍스처 복사, AI 추론, 합성 패스 시간을 따로 측정해야 한다. 목표가 60fps라면 전체 프레임 예산은 약 16.67ms이며 보간기가 그 예산을 잠식하지 않도록 제어해야 한다.
- 대상을 제한한다. 전체 화면보다 캐릭터·배경 레이어만 보간하고 UI와 텍스트는 제외한다.
- 추론 해상도를 낮춘다. Flow를 0.5배 해상도로 만들고 합성 단계에서 업샘플링한다.
- 매 프레임 추론하지 않는다. 원본 캡처가 갱신될 때만 모델을 실행하고 그 사이 표시 프레임은 같은 Flow를 재사용한다.
- 비동기 GPU 경로를 우선한다. CPU Readback은 프레임 동기화 비용을 만들 수 있으므로 피한다.
- 폴백을 기본 기능으로 둔다. 저사양 기기, 배터리 절약 모드, 빠른 화면 전환에서는 일반 렌더링으로 즉시 전환한다.
| 기기 등급 | 권장 전략 | 보간 해상도 |
|---|---|---|
| 고사양 PC·콘솔 | 양방향 Flow와 가림 마스크 | 원본 또는 0.75배 |
| 중급 모바일 | 단방향 Flow와 신뢰도 폴백 | 0.5배 |
| 저사양 모바일 | Transform 보간 또는 비활성화 | AI 추론 없음 |
자주 묻는 질문 (FAQ)
AI 프레임 보간으로 게임 로직 FPS도 높아지는가?
아니다. 화면에 보이는 중간 프레임만 생성한다. 물리, 입력, 네트워크 판정은 기존 시뮬레이션 주기로 유지해야 한다.
모든 2D 게임에 Optical Flow가 적합한가?
아니다. 픽셀 아트처럼 프레임 단위의 선명한 변화가 중요한 경우에는 픽셀 단위 왜곡이 더 거슬릴 수 있다. 해당 장르는 Transform 보간이나 원본 프레임 표시가 더 적합할 수 있다.
단순 알파 블렌딩만으로 시작해도 되는가?
카메라가 거의 움직이지 않고 객체 이동이 작다면 가능하다. 빠르게 이동하는 캐릭터가 있다면 고스트를 줄이기 위해 최소한 Flow 기반 워핑 또는 장면 전환 폴백을 추가하는 편이 좋다.
정리
AI 기반 2D 자동 보간의 실용적인 최소 구조는 이전/현재 RenderTexture, Flow·가림 마스크 추론, 워핑 합성 셰이더, 품질 폴백 네 가지다. 먼저 특정 연출 레이어에만 적용하고 프로파일러로 비용과 고스트를 측정하자. 품질이 불안정한 장면에서 원본을 표시하는 정책까지 갖추면 애니메이션의 부드러움과 게임플레이의 안정성을 함께 지킬 수 있다.



