UGUI實現(xiàn)隨意調(diào)整Text中的字體間距
UGUI中是沒有可以隨意調(diào)整字體間的距離的方法,仔細研究一下可以通過控制每個字體的網(wǎng)格頂點位置進行調(diào)整字體之間的距離,分析一下最簡單情況:輸入的文本是單行的,且末尾沒有換行符;
unity在UnityEngine.UI命名空間中定義了一個BaseMeshEffect抽象類,他提供了一個抽象方法ModifyMesh(VertexHelper vh),使得可以輕松地獲得text文本中所有字體 的頂點信息,我們的移動字體的操作將在這里面進行。VertexHelper類主要是用于提供字體網(wǎng)格數(shù)據(jù)的工具類;
上述便是掛載TestSpacingText腳本之后的效果圖。下面貼出代碼
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TextSpacingTest : BaseMeshEffect
{
 public float spacing = 0;
 public override void ModifyMesh(VertexHelper vh)
 {
  List<UIVertex> vertexs = new List<UIVertex>();
  vh.GetUIVertexStream(vertexs);
  int vertexIndexCount = vertexs.Count;
  for (int i = 6; i < vertexIndexCount; i++)
  {
   UIVertex v = vertexs[i];
   v.position += new Vector3(spacing * (i / 6), 0, 0);
   vertexs[i] = v;
   if (i % 6 <= 2)
   {
    vh.SetUIVertex(v, (i / 6) * 4 + i % 6);
   }
   if (i % 6 == 4)
   {
    vh.SetUIVertex(v, (i / 6) * 4 + i % 6 - 1);
   }
  }
 }
}
分析代碼:
1)首先創(chuàng)建一個字體間距的變量,然后需要繼承BaseMeshEffect類并且實現(xiàn)其中的抽象的方法MeshModify()函數(shù)。
2)創(chuàng)建一個容器從網(wǎng)格信息生成器vh中將字體的頂點信息全部加載保存下來
3)接下來開始遍歷獲取到的頂點,我們知道每個字體是由兩個三角形的組成的網(wǎng)格,字體是顯示在這樣的網(wǎng)格上的,因此每個字體也就對應6個頂點。那么就開始移動每個頂點就可以了。
4)移動頂點之后要記得設置UV頂點與頂點索引的對應關系,因為一個字體網(wǎng)格由兩個三角形組成,那么就重疊了兩個頂點,故而一個字體的6個頂點,就只對應4個UV頂點索引,如上代碼顯示的那樣。
分析如下:
接下來看看比較復雜的情況:
文本的情況為,可以有多行,或單行,單行、多行時末尾均可以有換行符。
核心思路:
1)先考慮僅僅是多行且末尾行的末尾沒有換行符的情況,解決了這個核心問題,再考慮其他的問題。
2)將多行的文本按照換行符進行分割,這樣每一行就形成了一個字符串,此時對每一行進行上面簡單的操作,就可以實現(xiàn)移動的了。
3)考慮到所有的文本的頂點信息數(shù)據(jù)都存儲在vh中,可以創(chuàng)建一個行數(shù)據(jù)結構Line以此來存儲每行的基本屬性(比如:本行開始定點的索引位置,結束頂點的索引位置,所有頂點的數(shù)量)。
4)簡單多行的情況,利用上面的分行的思路就可以解決,接下來分析其他的問題。
5)單行時末尾有換行符,我們在分割字符串之后要加以判斷是否有空串的情況 ,若有那么就認為末尾產(chǎn)生了換行符,此時空串不再創(chuàng)建LIne對象,只用創(chuàng)建一個Line對象。解法看代碼。
6)多行時末尾有換行符,同樣用于上面一樣的方法進行檢驗,最后一個空串不在創(chuàng)建Line對象,解法看代碼。
7)之后若是想擴展修改字體垂直方向的間距也可以在此基礎上修改,非常簡單。
接下來看代碼:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
internal class Line
{
 //每行開始頂點索引
 private int startVertexIndex;
 public int StartVertexIndex
 {
  get
  {
   return startVertexIndex;
  }
 }
 //每行結束頂點索引
 private int endVertexIndex;
 public int EndVertexIndex
 {
  get
  {
   return endVertexIndex;
  }
 }
 //每行頂點總量
 private int countVertexIndex;
 public int CountVertexIndex
 {
  get
  {
   return countVertexIndex;
  }
 }
 public Line(int startVertexIndex,int countVertexIndex)
 {
  this.startVertexIndex = startVertexIndex;
  this.countVertexIndex = countVertexIndex;
  this.endVertexIndex = this.startVertexIndex + countVertexIndex - 1;
 }
}
/// <summary>
/// 這是設置字體移動的核心類
/// 執(zhí)行多重行移動的核心算法是:將多重行分開依次進行處理,每一行的處理都是前面對單行處理的子操作
/// 但是由vh是記錄一個文本中所有的字的頂點,所以說需要分清楚每行開始,每行結束,以及行的字個數(shù),
/// 如此需要創(chuàng)建一個行的數(shù)據(jù)結構,以保存這些信息
/// </summary>
public class TextSpacingMulTest : BaseMeshEffect
{
 public float spacing = 0;
 public override void ModifyMesh(VertexHelper vh)
 {
  Text text = GetComponent<Text>();
  string[] ls = text.text.Split('\n');
  int length = ls.Length;
  bool isNewLine = false;
  Line[] line;
  if (string.IsNullOrEmpty(ls[ls.Length - 1]) == true)
  {
   line = new Line[length - 1];
   isNewLine = true;
  }
  else
  {
   line = new Line[length];
   
  }
  //Debug.Log("ls長度" + ls.Length);
  for (int i = 0; i < line.Length; i++)
  {
   if (i == 0 && line.Length == 1&&isNewLine==false)//解決單行時沒有換行符的情況
   {
    line[i] = new Line(0, ls[i].Length * 6);
    break;
   }
   if (i == 0&&line.Length>=1)//解決單行時有換行符的情況,以及多行時i為0的情況
   {
    line[i] = new Line(0, (ls[i].Length+1) * 6);
   }
   else
   {
    if (i < line.Length - 1)
    {
     line[i] = new Line(line[i - 1].EndVertexIndex + 1, (ls[i].Length + 1) * 6);
    }
    else
    {
     if (isNewLine == true)//解決多行時,最后一行末尾有換行符的情況
     {
      line[i] = new Line(line[i - 1].EndVertexIndex + 1, (ls[i].Length + 1) * 6);
     }
     else
     {
      line[i] = new Line(line[i - 1].EndVertexIndex + 1, ls[i].Length * 6);
     }
    }
   }
  }
  
  List<UIVertex> vertexs = new List<UIVertex>();
  vh.GetUIVertexStream(vertexs);
  int countVertexIndex = vertexs.Count;
  //Debug.Log("頂點總量" + vertexs.Count);
  for (int i = 0; i < line.Length; i++)
  {
   if (line[i].CountVertexIndex == 6) { continue; }
   for (int k = line[i].StartVertexIndex+6; k <= line[i].EndVertexIndex; k++)
   {
    UIVertex vertex = vertexs[k]; 
    vertex.position += new Vector3(spacing * ((k-line[i].StartVertexIndex) / 6), 0, 0);
    //Debug.Log("執(zhí)行");
    vertexs[k] = vertex;
    if (k % 6 <= 2)
    {
     vh.SetUIVertex(vertex, (k / 6) * 4 + k % 6);
    }
    if (k % 6 == 4)
    {
     vh.SetUIVertex(vertex, (k / 6) * 4 + k % 6 - 1);
    }
   }
  }
 }
}
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持我們。
欄 目:C#教程
下一篇:UnityShader3實現(xiàn)轉(zhuǎn)圈與冷卻效果
本文標題:UGUI實現(xiàn)隨意調(diào)整Text中的字體間距
本文地址:http://www.jygsgssxh.com/a1/C_jiaocheng/4839.html
您可能感興趣的文章
- 01-10C#實現(xiàn)txt定位指定行完整實例
 - 01-10WinForm實現(xiàn)仿視頻播放器左下角滾動新聞效果的方法
 - 01-10C#實現(xiàn)清空回收站的方法
 - 01-10C#實現(xiàn)讀取注冊表監(jiān)控當前操作系統(tǒng)已安裝軟件變化的方法
 - 01-10C#實現(xiàn)多線程下載文件的方法
 - 01-10C#實現(xiàn)Winform中打開網(wǎng)頁頁面的方法
 - 01-10C#實現(xiàn)遠程關閉計算機或重啟計算機的方法
 - 01-10C#自定義簽名章實現(xiàn)方法
 - 01-10C#文件斷點續(xù)傳實現(xiàn)方法
 - 01-10winform實現(xiàn)創(chuàng)建最前端窗體的方法
 


閱讀排行
本欄相關
- 01-10C#通過反射獲取當前工程中所有窗體并
 - 01-10關于ASP網(wǎng)頁無法打開的解決方案
 - 01-10WinForm限制窗體不能移到屏幕外的方法
 - 01-10WinForm繪制圓角的方法
 - 01-10C#實現(xiàn)txt定位指定行完整實例
 - 01-10WinForm實現(xiàn)仿視頻播放器左下角滾動新
 - 01-10C#停止線程的方法
 - 01-10C#實現(xiàn)清空回收站的方法
 - 01-10C#通過重寫Panel改變邊框顏色與寬度的
 - 01-10C#實現(xiàn)讀取注冊表監(jiān)控當前操作系統(tǒng)已
 
隨機閱讀
- 08-05DEDE織夢data目錄下的sessions文件夾有什
 - 01-10使用C語言求解撲克牌的順子及n個骰子
 - 08-05織夢dedecms什么時候用欄目交叉功能?
 - 01-10delphi制作wav文件的方法
 - 04-02jquery與jsp,用jquery
 - 01-10C#中split用法實例總結
 - 01-11ajax實現(xiàn)頁面的局部加載
 - 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
 - 01-10SublimeText編譯C開發(fā)環(huán)境設置
 - 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
 


