最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Unity制作自定義字體的兩種方法

 更新時間:2020年12月23日 15:08:28   作者:jince1991  
這篇文章主要為大家詳細介紹了Unity制作自定義字體的兩種方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

Unity支持自定義圖片字體(CustomFont),網(wǎng)上有很多教程,細節(jié)不盡相同,當概括起來基本就是兩種方式。一是使用BMFont,導出圖集和.fnt文件,再使用圖集在Unity中設置得到字體。二是不用BMFont,使用Unity自帶的Sprite類似圖集的功能。兩種方式原理相同,只是手段有區(qū)別?;驹矶际窍扔幸粡堎N圖,比如:

需要知道的信息是貼圖中每一個字符對應的ASCII碼(例如0的ASCII碼為48)與該字符在圖集中對應的位置(0為x:0;y:0;w:55;h:76)。然后在Unity中創(chuàng)建材質(zhì)和CustomFont并根據(jù)信息進行設置。

最后得到字體。

兩種方式的區(qū)別僅在于第一步中如何得到圖集的信息。具體的:

對于第一種使用BMFont的方式,目的是得到.fnt文件,實際上是xml格式文件。具體的信息為:

BMFont的使用方法不再詳述。得到圖集個fnt文件后,網(wǎng)上一般的方法是手動計算在Unity中的參數(shù),有些繁瑣,在這里寫一個Editor腳本來自動完成這個過程。直接上代碼:

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using UnityEditor;
using UnityEngine;
 
public class CreateFontFromFnt : EditorWindow
{
 [MenuItem("Tools/創(chuàng)建字體(Fnt)")]
 static void DoIt()
 {
  GetWindow<CreateFontFromFnt>("創(chuàng)建字體");
 }
 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("創(chuàng)建"))
  {
   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("已存在同名字體材質(zhì):{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;
   //紋理映射,上下翻轉(zhuǎn)
   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("創(chuàng)建成功!");
 }
}

使用起來很簡單:

代碼也沒什么可深究的,目的是代替手動計算,只是在紋理映射的時候有一個小坑。

第二種方式使用Unity中的Sprite。Unity支持把一個Sprite切割成多個。可以用這種方式代替BMFont導出的fnt文件。需要手動做的工作是將圖集的TextureType設置為Sprite,然后把SpriteMode設為Multiple,打開SpriteEditor,對圖片進行切割。Slice就基本可以完成這個工作,如果需要再手動微調(diào)一下。

一張圖按照字符的位置分割成了10個Sprite。然后選中每一個Sprite把Name設置成字符對應的ASCII碼。這樣第一種方法里fnt文件包含的信息基本都包含在這個“圖集”里了。同樣寫一個Editor腳本把這些信息寫入到CustomFont里面,并不用手動去創(chuàng)建。

using UnityEngine;
using UnityEditor;
using System.IO;
 
public class CreateFont : EditorWindow
{
 [MenuItem("Tools/創(chuàng)建字體(sprite)")]
 public static void Open()
 {
  GetWindow<CreateFont>("創(chuàng)建字體");
 }
 
 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("創(chuàng)建"))
  {
   Create();
  }
  GUILayout.EndHorizontal();
 
  GUILayout.EndVertical();
 }
 
 private void Create()
 {
  if (tex == null)
  {
   Debug.LogWarning("創(chuàng)建失敗,圖片為空!");
   return;
  }
 
  if (string.IsNullOrEmpty(fontPath))
  {
   Debug.LogWarning("字體路徑為空!");
   return;
  }
  if (fontName == null)
  {
   Debug.LogWarning("創(chuàng)建失敗,字體名稱為空!");
   return;
  }
  else
  {
   if (File.Exists(Application.dataPath + fontPath + fontName + ".fontsettings"))
   {
    Debug.LogError("創(chuàng)建失敗,已存在同名字體文件");
    return;
   }
   if (File.Exists(Application.dataPath + fontPath + fontName + ".mat"))
   {
    Debug.LogError("創(chuàng)建失敗,已存在同名字體材質(zhì)文件");
    return;
   }
  }
 
  string selectionPath = AssetDatabase.GetAssetPath(tex);
  if (selectionPath.Contains("/Resources/"))
  {
   string selectionExt = Path.GetExtension(selectionPath);
   if (selectionExt.Length == 0)
   {
    Debug.LogError("創(chuàng)建失?。?);
    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("創(chuàng)建失敗,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("創(chuàng)建字體成功");
 
   }
   else
   {
    Debug.LogError("圖集錯誤!");
   }
  }
  else
  {
   Debug.LogError("創(chuàng)建失敗,選擇的圖片不在Resources文件夾內(nèi)!");
  }
 }
}

這個腳本參考了某一篇博文,時間長了實在是找不到了。

原理跟第一種方法一樣,只是計算細節(jié)略有差異。使用起來還是很簡單:

大同小異的兩種方法,個人更喜歡用第二種。不需要使用額外的軟件,一鍵搞定,基本上可以丟給美術童鞋來做了。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • 關于C#數(shù)強轉(zhuǎn)會不會拋出異常詳解

    關于C#數(shù)強轉(zhuǎn)會不會拋出異常詳解

    這篇文章主要給大家介紹了關于C#數(shù)強轉(zhuǎn)會不會拋出異常的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2018-04-04
  • C#Process的OutputDataReceived事件不觸發(fā)問題及解決

    C#Process的OutputDataReceived事件不觸發(fā)問題及解決

    這篇文章主要介紹了C#Process的OutputDataReceived事件不觸發(fā)問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • C#將Sql數(shù)據(jù)保存到Excel文件中的方法

    C#將Sql數(shù)據(jù)保存到Excel文件中的方法

    這篇文章主要介紹了C#將Sql數(shù)據(jù)保存到Excel文件中的方法,文中的ExportExcel可起到將sql數(shù)據(jù)導出為Excel的作用,需要的朋友可以參考下
    2014-08-08
  • C#實現(xiàn)Word轉(zhuǎn)PDF的方法總結

    C#實現(xiàn)Word轉(zhuǎn)PDF的方法總結

    這篇文章主要為大家詳細介紹了C#中實現(xiàn)Word轉(zhuǎn)PDF的常用方法,文中的示例代碼講解詳細,具有一定的學習價值,有需要的小伙伴可以參考下
    2023-10-10
  • C#中Html.RenderPartial與Html.RenderAction的區(qū)別分析

    C#中Html.RenderPartial與Html.RenderAction的區(qū)別分析

    這篇文章主要介紹了C#中Html.RenderPartial與Html.RenderAction的區(qū)別分析,需要的朋友可以參考下
    2014-07-07
  • Visual Studio 中自定義代碼片段的方法

    Visual Studio 中自定義代碼片段的方法

    這篇文章主要介紹了Visual Studio 中自定義代碼片段的方法,本文分步驟通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • C#非矩形窗體實現(xiàn)方法

    C#非矩形窗體實現(xiàn)方法

    這篇文章主要介紹了C#非矩形窗體實現(xiàn)方法,涉及C#窗體操作的相關技巧,需要的朋友可以參考下
    2015-06-06
  • C#語法相比其它語言比較獨特的地方(二)

    C#語法相比其它語言比較獨特的地方(二)

    這篇文章主要介紹了C#語法相比其它語言比較獨特的地方(二),本文講解了internal與protected、private、enum、string的==、傳引用等內(nèi)容,需要的朋友可以參考下
    2015-04-04
  • Unity3D實現(xiàn)控制攝像機移動

    Unity3D實現(xiàn)控制攝像機移動

    這篇文章主要為大家詳細介紹了Unity3D實現(xiàn)控制攝像機移動 ,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • Unity動畫混合樹實例詳解

    Unity動畫混合樹實例詳解

    這篇文章主要為大家詳細介紹了Unity動畫混合樹實例,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11

最新評論

东兰县| 紫云| 札达县| 乌兰浩特市| 浦江县| 孝感市| 衡阳市| 临沂市| 梁山县| 东乌珠穆沁旗| 文登市| 赤城县| 宜兰县| 乐至县| 来凤县| 澜沧| 策勒县| 江陵县| 教育| 淅川县| 固原市| 闽侯县| 安平县| 万宁市| 密云县| 仪陇县| 肃宁县| 全州县| 麻阳| 余江县| 正安县| 股票| 双流县| 汽车| 郎溪县| 波密县| 涞水县| 抚顺市| 大邑县| 红河县| 财经|