<aside> 💡 TextMesy Pro를 사용할 경우, 언어별로 머티리얼들 구축해야 하기 때문에 이를 자동화시킴

</aside>

예시 이미지

예시 이미지

코드 구성

using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using TMPro;

/* 
------------------------------------------------------------------------------------------------------------
작성  : (woody)
설명  : TMP 메인 폰트의 머티리얼 리스트를 기준으로, 각 언어별 TMP 폰트들을 대상으로 동일한 머티리얼 리스트를 생성합니다.
주의  : 메인 폰트가 변경될 경우, 'mainFontName' 변수를 변경해줘야 합니다.
주의  : 만약 "Font & Materials" 의 Root 경로가 변경될 경우, 'fontFolderPath' 변수를 변경해줘야 합니다.
주의  : TMP 폰트의 Atlas Population Mode -> static 이어야 정상 작동합니다. (Dinamic 불가)
------------------------------------------------------------------------------------------------------------
*/

public class TextMeshProMaterialGenerator : MonoBehaviour
{
    [MenuItem("UI Utility/TextMeshPro Material Generator")]
    static void TmpMatGen()
    {

        TMP_FontAsset[] fonts = Resources.LoadAll<TMP_FontAsset>("Font & Materials");   // "Font & Materials" 폴더내 전체 TMP 폰트
        Material[] materials = Resources.LoadAll<Material>("Font & Materials");         // "Font & Materials" 폴더내 전체 머티리얼
        Texture2D[] atlases = Resources.LoadAll<Texture2D>("Font & Materials");         // "Font & Materials" 폴더내 전체 아틀라스
        List<Material> oneMobile_materials = new List<Material>();                      // ONE Mobile 머티리얼 리스트
        List<Material> core_materials = new List<Material>();                           // 각 폰트의 코어 머티리얼 리스트
        string mainFontName = "ONE Mobile POP SDF";                                     // ONE Mobile TMP 폰트명 : (**메인폰트 변경시 이 부분을 바꿔줌)
        string fontFolderPath = "Assets/Asset Game/Graphics/Resources/Font & Materials/";

        try
        {
            AssetDatabase.StartAssetEditing();  // 데이터베이스 편집 시작

            foreach (Material material in materials)
            {
                // OneMobile 폰트의 머티리얼만 추출
                if (material.name.Contains(mainFontName) && !material.name.EndsWith("Material"))
                {
                    oneMobile_materials.Add(material);
                    Debug.Log("Main Material: " + material.name);
                // 폰트 자체에 포함된 머티리얼은 패스
                }
                else if (material.name.EndsWith("Material"))
                {
                    core_materials.Add(material);
                    Debug.Log("EndsWidth Material: " + material.name);
                // ONE Mobile 관련 머티리얼이 아니라면 모두 제거
                }
                else
                {
                    string path = AssetDatabase.GetAssetPath(material);
                    AssetDatabase.DeleteAsset(path);
                    Debug.Log("Deleted Material: " + material.name);
                }
            }
        }
        finally
        {
            AssetDatabase.StopAssetEditing();  // 데이터베이스 편집 종료
        }

        // 메인 폰트를 제외한 나머지 폰트들에 대해 적용
        foreach (TMP_FontAsset font in fonts)
        {
            if (font.name != mainFontName)
            {
                foreach (Material oneMobile_material in oneMobile_materials)
                {
                    
                    Material clonedMaterial = new Material(oneMobile_material);                         // OneMobile 머티리얼 복제
                    clonedMaterial.name = oneMobile_material.name.Replace(mainFontName, font.name);     // 복제한 머티리얼의 이름 변경: mainFontName -> font.name으로

                    foreach (Texture2D atlas in atlases) {     // 아틀라스 교체 로직
                        foreach (Material core_material in core_materials)
                        {
                            // 폰트 머티리얼의 속성값을 복제된 머티리얼에 모두 적용
                            if (atlas.name.Contains(font.name) && core_material.name.Contains(font.name))
                            {
                                clonedMaterial.SetTexture("_MainTex", atlas);
                                clonedMaterial.SetFloat("_GradientScale", core_material.GetFloat("_GradientScale"));
                                clonedMaterial.SetFloat("_TextureWidth", core_material.GetFloat("_TextureWidth"));
                                clonedMaterial.SetFloat("_TextureHeight", core_material.GetFloat("_TextureHeight"));
                                clonedMaterial.SetFloat("_ScaleX", core_material.GetFloat("_ScaleX"));
                                clonedMaterial.SetFloat("_ScaleY", core_material.GetFloat("_ScaleY"));
                                clonedMaterial.SetFloat("_Sharpness", core_material.GetFloat("_Sharpness"));
                                clonedMaterial.SetFloat("_PerspectiveFilter", core_material.GetFloat("_PerspectiveFilter"));
                                clonedMaterial.SetFloat("_VertexOffsetX", core_material.GetFloat("_VertexOffsetX"));
                                clonedMaterial.SetFloat("_VertexOffsetY", core_material.GetFloat("_VertexOffsetY"));
                                clonedMaterial.SetVector("_ClipRect", core_material.GetVector("_ClipRect"));
                                clonedMaterial.SetFloat("_MaskSoftnessX", core_material.GetFloat("_MaskSoftnessX"));
                                clonedMaterial.SetFloat("_MaskSoftnessY", core_material.GetFloat("_MaskSoftnessY"));
                                clonedMaterial.SetFloat("_CullMode", core_material.GetFloat("_CullMode"));
                                break;
                            }
                        }
                    }

                    // 복제한 머티리얼을 프로젝트에 저장
                    string path = fontFolderPath + clonedMaterial.name + ".mat";
                    AssetDatabase.CreateAsset(clonedMaterial, path);
                    Debug.Log("Created Material: " + clonedMaterial.name + " for Font: " + font.name);
                }
            }
        }
    }
}