유 니 티 가 사용자 정의 글꼴 을 만 드 는 두 가지 방법
알 아야 할 정 보 는 스티커 에 있 는 모든 문자 에 대응 하 는 ASCII 코드(예 를 들 어 0 의 ASCII 코드 는 48)와 이 문자 가 그림 집합 에 대응 하 는 위치(0 은 x:0;y:0;w:55;h:76)。그리고 유 니 티 에 소재 와 CustomFont 을 만 들 고 정보 에 따라 설정 합 니 다.
마지막 으로 글꼴 을 얻 습 니 다.
두 가지 방식 의 차 이 는 첫 번 째 단계 에서 앨범 의 정 보 를 어떻게 얻 느 냐 에 있다.구체 적:
첫 번 째 BMFont 을 사용 하 는 방식 은'fnt 파일'을 얻 기 위해 서 이 며,실제로는 xml 형식 파일 입 니 다.구체 적 인 정 보 는 다음 과 같다.
BMFont 의 사용 방법 은 더 이상 상술 하지 않 습 니 다.그림 집합 fnt 파일 을 얻 은 후 인터넷 에서 일반적인 방법 은 유 니 티 에 있 는 인 자 를 수 동 으로 계산 하 는 것 입 니 다.좀 번 거 롭 습 니 다.여기 서 Editor 스 크 립 트 를 써 서 이 과정 을 자동 으로 완성 합 니 다.직접 코드 올 리 기:
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using UnityEditor;
using UnityEngine;
public class CreateFontFromFnt : EditorWindow
{
[MenuItem("Tools/ (Fnt)")]
static void DoIt()
{
GetWindow<CreateFontFromFnt>(" ");
}
private string fontName;
private string fontPath;
private Texture2D tex;
private string fntFilePath;
private void OnGUI()
{
GUILayout.BeginVertical();
GUILayout.BeginHorizontal();
GUILayout.Label(" :");
fontName = EditorGUILayout.TextField(fontName);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label(" :");
tex = (Texture2D)EditorGUILayout.ObjectField(tex, typeof(Texture2D), true);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button(string.IsNullOrEmpty(fontPath) ? " " : fontPath))
{
fontPath = EditorUtility.OpenFolderPanel(" ", Application.dataPath, "");
if (string.IsNullOrEmpty(fontPath))
{
Debug.Log(" ");
}
else
{
fontPath = fontPath.Replace(Application.dataPath, "") + "/";
}
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button(string.IsNullOrEmpty(fntFilePath) ? " fnt " : fntFilePath))
{
fntFilePath = EditorUtility.OpenFilePanelWithFilters(" fnt ", Environment.GetFolderPath(Environment.SpecialFolder.Desktop), new string[] { "", "fnt" });
if (string.IsNullOrEmpty(fntFilePath))
{
Debug.Log(" ");
}
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button(" "))
{
Create();
}
GUILayout.EndHorizontal();
GUILayout.EndVertical();
}
private void Create()
{
if (string.IsNullOrEmpty(fntFilePath))
{
Debug.LogError("fnt ");
return;
}
if (tex == null)
{
Debug.LogError(" ");
return;
}
string fontSettingPath = fontPath + fontName + ".fontsettings";
string matPath = fontPath + fontName + ".mat";
if (File.Exists(Application.dataPath + fontSettingPath))
{
Debug.LogErrorFormat(" :{0}", fontSettingPath);
return;
}
if (File.Exists(Application.dataPath + matPath))
{
Debug.LogErrorFormat(" :{0}", matPath);
return;
}
var list = new List<CharacterInfo>();
XmlDocument xmlDoc = new XmlDocument();
var content = File.ReadAllText(fntFilePath, System.Text.Encoding.UTF8);
xmlDoc.LoadXml(content);
var nodelist = xmlDoc.SelectNodes("font/chars/char");
foreach (XmlElement item in nodelist)
{
CharacterInfo info = new CharacterInfo();
var id = int.Parse(item.GetAttribute("id"));
var x = float.Parse(item.GetAttribute("x"));
var y = float.Parse(item.GetAttribute("y"));
var width = float.Parse(item.GetAttribute("width"));
var height = float.Parse(item.GetAttribute("height"));
info.index = id;
// ,
info.uvBottomLeft = new Vector2(x / tex.width, 1 - (y + height) / tex.height);
info.uvBottomRight = new Vector2((x + width) / tex.width, 1 - (y + height) / tex.height);
info.uvTopLeft = new Vector2(x / tex.width, 1 - y / tex.height);
info.uvTopRight = new Vector2((x + width) / tex.width, 1 - y / tex.height);
info.minX = 0;
info.maxX = (int)width;
info.minY = -(int)height / 2;
info.maxY = (int)height / 2;
info.advance = (int)width;
list.Add(info);
}
Material mat = new Material(Shader.Find("GUI/Text Shader"));
mat.SetTexture("_MainTex", tex);
Font m_myFont = new Font();
m_myFont.material = mat;
AssetDatabase.CreateAsset(mat, "Assets" + matPath);
AssetDatabase.CreateAsset(m_myFont, "Assets" + fontSettingPath);
m_myFont.characterInfo = list.ToArray();
EditorUtility.SetDirty(m_myFont);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Debug.Log(" !");
}
}
사용 하기 쉽다:코드 도 깊이 연구 할 만 한 것 이 없 는데 수 동 계산 을 대체 하 는 것 이 목적 이 고 무늬 가 비 칠 때 작은 구멍 이 있 을 뿐이다.
두 번 째 방식 은 Unity 의 Sprite 를 사용 합 니 다.Unity 는 하나의 Sprite 를 여러 개 로 자 르 는 것 을 지원 합 니 다.BMFont 에서 내 보 낸 fnt 파일 을 이런 식 으로 대체 할 수 있 습 니 다.수 동 으로 해 야 할 작업 은 그림 집의 Texture Type 을 Sprite 로 설정 한 다음 Sprite Mode 를 Multiple 로 설정 하고 Sprite Editor 를 열 어 그림 을 자 르 는 것 입 니 다.Slice 는 기본적으로 이 일 을 완성 할 수 있 습 니 다.만약 에 수 동 으로 미세 조정 이 필요 하 다 면.
한 장의 그림 이 문자 의 위치 에 따라 10 개의 Sprite 로 나 뉘 었 다.그리고 모든 Sprite 를 선택 하여 Name 을 문자 에 대응 하 는 ASCII 코드 로 설정 합 니 다.이러한 첫 번 째 방법 에는 fnt 파일 에 포 함 된 정보 가 기본적으로 이'그림 집합'에 포함 되 어 있다.마찬가지 로 Editor 스 크 립 트 를 써 서 이 정 보 를 CustomFont 에 기록 하고 수 동 으로 만 들 지 않 아 도 됩 니 다.
using UnityEngine;
using UnityEditor;
using System.IO;
public class CreateFont : EditorWindow
{
[MenuItem("Tools/ (sprite)")]
public static void Open()
{
GetWindow<CreateFont>(" ");
}
private Texture2D tex;
private string fontName;
private string fontPath;
private void OnGUI()
{
GUILayout.BeginVertical();
GUILayout.BeginHorizontal();
GUILayout.Label(" :");
tex = (Texture2D)EditorGUILayout.ObjectField(tex, typeof(Texture2D), true);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
GUILayout.Label(" :");
fontName = EditorGUILayout.TextField(fontName);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button(string.IsNullOrEmpty(fontPath) ? " " : fontPath))
{
fontPath = EditorUtility.OpenFolderPanel(" ", Application.dataPath, "");
if (string.IsNullOrEmpty(fontPath))
{
Debug.Log(" ");
}
else
{
fontPath = fontPath.Replace(Application.dataPath, "") + "/";
}
}
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
if (GUILayout.Button(" "))
{
Create();
}
GUILayout.EndHorizontal();
GUILayout.EndVertical();
}
private void Create()
{
if (tex == null)
{
Debug.LogWarning(" , !");
return;
}
if (string.IsNullOrEmpty(fontPath))
{
Debug.LogWarning(" !");
return;
}
if (fontName == null)
{
Debug.LogWarning(" , !");
return;
}
else
{
if (File.Exists(Application.dataPath + fontPath + fontName + ".fontsettings"))
{
Debug.LogError(" , ");
return;
}
if (File.Exists(Application.dataPath + fontPath + fontName + ".mat"))
{
Debug.LogError(" , ");
return;
}
}
string selectionPath = AssetDatabase.GetAssetPath(tex);
if (selectionPath.Contains("/Resources/"))
{
string selectionExt = Path.GetExtension(selectionPath);
if (selectionExt.Length == 0)
{
Debug.LogError(" !");
return;
}
string fontPathName = fontPath + fontName + ".fontsettings";
string matPathName = fontPath + fontName + ".mat";
float lineSpace = 0.1f;
//string loadPath = selectionPath.Remove(selectionPath.Length - selectionExt.Length).Replace("Assets/Resources/", "");
string loadPath = selectionPath.Replace(selectionExt, "").Substring(selectionPath.IndexOf("/Resources/") + "/Resources/".Length);
Sprite[] sprites = Resources.LoadAll<Sprite>(loadPath);
if (sprites.Length > 0)
{
Material mat = new Material(Shader.Find("GUI/Text Shader"));
mat.SetTexture("_MainTex", tex);
Font m_myFont = new Font();
m_myFont.material = mat;
CharacterInfo[] characterInfo = new CharacterInfo[sprites.Length];
for (int i = 0; i < sprites.Length; i++)
{
if (sprites[i].rect.height > lineSpace)
{
lineSpace = sprites[i].rect.height;
}
}
for (int i = 0; i < sprites.Length; i++)
{
Sprite spr = sprites[i];
CharacterInfo info = new CharacterInfo();
try
{
info.index = System.Convert.ToInt32(spr.name);
}
catch
{
Debug.LogError(" ,Sprite !");
return;
}
Rect rect = spr.rect;
float pivot = spr.pivot.y / rect.height - 0.5f;
if (pivot > 0)
{
pivot = -lineSpace / 2 - spr.pivot.y;
}
else if (pivot < 0)
{
pivot = -lineSpace / 2 + rect.height - spr.pivot.y;
}
else
{
pivot = -lineSpace / 2;
}
int offsetY = (int)(pivot + (lineSpace - rect.height) / 2);
info.uvBottomLeft = new Vector2((float)rect.x / tex.width, (float)(rect.y) / tex.height);
info.uvBottomRight = new Vector2((float)(rect.x + rect.width) / tex.width, (float)(rect.y) / tex.height);
info.uvTopLeft = new Vector2((float)rect.x / tex.width, (float)(rect.y + rect.height) / tex.height);
info.uvTopRight = new Vector2((float)(rect.x + rect.width) / tex.width, (float)(rect.y + rect.height) / tex.height);
info.minX = 0;
info.minY = -(int)rect.height - offsetY;
info.maxX = (int)rect.width;
info.maxY = -offsetY;
info.advance = (int)rect.width;
characterInfo[i] = info;
}
AssetDatabase.CreateAsset(mat, "Assets" + matPathName);
AssetDatabase.CreateAsset(m_myFont, "Assets" + fontPathName);
m_myFont.characterInfo = characterInfo;
EditorUtility.SetDirty(m_myFont);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();//
Debug.Log(" ");
}
else
{
Debug.LogError(" !");
}
}
else
{
Debug.LogError(" , Resources !");
}
}
}
이 각본 은 어떤 박문 을 참고 하 였 는데,시간 이 지나 서 정말 찾 을 수 없다.원 리 는 첫 번 째 방법 과 마찬가지 로 세부 적 인 계산 에 약간의 차이 가 있 을 뿐이다.사용 하기는 여전히 간단 하 다.
대동소이 한 두 가지 방법 은 개인 적 으로 두 번 째 방법 을 더 좋아한다.별도의 소프트웨어 를 사용 하지 않 고 원 클릭 으로 해결 하면 기본적으로 미술 아동 화 에 버 려 서 만 들 수 있다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
photonnetwork.instantiate에서 gamepobject 유형을 생성 한 다음 상태 및 값을 참조하는 방법주로 마지막 기사에서 일어난 일의 수정입니다. 지난번↓ 그럼 주제입니다. (타이틀이 정리되어 없어서 죄송합니다) 우선 전회의 Illegal view ID:0입니다만 photonnetwork.instantiate를 사...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.