首先我们需要一张字体图片:
放入unity,修改sprite mode为multipie多张图,以便分割,
点击sprite editor,如果报错请下载2d spite工具
然后点击Slice,会自动分割数字,也可以自己再调下位置
在Project下新建材质number1,修改材质的shader,并放入刚刚的图片
在新建custom font命为number1,将上面的材质球,拖入default material
index:为1的1asic码值
uv:数字1在图片中的位置,不过要在0-1之间
vert:为偏移量,不过高度要取负
advance:宽度
flipped:反向
在创建text,将刚才自定义的字体拖入font即可
这样只能一个字符,下面用代码的形式创建多个字符
AssetDatabase.GetAssetPath(object)
该object在assets下的路径,返回string
AssetDatabase.LoadAssetAtPath< T>(string fontPath)
加载该object的路径,返回T
AssetDatabase.LoadAllAssetsAtPath(path);
//加载该路径下的所有资源,返回Object[]
AssetDatabase.CreateAsset(object, string matPath);
在对应路径下创建object,无返回值
//保存资源
AssetDatabase.SaveAssets();
//更新asset修改的资源
AssetDatabase.Refresh();
代码:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
public class XFImageFontMaker : MonoBehaviour
{
//MenuItem可以让我们在asset下的物体右键执行指定方法
[MenuItem("Assets/XFCreateImageFont")]
static void XFCreateImageFont()
{
if (Selection.objects == null) return;
for(int i=0;i<Selection.objects.Length;i++)
{
//如果右键对象是图片才执行
if(Selection.objects[i].GetType()==typeof(Texture2D))
{
CreateImageFont(Selection.objects[i] as Texture2D);
}
}
}
public static void CreateImageFont(Texture2D texture)
{
if (texture == null) return;
//获取贴图路径
string texturePath = AssetDatabase.GetAssetPath(texture);
//获取路径后缀
string textureExtension = Path.GetExtension(texturePath);
//得到存图片的那个文件路径
string filePath = texturePath.Remove(texturePath.Length - textureExtension.Length);
//要创建材质和字体的路径后缀(自定)
string matPath = filePath + ".mat";
string fontPath = filePath + ".fontsettings";
//如果字体已经创建加载路径即可
Font font = AssetDatabase.LoadAssetAtPath<Font>(fontPath);
if(font==null)
{
font = new Font();
//创建材质修改shader
Material mat = new Material(Shader.Find("GUI/Text Shader"));
mat.SetTexture("_MainTex", texture);
//在文件夹里创建材质
AssetDatabase.CreateAsset(mat, matPath);
font.material = mat;
//在文件夹里创建字体
AssetDatabase.CreateAsset(font, fontPath);
}
//设置字符
Sprite[] sprites = LoadSpriteByPath(texturePath);
if(sprites.Length==0)
{
print("没有发现创建的字符,请分割一下字符");
return;
}
CharacterInfo[] characterInfos = new CharacterInfo[sprites.Length];
for(int i=0;i<characterInfos.Length;i++)
{
characterInfos[i] = new CharacterInfo();
//获取字符名字最后一个字符
characterInfos[i].index = sprites[i].name[sprites[i].name.Length - 1];
//设置字符uv
Rect rect = sprites[i].rect;
characterInfos[i].uvBottomLeft = new Vector2(rect.x / texture.width, rect.y / texture.height);
characterInfos[i].uvBottomRight = new Vector2((rect.x+ rect.width) / texture.width, rect.y / texture.height);
characterInfos[i].uvTopLeft = new Vector2(rect.x / texture.width, (rect.y + rect.height )/ texture.height);
characterInfos[i].uvTopRight = new Vector2((rect.x + rect.width) / texture.width, (rect.y + rect.height) / texture.height);
//设置字符偏移和宽高
characterInfos[i].minX = 0;
characterInfos[i].maxX = (int)rect.width;
//sprites[i].pivot为每个字符的中心点坐标
//方便对特定字符修改中心点来定位
characterInfos[i].minY = 0 - (int)sprites[i].pivot.y ;
characterInfos[i].maxY = (int)rect.height - (int)sprites[i].pivot.y ;
characterInfos[i].advance = (int)rect.width;
}
font.characterInfo = characterInfos;
EditorUtility.SetDirty(font);
//保存资源
AssetDatabase.SaveAssets();
//更新asset修改的资源
AssetDatabase.Refresh();
}
public static Sprite[] LoadSpriteByPath(string path)
{
List<Sprite> sprites = new List<Sprite>();
//加载该路径下的所有资源
Object[] objects = AssetDatabase.LoadAllAssetsAtPath(path);
for(int i=0;i<objects.Length;i++)
{
if(objects[i].GetType()==typeof(Sprite))
{
sprites.Add(objects[i] as Sprite);
}
}
return sprites.ToArray();
}
}
操作:
勾选图片数字1的Advanced->Read/write enabled
点击sprite editor修改每个字符的name的最后一位,因为是以名字最后一个作为字体的index(ascii),点击apply
当希望你的字符像放在下中的位置,请将中心点pivot改为top center(相反)
再对数字一图片,右键点击刚才的脚本
就会多出字体和材质
再新建Text,将自定义字体数字1拖入Text 的Font,居中,随便输入数字测试
当我们修改脚本时,要重新单击图片右键后才会生效
缺点:
1.这种方式无法修改字符大小
2.只能对ascii码表里的字符生效