부드러움을 메모리로 살 것인가 연산으로 살 것인가
Esc

    부드러움을 메모리로 살 것인가 연산으로 살 것인가

    –Unity최적화렌더링

    이 글은 최적화라기보다 만들기 전에 정하는 것 에 가깝습니다. 애니메이션 방식은 나중에 바꾸려면 에셋을 다시 만들어야 해서, 뒤늦게 고치기가 제일 어렵습니다.

    세 가지 방식

    방식 원리 장점 단점
    스프라이트 애니메이션 프레임마다 다른 스프라이트로 교체 CPU 연산이 거의 없고 구현이 단순 메모리 폭증. 부드러울수록 장수가 늘어납니다
    스켈레탈 애니메이션 본 + 메시 변형 + 키프레임 보간 적은 텍스처로 부드럽게, 런타임 블렌딩 가능 실시간 연산 비용 (본 변환과 스키닝)
    버텍스 셰이더 정점을 셰이더에서 흔듦 GPU 처리라 CPU 비용이 0에 수렴 로직으로 제어 불가, 단순 반복 모션만

    세 줄로 요약하면 이렇습니다. 스프라이트는 메모리로 사고, 스켈레탈은 연산으로 사고, 버텍스 셰이더는 자유도를 팝니다.

    스프라이트 애니메이션의 진짜 비용

    가장 흔하고 가장 과소평가되는 쪽입니다.

    걷기 8프레임이면 괜찮습니다. 그런데 부드럽게 하려고 16프레임으로 늘리면 두 배입니다. 그리고 걷기만 있는 게 아닙니다. 대기, 걷기, 달리기, 공격 3단, 피격, 사망까지 넣으면 캐릭터 한 명이 수십 장입니다.

    여기서 앞의 아틀라스 이야기가 그대로 돌아옵니다. 장수가 늘면 아틀라스가 페이지로 쪼개지고, 쪼개지면 배치도 나뉩니다. 메모리 문제가 배칭 문제로 번지는 자리입니다.

    애니메이션 프레임을 두 배로 늘리는 결정은 아틀라스 크기를 두 배로 늘리는 결정입니다. 아티스트와 이야기할 때 이 문장을 같이 두는 편이 낫습니다.

    스켈레탈은 Burst 만 깔아도 다르다

    2D Animation 패키지의 스키닝 연산은 Burst 와 Collections 패키지가 있으면 그쪽 경로로 돕니다. 코드를 한 줄도 안 고치고 패키지만 설치하면 됩니다.

    이걸 모르고 “스켈레탈은 무겁다” 고 판단하는 경우가 있습니다. 패키지 없이 잰 숫자였다면 다시 재 봐야 합니다.

    그다음은 리깅 단계에서 정합니다.

    • 본 수를 줄입니다. 손가락 하나하나에 본을 넣을 이유는 거의 없습니다
    • 정점 수를 줄입니다. 스키닝 비용은 정점 수에 비례합니다
    • 한 정점에 영향을 주는 본 개수를 제한합니다

    여기는 프로그래머가 코드로 못 고칩니다. 에셋을 만들 때 정해집니다.

    답은 하이브리드다

    셋 중 하나를 고르는 문제가 아닙니다. 캐릭터마다 다르게 고르는 문제 입니다.

    대상 방식 왜
    플레이어, 보스 스켈레탈 화면에 한둘뿐이라 연산 비용이 총량에서 작습니다. 대신 자세히 보이니 부드러워야 합니다
    잔몹, 다수 스폰 스프라이트 수십 마리가 동시에 도니 연산이 곱해집니다. 대신 작게 보여서 프레임 수를 줄여도 됩니다
    배경 식물, 깃발, 물결 버텍스 셰이더 로직이 필요 없고 개수가 많습니다. CPU 를 아예 안 씁니다

    기준이 하나입니다. 화면에 동시에 몇 개가 있는가.

    하나뿐이면 그 하나에 연산을 써도 됩니다. 쉰 마리면 연산이 쉰 배가 되니 메모리 쪽으로 밉니다. 그리고 쉰 마리는 작게 보이니까 프레임을 줄여도 티가 안 납니다. 비용 구조와 품질 요구가 같은 방향으로 갈립니다.

    배경은 버텍스 셰이더로

    이건 따로 강조할 만합니다. 흔들리는 풀, 나부끼는 깃발, 물결, 반짝이는 별. 전부 로직이 필요 없는 반복 모션이고, 개수가 많고, 배경이라 대충 흔들려도 됩니다.

    이걸 스프라이트 애니메이션으로 만들면 배경 하나에 텍스처가 수십 장 붙습니다. 셰이더에서 sin 하나로 정점을 흔들면 텍스처는 한 장이고 CPU 비용은 없습니다.

    같은 셰이더를 쓰니 배치도 안 끊깁니다. 최적화가 아니라 처음부터 이렇게 만들면 되는 것 에 가깝습니다.