UGUI中CustomFont(BMFont)字体使用与制作
2017-11-23 本文已影响681人
codingriver
首先使用工具Bitmap Font Generator生成.fnt和图集贴图,教程参考Unity3D-使用Bitmap Font Generator自定义字体
这里主要介绍根据Text格式的.fnt和贴图 在unity中自定义字体
-
生成字体教程
上代码(Unity版本5.6.0f3)
生成字体文件后必须重启unity才能生效,否则字体文件不能正确加载(unity bug或者我没找到方法刷新unity,知道的请指教)
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
public class BMFontEditor : EditorWindow {
public TextAsset fontPosTbl;
public Texture fontTexture;
public Vector2 scrollPos;
struct ChrRect {
public int id;
public int x;
public int y;
public int w;
public int h;
public int xofs;
public int yofs;
public int index;
public float uvX;
public float uvY;
public float uvW;
public float uvH;
public float vertX;
public float vertY;
public float vertW;
public float vertH;
public float width;
}
// add menu
[MenuItem("Tools/BMFontTools")]
static void Init() {
EditorWindow.GetWindow(typeof(BMFontEditor));
}
// layout window
void OnGUI() {
//EditorGUILayout.BeginScrollView(scrollPos);
EditorGUILayout.BeginVertical();
// use .fnt(.txt)
fontTexture = (Texture)EditorGUILayout.ObjectField("Font Texture", fontTexture, typeof(Texture), false);
EditorGUILayout.Space();
EditorGUILayout.LabelField("Use BMFont fnt File", EditorStyles.boldLabel);
EditorGUILayout.LabelField("(must Font Descriptor select Text)", EditorStyles.boldLabel);
fontPosTbl = (TextAsset)EditorGUILayout.ObjectField("BMFont fnt (.fnt)", fontPosTbl, typeof(TextAsset), false);
if (GUILayout.Button("Create(创建后必须重启生效)")) {
if (fontTexture == null) this.ShowNotification(new GUIContent("No Font Texture selected"));
else if (fontPosTbl == null) this.ShowNotification(new GUIContent("No Font Position Table file selected"));
else {
CalcChrRect(fontPosTbl, fontTexture);
}
}
EditorGUILayout.LabelField("(Must Restart unity valid!)", EditorStyles.whiteBoldLabel);
EditorGUILayout.LabelField("*********************************", EditorStyles.largeLabel);
EditorGUILayout.EndVertical();
//EditorGUILayout.EndScrollView();
}
void OnInspectorUpdate() {
this.Repaint();
}
void CalcChrRect(TextAsset posTbl, Texture tex) {
string fileName = AssetDatabase.GetAssetPath(fontPosTbl);
string texName = AssetDatabase.GetAssetPath(tex);
string fontName = System.IO.Path.GetFileNameWithoutExtension(fileName);
string fontPath = fileName.Replace(".fnt", ".fontsettings");
string matPath = fileName.Replace(".fnt", ".mat");
float imgw = (float)tex.width;
float imgh = (float)tex.height;
string txt = posTbl.text;
List<ChrRect> tblList = new List<ChrRect>();
foreach (string line in txt.Split('\n')) {
if (line.IndexOf("char id=") == 0) {
ChrRect d = GetChrRect(line, imgw, imgh);
tblList.Add(d);
}
}
if(tblList.Count==0)
{
new GUIContent("Failed");
return;
}
ChrRect[] tbls = tblList.ToArray();
Font font = new Font();
font.name = fontName;
SetCharacterInfo(tbls, font);
Material mat = new Material(Shader.Find("Unlit/Transparent"));
mat.mainTexture = tex;
mat.name = fontName;
font.material = mat;
Debug.Log(System.IO.Path.GetFileNameWithoutExtension(fileName));
Debug.Log(fileName);
AssetDatabase.CreateAsset(mat, matPath);
AssetDatabase.CreateAsset(font, fontPath);
AssetDatabase.SaveAssets();
this.ShowNotification(new GUIContent("Complete"));
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
}
// over write custom font by new CharacterInfo
void SetCharacterInfo(ChrRect[] tbls, Font fontObj) {
CharacterInfo[] nci = new CharacterInfo[tbls.Length];
for (int i = 0; i < tbls.Length; i++) {
nci[i].index = tbls[i].index;
nci[i].advance = (int)tbls[i].width;
nci[i].uv.x = tbls[i].uvX;
nci[i].uv.y = tbls[i].uvY;
nci[i].uv.width = tbls[i].uvW;
nci[i].uv.height = tbls[i].uvH;
nci[i].vert.x = tbls[i].vertX;
nci[i].vert.y = tbls[i].vertY;
nci[i].vert.width = tbls[i].vertW;
nci[i].vert.height = tbls[i].vertH;
}
fontObj.characterInfo = nci;
}
// get font table one line.
ChrRect GetChrRect(string line, float imgw, float imgh) {
ChrRect d = new ChrRect();
foreach (string s in line.Split(' ')) {
if (s.IndexOf("id=") >= 0) d.id = GetParamInt(s, "id=");
else if (s.IndexOf("x=") >= 0) d.x = GetParamInt(s, "x=");
else if (s.IndexOf("y=") >= 0) d.y = GetParamInt(s, "y=");
else if (s.IndexOf("width=") >= 0) d.w = GetParamInt(s, "width=");
else if (s.IndexOf("height=") >= 0) d.h = GetParamInt(s, "height=");
else if (s.IndexOf("xoffset=") >= 0) d.xofs = GetParamInt(s, "xoffset=");
else if (s.IndexOf("yoffset=") >= 0) d.yofs = GetParamInt(s, "yoffset=");
else if (s.IndexOf("xadvance=") >= 0) d.width = GetParamInt(s, "xadvance=");
}
d.index = d.id;
d.uvX = (float)d.x / imgw;
d.uvY = (float)(imgh-(d.y)) / imgh;
d.uvW = (float)d.w / imgw;
//d.uvH = (float)-d.h / imgh;
d.uvH = (float)-d.h / imgh;
d.vertX = (float)d.xofs;
d.vertY = (float)d.yofs;
d.vertW = d.w;
d.vertH = d.h;
return d;
}
// "wd=int" to int
int GetParamInt(string s, string wd) {
if (s.IndexOf(wd) >= 0) {
int v;
if (int.TryParse(s.Substring(wd.Length), out v)) return v;
}
return int.MaxValue;
}
}
将脚本放在Unity工程的Editor目录下
点击Tools-->BMFontTools按钮
image.png
打开界面
image.png
托入资源,.fnt文件必须是Text文本结构的,不能是Xml和Binary(Bitmap Font Generator在这里面配置)
image.png
image.png
点击生成
image.png
生成后必须重启unity才能生效,否则字体文件不能正确加载(unity bug或者我没找到方法刷新unity)
**
-
文字换行问题
设置字体的LineSpacing属性,为文字的高度,这里设置应该是128,一般不用
image.png