UniText 는 TextMeshPro 가 못 그리는 글을 그리고, 그 대신 잃은 것이 있다
Esc

    UniText 는 TextMeshPro 가 못 그리는 글을 그리고, 그 대신 잃은 것이 있다

    –Unity라이브러리UIuGUI
    label.text = "I said مرحبا to him";   // 영어 문장 가운데에 아랍어 단어 하나

    이 한 줄을 TextMeshPro 에 넣으면 아랍어 글자가 서로 떨어진 낱자로 나오고 순서도 뒤집힙니다. UniText 에 넣으면 제대로 나옵니다.

    그렇다고 UniText 가 TextMeshPro 를 그대로 대신하는 물건은 아닙니다. UniText 는 TextMeshPro 가 구조상 못 하는 일을 풀었고, 그 대신 TextMeshPro 에서는 신경 쓰지 않아도 되던 것을 떠안았습니다. 무엇을 잃는지는 무료판과 유료판이 크게 다릅니다.

    UniText 는 판이 둘이다

    비교하기 전에 어느 UniText 인지부터 정해야 합니다. 공식 사이트는 둘을 “관련은 있지만 다른 제품” 이라고 적습니다.

    무료판 유료판 (Folio)
    버전 1.0.0 2.x, 3.x (2026년 9월 기준 3.12.1)
    라이선스 MIT 회사 매출 구간별 영구 라이선스
    들어 있는 것 셰이핑, 양방향, 줄바꿈, SDF 굽기, 이모지, 태그 무료판에 더해 입력과 선택, 월드 공간 텍스트, 드롭다운, MSDF, 가변 폰트, 효과, 폰트 압축, TextMeshPro 이전 도구
    갱신 1.0.0 에서 멈춤 거의 매주 새 버전

    이 시리즈가 소스를 읽은 것은 무료판 1.0.0 입니다. 공식 사이트의 비교표와 측정값은 유료판 3.x 기준입니다.

    얻은 것 1. 앞뒤 글자를 보고 글리프를 고른다

    TextMeshPro 도 폰트의 규칙을 조금은 씁니다. 폰트 에셋을 만들 때 뽑아 둔 표를 찾아보는 방식입니다.

    // TextMeshProUGUI.cs: 글리프 하나를 열쇠로 표를 찾는다
    if (ligature && m_currentFontAsset.fontFeatureTable.m_LigatureSubstitutionRecordLookup
            .TryGetValue(character.glyphIndex, out List<LigatureSubstitutionRecord> records))
    {
        // 합자: 이 글리프로 시작하는 묶음이 있으면 글리프 하나로 바꾼다
    }
    
    if (m_currentFontAsset.m_FontFeatureTable.m_GlyphPairAdjustmentRecordLookup
            .TryGetValue(key, out adjustmentPair))
    {
        // 커닝: 이 글리프 쌍의 간격을 조정한다
    }

    표는 넷입니다. 합자, 글리프 쌍 간격(커닝), 기준 글자에 기호 붙이기, 기호에 기호 붙이기입니다. 모두 “이 글리프(또는 이 쌍)가 나오면 이렇게 한다” 는 조회입니다.

    없는 것은 앞뒤 글자에 따라 글리프 자체를 바꾸는 일입니다. 아랍어 글자는 단어의 처음, 가운데, 끝, 단독일 때 모양이 다른데, 그것을 고르는 코드가 TextMeshPro 소스에 없습니다. 힌디어처럼 글자의 화면 순서를 바꾸는 일도 없습니다.

    UniText 는 이 일을 HarfBuzz 에 맡깁니다. HarfBuzz 는 폰트 안의 규칙 표(GSUB, GPOS) 전체를 문자 체계에 맞는 순서로 실행합니다.

    TextMeshPro UniText
    기본 코드포인트 하나에 글리프 하나 HarfBuzz 가 정함
    합자, 커닝, 기호 붙이기 에셋에 뽑아 둔 표 조회 폰트의 규칙 표 전체 실행
    아랍 문자의 이어 쓰기 플러그인이 필요 됨
    히브리 문자 플러그인이 필요 됨
    복잡한 OpenType 셰이핑 기본 수준 HarfBuzz
    유니코드 버전 14.0 17.0

    공식 사이트는 TextMeshPro 쪽 칸에 이렇게 주석을 답니다. 양방향과 복잡한 문자 체계는 바깥 구현이 있어야 하고, 오른쪽에서 왼쪽 플래그 하나로는 그 알고리즘이 생기지 않는다는 것입니다.

    얻은 것 2. 한 줄에 방향이 섞여도 된다

    TextMeshPro 의 방향은 불리언 하나입니다.

    // TMP_Text.cs
    public bool isRightToLeftText
    {
        get { return m_isRightToLeft; }
        set { if (m_isRightToLeft == value) return; m_isRightToLeft = value; ... }
    }
    protected bool m_isRightToLeft = false;

    텍스트를 보고 정하는 값이 아니라 사용자가 켜는 값이고, 컴포넌트 전체에 걸립니다. 전체가 왼쪽에서 오른쪽이거나 전체가 오른쪽에서 왼쪽입니다. 맨 위 문장처럼 둘이 섞이면 켜도 꺼도 한쪽이 틀립니다.

    UniText 는 유니코드 양방향 알고리즘(UAX #9)을 C# 으로 구현했습니다(BidiEngine.cs, 2,302줄). 글자마다 방향을 판정하고, 방향이 없는 공백과 구두점은 주변을 보고 정하고, 아랍어 문장 안의 숫자는 왼쪽에서 오른쪽으로 남깁니다.

    TextMeshPro UniText
    방향을 정하는 쪽 사용자가 켜는 불리언 텍스트를 보고 자동 판정 (강제도 가능)
    단위 컴포넌트 전체 글자마다
    섞인 방향 표현할 수 없음 가능
    유니코드 시험 파일 해당 없음 양방향 시험 91,707줄 통과

    얻은 것 1 과 2 가 UniText 를 쓰는 이유의 중심입니다. 아랍어, 히브리어, 힌디어, 섞인 방향이 필요하면 TextMeshPro 만으로는 길이 없고, 문자열을 미리 바꿔 넣어 주는 플러그인을 붙여야 합니다.

    얻은 것 3. 바뀐 층만 다시 돈다

    TextMeshPro 는 글자를 도는 루프 하나가 폰트 조회, 커닝, 줄바꿈, 정렬, 정점 생성을 한꺼번에 합니다. TextMeshProUGUI.GenerateTextMesh 한 메서드가 약 2,900줄입니다. 무엇이 바뀌든 이 메서드가 처음부터 다시 돕니다.

    UniText 는 같은 일을 단계로 나눴고, 결과를 세 층으로 따로 붙잡아 둡니다.

    바꾼 것 TextMeshPro UniText
    텍스트 전부 다시 전부 다시
    폰트 크기 전부 다시 줄나누기부터 다시. 셰이핑은 그대로
    정렬 전부 다시 배치만 다시

    단계가 나뉘어 있어서 여러 컴포넌트를 워커 스레드에 나눠 줄 수도 있습니다. TextMeshPro 의 텍스트 처리에는 스레드를 쓰는 코드가 없습니다. 다만 UniText 의 병렬은 조건이 까다로워 보통의 UI 에서는 대부분 메인 스레드에서 돕니다.

    얻은 것 4. 폰트와 이모지를 덜 싣는다

    TextMeshPro UniText
    이모지 스프라이트 에셋이나 이모지 폰트 에셋을 만들어 등록 기기의 OS 에 깔린 이모지 폰트를 찾아 씀
    이어 붙인 이모지 (가족, 피부색, 국기) 스프라이트 치환으로는 일반적인 처리가 안 됨 묶음 전체를 한 글자로 판정
    없는 글자의 폴백 제한적 OS 폰트로 자동 폴백
    빌드에 넣는 폰트 크기 그대로 압축해서 넣음 (12 MB 가 4.4 MB)

    사이트에 실린 사례 하나는 프로젝트를 이틀에 옮기고 폰트를 하나도 더하지 않은 채 11개 언어를 늘렸다고 적습니다. 기기의 OS 폰트로 폴백하기 때문에 가능한 일입니다.

    공식 사이트가 내세우는 속도

    공식 사이트는 TextMeshPro 와 견준 측정값을 싣습니다.

    항목 UniText TextMeshPro
    오브젝트 생성 166 ms 572 ms
    전체 재구성 136 ms 398 ms
    레이아웃 71 ms 1,468 ms
    메시 재구성 60 ms 424 ms
    생성 중 GC 횟수 3 147
    생성 중 할당 292 MB 2,249 MB
    동작 한 번의 할당 90 KB 13.8 MB

    이 숫자는 조건을 같이 읽어야 합니다.

    • 안드로이드 출하 빌드에서, 오브젝트 100개에 오브젝트마다 약 2,300자를 넣은 값입니다.
    • 텍스트는 라틴, 아랍어, 히브리어를 섞은 것입니다. TextMeshPro 가 제대로 그리지 못하는 글이라, 두 엔진이 같은 일을 한 비교가 아닙니다.
    • 기기와 유니티 버전은 적혀 있지 않습니다.
    • 유료판 3.x 의 값입니다.

    한국어와 영어만 쓰는 화면에서 어느 쪽이 빠른지는 이 표로 알 수 없습니다. 이 시리즈에서도 두 엔진을 같은 조건으로 재지 않았습니다.

    잃은 것 1. 입력, 3D 텍스트, 드롭다운

    TextMeshPro 는 텍스트 컴포넌트만이 아닙니다. TMP_InputField, TMP_Dropdown 이 함께 오고, 캔버스 밖 월드 공간용 TextMeshPro 컴포넌트도 있습니다.

    TextMeshPro UniText 무료판 UniText 유료판
    입력 필드 TMP_InputField 없음 있음 (3.0 부터)
    월드 공간 텍스트 TextMeshPro 없음 UniTextWorld
    드롭다운 TMP_Dropdown 없음 UniTextDropdown (3.8.0 부터)
    TextMeshPro 에서 옮기는 도구 해당 없음 없음 있음

    무료판에는 표시용 컴포넌트 UniText 하나뿐입니다. 클릭 위치를 알려 주는 이벤트와 선택 영역을 칠하는 코드는 있지만 입력 필드 컴포넌트는 없습니다. 무료판으로 닉네임 입력이나 채팅 입력창을 만들려면 직접 짜거나 TextMeshPro 를 함께 써야 합니다.

    유료판은 이 자리를 채웠고, 사이트는 오히려 입력 쪽을 강점으로 내세웁니다. 오른쪽에서 왼쪽 글의 캐럿과 선택, 실행 취소, 서식을 보면서 편집하기 같은 것들입니다.

    잃은 것 2. 미리 구운 아틀라스가 없다

    TextMeshPro 의 폰트 에셋은 글리프를 구운 아틀라스를 에셋에 저장해 둘 수 있습니다(AtlasPopulationMode.Static). 빌드에 픽셀이 들어 있어서 첫 프레임에 굽는 일이 없습니다.

    UniText 의 아틀라스는 저장되지 않습니다. 공식 문서도 글리프 아틀라스는 런타임에 만든다고 적습니다. 글리프는 화면에 처음 나오는 순간에 구워져 GPU 로 올라갑니다. 빌드는 작아지지만, 새 글자가 한꺼번에 처음 나오는 프레임에 굽는 비용이 몰립니다. 한글처럼 글자 수가 많은 언어에서 더 두드러집니다.

    잃은 것 3. 태그가 기본으로 켜져 있지 않다

    TextMeshPro 는 <b>, <color>, <size> 같은 태그를 처음부터 읽습니다.

    UniText 에는 기본으로 켜진 태그가 없습니다. 규칙과 모디파이어를 등록해야 읽히고, 등록하지 않으면 <b>world</b> 가 글자 그대로 나옵니다. TextMeshPro 에서 옮길 때 가장 먼저 걸리는 자리입니다.

    유료판은 TextMeshPro 에 있던 태그 몇 가지를 태그가 아닌 다른 방식으로 바꿨습니다. 외곽선과 그림자는 태그가 아니라 텍스트 전체에 거는 스타일이고, <alpha> 는 TextMeshPro 와 동작이 달라 이전 도구가 경고를 냅니다.

    잃은 것 4. 네이티브 바이너리가 따라온다

    TextMeshPro 는 전부 C# 입니다. 유니티가 도는 곳이면 돕니다.

    UniText 는 HarfBuzz, FreeType, Blend2D 를 묶은 네이티브 라이브러리가 플랫폼마다 따로 들어 있습니다. 무료판은 하나의 크기가 2 ~ 5 MB 입니다(Android arm64 가 약 2.4 MB).

    TextMeshPro UniText
    지원 플랫폼 유니티가 도는 모든 곳 Windows, macOS, Linux, Android, iOS, tvOS, WebGL (유료판은 UWP 와 visionOS 도)
    콘솔 됨 목록에 없음
    WebGL 다른 플랫폼과 같음 OS 폰트에 접근할 수 없어 폰트를 직접 넣어야 하고, 컬러 이모지 폰트를 굽지 못함
    문제를 들여다볼 때 C# 디버거 네이티브 쪽은 C# 디버거로 볼 수 없음

    잃은 것 5. 어느 기기에서나 같은 이모지

    UniText 는 기기의 OS 에 깔린 이모지 폰트를 빌려 씁니다. 빌드는 작아지지만, 기기마다 깔린 폰트가 달라 이모지 모양이 기기마다 다릅니다. TextMeshPro 는 이모지 그림을 직접 등록해 빌드에 넣으므로 어느 기기에서나 같은 그림이 나옵니다.

    TextMeshPro UniText
    이모지 모양 등록한 그림이라 어느 기기에서나 같음 기기의 OS 폰트라 기기마다 다름
    이모지가 안 나올 가능성 등록했으면 나옴 기기에서 이모지 폰트를 못 찾으면 통째로 안 나옴

    바뀌지 않은 것

    uGUI 에 붙는 방식은 거의 같습니다. 무료판 소스로 확인한 것입니다.

    • 둘 다 MaskableGraphic 을 상속합니다.
    • 둘 다 OnPopulateMesh 를 쓰지 않고 CanvasRenderer 에 메시를 직접 넘깁니다.
    • 둘 다 폰트가 여럿이면 숨은 자식 오브젝트를 만들어 나눠 그립니다.

    Graphic 하나가 CanvasRenderer 하나와 머티리얼 하나를 전제하기 때문에, 두 엔진이 같은 제약에서 같은 답에 닿았습니다. 그래서 캔버스 배칭, 마스크, 레이아웃 그룹 안에서의 동작은 TextMeshPro 를 쓰던 감각 그대로 다뤄도 됩니다.

    정리

    UniText 는 TextMeshPro 가 구조상 못 하는 문맥 셰이핑과 양방향 처리를 얻고, TextMeshPro 에서는 신경 쓰지 않아도 되던 것을 떠안은 엔진입니다.

    • 얻은 것은 앞뒤 글자를 본 글리프 선택, 섞인 방향, 바뀐 층만 다시 도는 캐시, 덜 싣는 폰트와 이모지입니다.
    • 잃은 것은 미리 구운 아틀라스, 기본으로 켜진 태그, 순수 C# 이라는 단순함, 기기마다 같은 이모지입니다.
    • 입력 필드, 월드 공간 텍스트, 드롭다운은 무료판에만 없고 유료판에는 있습니다.
    • 공식 사이트의 속도 비교는 TextMeshPro 가 제대로 그리지 못하는 섞인 글로 잰 값입니다.