什么是Mesh
Mesh是指的模型的网格,3D模型是由多边形拼接而成,而多边形实际上又是由多个三角形拼接而成的。即一个3D模型的表面其实是由多个彼此相连的三角面构成。三维空间中,构成这些三角形的点和边的集合就是Mesh
为什么要用Mesh实现战斗飘血
我们都做游戏的时候,都是知道一个很熟悉的词汇“预设体”,它在游戏开发过程中有这举足轻重的地位,时刻时刻都能见到他的身影。我们可以通过预设体的特征克隆出大量的具有相同性质的游戏物体,我上一个项目的的飘血实现就是用不断的克隆预设体实现的。由于战斗的节奏很快,所以会创建很多的飘血对象。比如场景有一百条飘血展示,这个时候客户端就需要存在一百条飘血的对象。这个对内存的消耗是很大,并且没有必要的。
问:“有什么改进的方法吗”?
答:“有的”。
工作原理
我们可以通过Mesh来实现,
- 创建Mesh对象
- 初始化Mash的顶点数据,UV数据
- 根据输入的内容设置顶点数据,UV数据
- 在Mesh渲染出来
详细过程
附上代码,只有稍微对Mesh有点了解的你,这些代码都不是问题:
1.SpriteHeper
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpriteHelper
{
private Rect uvRect;
private Font font;
bool isDynamic;
public Font getFont { get { return font; } }
Dictionary<char, CharacterInfo> m_dicCharacter;
Dictionary<char, CharacterInfo> characterTable
{
get
{
if (m_dicCharacter == null)
m_dicCharacter = new Dictionary<char, CharacterInfo>();
return m_dicCharacter;
}
}
public SpriteHelper(Font fontInfo, bool isDynamic)
{
font = fontInfo;
if (font.dynamic != isDynamic)
{
Debugger.LogError("字体类型不符合,请修改!");
}
this.isDynamic = isDynamic;
}
public Rect GetSpriteRect(char index)
{
return GetFontUv(index);
}
public Rect GetFontUv(char index)
{
CharacterInfo cha;
if (GetCharacterInfo(index, out cha))
{
uvRect = new Rect(cha.uvBottomLeft, cha.uvTopRight - cha.uvBottomLeft);
if (uvRect.width < 0)
{
uvRect.x += uvRect.width;
uvRect.width *= -1;
}
if (uvRect.height < 0)
{
uvRect.y += uvRect.height;
uvRect.height *= -1;
}
return uvRect;
}
return Rect.zero;
}
internal bool GetCharacterInfo(char c, out CharacterInfo info)
{
if (isDynamic)
{
return font.GetCharacterInfo(c, out info);
}
else
{
if (!characterTable.TryGetValue(c, out info))
{
if (font.GetCharacterInfo(c, out info))
characterTable.Add(c, info);
else
Debugger.LogError("静态字体没有文字[{0}],请修复", c);
}
return true;
}
}
}
- UIMeshTextGenerator
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
public class UIMeshText
{
public Color?[] colorArray;
public string originString; //起始
public string outPutString; // 输出
public Vector2 offset;
public float[] minX;
public float[] minY;
public float[] maxX;
public float[] maxY;
public float[] advance;
public Vector3 pos;
public float scale;
public Color color;
public Vector3 scaleVec = Vector3.zero;
public UIMeshText(string originStr)
{
originString = originStr;
colorArray = new Color?[originStr.Length];
}
}
public class UIMeshTextGenerator
{
StringBuilder m_textBuilder;
static readonly Regex m_colorRegex = new Regex(@"<color=(#[a-zA-Z0-9]{6,8})>(.*?)</color>", RegexOptions.Singleline);
public UIMeshTextGenerator()
{
m_textBuilder = new StringBuilder();
}
public UIMeshText GeneratText(string originStr)
{
UIMeshText meshText = new UIMeshText(originStr);
meshText.outPutString = originStr;
meshText.minX = new float[meshText.outPutString.Length];
meshText.minY = new float[meshText.outPutString.Length];
meshText.maxX = new float[meshText.outPutString.Length];
meshText.maxY = new float[meshText.outPutString.Length];
meshText.advance = new float[meshText.outPutString.Length];
return meshText;
}
private void FillOutPutClass(string originStr, UIMeshText meshText)
{
m_textBuilder.Length = 0;
int textIndex = 0;
foreach (Match match in m_colorRegex.Matches(originStr))
{
m_textBuilder.Append(originStr.Substring(textIndex, match.Index - textIndex));
int trueIndex = m_textBuilder.Length;
m_textBuilder.Append(match.Groups[2].Value);
for (int i = 0; i < match.Groups[2].Value.Length; i++)
meshText.colorArray[trueIndex + i] = GetColot(match.Groups[1].Value);
textIndex = match.Index + match.Length;
}
m_textBuilder.Append(originStr.Substring(textIndex, originStr.Length - textIndex));
meshText.outPutString = m_textBuilder.ToString();
}
private Color GetColot(string colorStr)
{
Color colour;
ColorUtility.TryParseHtmlString(colorStr, out colour);
return colour;
}
}
3 . UIMesh
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
using UnityEngine.UI;
using System.Text;
public class VertPool
{
private int maxVertNum;
private int[] blocks; //顶点
private char[] charList;
public VertPool(int maxVert)
{
maxVertNum = maxVert;
blocks = new int[maxVert % 4 == 0 ? maxVert >> 2 : maxVert >> 2 + 1]; // 取4的倍数
charList = new char[maxVert % 4 == 0 ? maxVert >> 2 : maxVert >> 2 + 1];
}
// 获取一个顶点
public int GetVert()
{
for (int i = 0; i < blocks.Length; i++)
{
if (blocks[i] >= 0)
{
blocks[i] = -1;
return i;
}
}
Debug.Log("No Available Vertex");
return -1;
}
public int GetVert(char value)
{
for (int i = 0; i < blocks.Length; i++)
{
if (blocks[i] >= 0)
{
blocks[i] = -1;
charList[i] = value;
return i;
}
}
Debug.Log("No Available Vertex");
return -1;
}
// 顶点数是否足够
public bool TestVert(int nCount)
{
int nCurCount = 0;
for (int i = 0; i < blocks.Length; i++)
{
if (blocks[i] >= 0)
{
nCurCount++;
if (nCurCount > nCount)
{
return true;
}
}
}
return false;
}
public int[] GetBlocks { get { return blocks; } }
public char[] GetCharList { get { return charList; } }
//释放
public void ReleaseVert(int id)
{
if (id < blocks.Length && blocks[id] < 0)
{
blocks[id] = 0;
}
}
}
public class UIMesh
{
private GameObject gameObj;
private MeshFilter meshFilter;
private MeshRenderer meshRenderer;
private Vector3[] vertices; //顶点
private Vector2[] uvs; //uv 顶点
private Color[] colors;
private int[] triangles; //三角形
private Mesh mesh;
private VertPool vp; //顶点对象池
private SpriteHelper spriteHelper;
private bool m_isDrawUving = false; // 正在绘制Uv
private Vector2 m_rectVec = Vector2.zero;
private Vector3 m_vertOffsetVec = Vector3.zero;
private Dictionary<List<int>, UIMeshText> m_requireList;
private UIMeshTextGenerator textGenerator;
public RectTransform rectTransform;
private bool bShow = false;
private bool needRefresh = false;
private bool dynamic = false; //是否动态
private bool uvNeedRebuild = false;
private float critScale = 0.7f;
public UIMesh(GameObject parent, string name, Font font, bool isdynamic = false, int vertCount = 2040)
{
CreateMeshObject(name, parent);
CreateMeshComponent(font.material);
InitCapacity(vertCount);
spriteHelper = new SpriteHelper(font, isdynamic);
m_requireList = new Dictionary<List<int>, UIMeshText>();
textGenerator = new UIMeshTextGenerator();
dynamic = isdynamic;
this.gameObj.SetActive(false);
if (isdynamic)
{
Font.textureRebuilt += OnFontTextureRebuild;
}
else
{
meshRenderer.material.shader = UnityEngine.UI.Text.defaultGraphicMaterial.shader;
}
}
public void SetRenderQueue(int nQueue)
{
meshRenderer.material.renderQueue = nQueue;
}
public void Show(bool bShow)
{
if (this.bShow == bShow)
{
return;
}
this.bShow = bShow;
this.gameObj.SetActive(bShow);
}
public Vector3 GetVectorInMesh(Vector3 worldPos)
{
return gameObj.transform.InverseTransformPoint(worldPos);
}
//创建对象
private void CreateMeshObject(string name, GameObject parent)
{
gameObj = new GameObject();
gameObj.name = name;
gameObj.transform.SetParent(parent.transform);
}
//添加脚本
private void CreateMeshComponent(Material meshMaterial)
{
rectTransform = gameObj.AddComponent<RectTransform>();
meshFilter = gameObj.AddComponent<MeshFilter>();
meshRenderer = gameObj.AddComponent<MeshRenderer>();
meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
meshRenderer.lightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off;
meshRenderer.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off;
meshRenderer.receiveShadows = false;
meshRenderer.material = meshMaterial;
mesh = new Mesh();
mesh.name = gameObj.name;
meshFilter.mesh = mesh;
}
//初始化顶点数据
private void InitCapacity(int vertCount)
{
vertices = new Vector3[vertCount];
uvs = new Vector2[vertCount];
triangles = new int[(vertCount - 2) * 3];
colors = new Color[vertCount];
vp = new VertPool(vertCount);
}
public void OnFontTextureRebuild(Font changedFont)
{
if (changedFont != spriteHelper.getFont)
return;
RebuildMesh();
}
private void ReDrawVerts(int vertIndex, float vertPosx, float vertPosy, Color vertColor, float vertAngle = 0)
{
if (vertAngle != 0)
RotationZ(vertAngle, ref vertPosx, ref vertPosy);
vertices[vertIndex].x = vertPosx;
vertices[vertIndex].y = vertPosy;
colors[vertIndex] = vertColor;
}
private void ReDrawUVs(int vertIndex, float uvVectorx, float uvVectory)
{
uvs[vertIndex].x = uvVectorx;
uvs[vertIndex].y = uvVectory;
}
/// <summary>
/// 通过旋转矩阵对顶点进行旋转,等同于修改unity中的rotation
/// </summary>
/// <param name="angle"></param>
/// <param name="vertX"></param>
/// <param name="vertY"></param>
private void RotationZ(float angle, ref float vertX, ref float vertY)
{
float x, y;
float CosAngle = Mathf.Cos(angle * Mathf.Deg2Rad);
float SinAngle = Mathf.Sin(angle * Mathf.Deg2Rad);
x = vertX * CosAngle - SinAngle * vertY;
y = vertX * SinAngle + CosAngle * vertY;
vertX = x;
vertY = y;
}
/// <summary>
/// 绘制一个正方形,占用4个顶点。根据顶点下标,绘制位置,图集宽高,uv位置绘制。
/// </summary>
/// <param name="vertIndex">顶点下标,不是4的倍数会从4的倍数开始绘制</param>
/// <param name="drawRect">xy为绘制起点(左下角),宽高代表绘制大小与缩放,使用世界坐标</param>
/// <param name="uvRect">xy是左下角uv坐标值。根据这个值算出四个点的uv</param>
private void DrawMesh(int vertIndex, Rect drawRect, Rect uvRect, Color drawColor, float vertAngle = 0)
{
return;
if (vertIndex % 4 != 0)
{
vertIndex = vertIndex >> 2 << 2;
}
int vertStartIndex = vertIndex;
int triglesIndex = vertIndex * 6 / 4;
ReDrawVerts(vertIndex, drawRect.x, drawRect.y, drawColor, vertAngle);
ReDrawUVs(vertIndex, uvRect.x, uvRect.y);
ReDrawVerts(++vertIndex, drawRect.x, drawRect.y + drawRect.height, drawColor, vertAngle);
ReDrawUVs(vertIndex, uvRect.x, (uvRect.y + uvRect.height));
ReDrawVerts(++vertIndex, drawRect.x + drawRect.width, drawRect.y + drawRect.height, drawColor, vertAngle);
ReDrawUVs(vertIndex, (uvRect.x + uvRect.width), (uvRect.y + uvRect.height));
ReDrawVerts(++vertIndex, drawRect.x + drawRect.width, drawRect.y, drawColor, vertAngle);
ReDrawUVs(vertIndex, (uvRect.x + uvRect.width), uvRect.y);
SetTriangle(triglesIndex, vertStartIndex);
}
private void SetTriangle(int triangleIndex, int vertIndex)
{
triangles[triangleIndex] = vertIndex;
triangles[triangleIndex + 1] = vertIndex + 1;
triangles[triangleIndex + 2] = vertIndex + 2;
triangles[triangleIndex + 3] = vertIndex;
triangles[triangleIndex + 4] = vertIndex + 2;
triangles[triangleIndex + 5] = vertIndex + 3;
}
void SetColor(int index, Color color)
{
colors[index + 0] = color;
colors[index + 1] = color;
colors[index + 2] = color;
colors[index + 3] = color;
}
//构建Meag
public void RebuildMesh()
{
if (m_isDrawUving)
{
return;
}
var blocks = vp.GetBlocks;
var charList = vp.GetCharList;
for (int i = 0; i < blocks.Length; i++)
{
if (blocks[i] == -1)
{
CharacterInfo ch;
if (!spriteHelper.GetCharacterInfo(charList[i], out ch))
{
uvNeedRebuild = true;
return;
}
SetUv(i << 2, ch);
}
}
needRefresh = true;
}
private void SetUv(int index, CharacterInfo ch)
{
//矩形的四个顶点
var uvTopLeft = ch.uvTopLeft;
var uvTopRight = ch.uvTopRight;
var uvBottomRight = ch.uvBottomRight;
var uvBottomLeft = ch.uvBottomLeft;
if (uvTopLeft == uvTopRight)
{
return;
}
uvs[index + 1] = uvTopLeft;
uvs[index + 2] = uvTopRight;
uvs[index + 3] = uvBottomRight;
uvs[index + 0] = uvBottomLeft;
}
public void Update()
{
if (!this.bShow)
{
return;
}
if (needRefresh)
{
RefreshMesh();
needRefresh = false;
}
if (null == m_requireList || dynamic == false)
{
return;
}
var e = m_requireList.GetEnumerator();
while (e.MoveNext())
{
spriteHelper.getFont.RequestCharactersInTexture(e.Current.Value.outPutString);
}
if (uvNeedRebuild)
{
uvNeedRebuild = false;
RebuildMesh();
}
}
private void RefreshMesh()
{
mesh.vertices = vertices;
mesh.uv = uvs;
mesh.triangles = triangles;
mesh.colors = colors;
}
private Vector3 SetVertOffsetVector(Vector3 pos, float x, float y)
{
pos.x += x;
pos.y += y;
return pos;
}
private void SetVert(int index, Vector3 pos, float maxX, float maxY, Vector3 scale)
{
int x = maxX > 0 ? 1 : -1;
int y = maxY > 0 ? 1 : -1;
if (y < 0)
{
pos.y += scale.y;
}
vertices[index + 1] = SetVertOffsetVector(pos, 0, scale.y * y);
vertices[index + 2] = SetVertOffsetVector(pos, scale.x * x, scale.y * y);
vertices[index + 3] = SetVertOffsetVector(pos, scale.x * x, 0);
vertices[index + 0] = pos;
}
public void RefreshDynamicPos(List<int> vertIndexList, Vector3 pos, Vector3 scale)
{
if (null == vertIndexList) return;
UIMeshText meshText = m_requireList[vertIndexList];
if (pos == meshText.pos)
return;
meshText.pos = pos;
meshText.scaleVec = scale;
pos.x -= scale.x * 0.5f;
m_isDrawUving = true;
var listCount = vertIndexList.Count;
for (int i = 0; i < listCount; i++)
{
int verticeStartIndex = vertIndexList[i] << 2;
SetVert(verticeStartIndex, pos, meshText.maxX[i], meshText.maxY[i], scale);
pos.x += meshText.advance[i] * scale.z;
}
needRefresh = true;
m_isDrawUving = false;
}
public void RefreshDynamicPos(List<int> vertIndexList, string showString, Vector3 pos, float scale, Color color, float scaleGlobal = 0.1f)
{
if (null == vertIndexList) return;
UIMeshText meshText = m_requireList[vertIndexList];
if (showString == meshText.originString && pos == meshText.pos && color == meshText.color)
return;
meshText.pos = pos;
meshText.color = color;
showString = meshText.outPutString;
if (showString != null)
{
pos.x -= meshText.offset.x * 0.5f;
}
m_isDrawUving = true;
var listCount = vertIndexList.Count;
for (int i = 0; i < listCount; i++)
{
int verticeStartIndex = vertIndexList[i] << 2;
//Color c = meshText.colorArray[i] == null ? color : (Color)meshText.colorArray[i];
SetVert(verticeStartIndex, pos, meshText.minX[i], meshText.minY[i], meshText.maxX[i], meshText.maxY[i], scale);
SetColor(verticeStartIndex, color);
pos.x += meshText.advance[i] * scale;
}
needRefresh = true;
m_isDrawUving = false;
}
public void RefreshDynamicPos(List<int> vertIndexList, Color color)
{
if (null == vertIndexList) return;
UIMeshText meshText = m_requireList[vertIndexList];
if (color == meshText.color)
return;
meshText.color = color;
m_isDrawUving = true;
var listCount = vertIndexList.Count;
for (int i = 0; i < listCount; i++)
{
int verticeStartIndex = vertIndexList[i] << 2;
SetColor(verticeStartIndex, color);
}
needRefresh = true;
m_isDrawUving = false;
}
public void RefreshDynamicPos(List<int> vertIndexList, string showString, Vector3 pos, Vector3 scale, Color color, float scaleGlobal = 0.1f)
{
if (null == vertIndexList) return;
UIMeshText meshText = m_requireList[vertIndexList];
showString = meshText.outPutString;
if (showString == meshText.originString && pos == meshText.pos && color == meshText.color && meshText.scaleVec == scale) return;
meshText.pos = pos;
meshText.color = color;
meshText.scaleVec = scale;
pos.x -= scale.x * 0.5f;
m_isDrawUving = true;
var listCount = vertIndexList.Count;
for (int i = 0; i < listCount; i++)
{
int verticeStartIndex = vertIndexList[i] << 2;
//Color c = color//meshText.colorArray[i] == null ? color : (Color)meshText.colorArray[i];
SetVert(verticeStartIndex, pos, meshText.maxX[i], meshText.maxY[i], scale);
SetColor(verticeStartIndex, color);
pos.x += meshText.advance[i] * scale.z;
}
needRefresh = true;
m_isDrawUving = false;
}
public void LuanMa(List<int> vertIndexList)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < vertIndexList.Count; i++)
{
int vertIndex = vertIndexList[i];
int index = vertIndex << 2;
sb.Append(string.Format("{0}=", vertIndex));
for (int k = 0; k < 4; k++)
{
sb.Append(string.Format("({0:0.000000},{1:0.000000}) ", uvs[index + k].x, uvs[index + k].y));
}
sb.Append("\n");
}
Debugger.Log("strUV==" + sb.ToString());
}
public void SetUVNeedRebuild()
{
uvNeedRebuild = true;
}
public Vector2 GetTextOffset(List<int> vertIndexList, float scale)
{
if (null == vertIndexList)
return Vector2.zero;
UIMeshText meshText = m_requireList[vertIndexList];
if (meshText != null)
return meshText.offset;
return Vector2.zero;
}
public List<int> DrawDynamicTextUVs(string showString, Vector3 pos, float scale, Color color, float scaleGlobal = 0.1f, bool isCrit = false)
{
if (!vp.TestVert(showString.Length))
{
return null;
}
UIMeshText meshText = textGenerator.GeneratText(showString);
meshText.pos = pos;
meshText.scale = scale;
meshText.color = color;
if (dynamic)
spriteHelper.getFont.RequestCharactersInTexture(meshText.outPutString);
List<int> indexArray = new List<int>();
int vertIndex;
bool bSuccess = true;
var offsets = GetTextRect(meshText.outPutString, scale, out bSuccess);
if (!bSuccess)
{
Debugger.LogError("DrawDynamicTextUVs uv error={0}", showString);
return null;
}
meshText.offset = offsets;
pos.x -= offsets.x * 0.5f;
for (int i = 0; i < meshText.outPutString.Length; i++)
{
vertIndex = vp.GetVert(meshText.outPutString[i]);
if (vertIndex == -1)
{
return null;
}
indexArray.Add(vertIndex);
int verticeStartIndex = vertIndex << 2;
int triangleStartIndex = vertIndex * 6;
CharacterInfo ch;
Color c = meshText.colorArray[i] == null ? color : (Color)meshText.colorArray[i];
if (!spriteHelper.GetCharacterInfo(meshText.outPutString[i], out ch))
{
uvNeedRebuild = true;
continue;
}
if ((meshText.outPutString[i] == '暴' || meshText.outPutString[i] == '击') && isCrit)
{
meshText.minX[i] = ch.minX * critScale;
meshText.maxX[i] = ch.maxX * critScale;
meshText.minY[i] = ch.minY * critScale;
meshText.maxY[i] = ch.maxY * critScale;
meshText.advance[i] = ch.advance * critScale;
}
else
{
meshText.minX[i] = ch.minX;
meshText.maxX[i] = ch.maxX;
meshText.minY[i] = ch.minY;
meshText.maxY[i] = ch.maxY;
meshText.advance[i] = ch.advance;
}
SetVert(verticeStartIndex, pos, meshText.minX[i], meshText.minY[i], meshText.maxX[i], meshText.maxY[i], scale);
SetUv(verticeStartIndex, ch);
SetColor(verticeStartIndex, c);
SetTriangle(triangleStartIndex, verticeStartIndex);
pos.x += meshText.advance[i] * scale;
}
needRefresh = true;
if (!m_requireList.ContainsKey(indexArray))
m_requireList.Add(indexArray, meshText);
return indexArray;
}
private void SetVert(int index, Vector3 pos, float minX, float minY, float maxX, float maxY, float scale)
{
minX *= scale;
maxX *= scale;
minY *= scale;
maxY *= scale;
vertices[index + 1] = SetVertOffsetVector(pos, minX, maxY);
vertices[index + 2] = SetVertOffsetVector(pos, maxX, maxY);
vertices[index + 3] = SetVertOffsetVector(pos, maxX, minY);
vertices[index + 0] = SetVertOffsetVector(pos, minX, minY);
}
public Vector2 GetTextRect(string showString, float scale, out bool bSuccess, bool isCrit = false)
{
float length = 0;
float heigth = 0;
bSuccess = true;
for (int i = 0; i < showString.Length; i++)
{
CharacterInfo ch;
bSuccess = spriteHelper.GetCharacterInfo(showString[i], out ch);
if (!bSuccess)
{
break;
}
if ((showString[i] == '暴' || showString[i] == '击') && isCrit)
{
length += ch.advance * scale * critScale;
float fAbsHeight = Mathf.Abs(ch.glyphHeight);
heigth = heigth > fAbsHeight ? heigth : fAbsHeight;
}
else
{
length += ch.advance * scale;
float fAbsHeight = Mathf.Abs(ch.glyphHeight);
heigth = heigth > fAbsHeight ? heigth : fAbsHeight;
}
}
m_rectVec.x = length;
m_rectVec.y = heigth;
return m_rectVec;
}
public void RefreshVertPos(List<int> vertArray, Vector3 pos, float scale, Color color, float vertAngle = 0)
{
RefreshDynamicPos(vertArray, null, pos, scale, color);
}
public void ReleaseVert(List<int> vertArray)
{
if (null == vertArray) return;
for (int i = 0; i < vertArray.Count; i++)
{
vp.ReleaseVert(vertArray[i]);
DrawMesh(vertArray[i] * 4, Rect.zero, Rect.zero, Color.white);
}
//ListPool<int>.Release(vertArray);
if (m_requireList.ContainsKey(vertArray))
m_requireList.Remove(vertArray);
needRefresh = true;
}
public List<int> DrawDamage(string showString, Vector3 pos, float scale, Color color, bool isCrit = false)
{
//请有bug修复bug,不要在这里用Replace方式处理文字。以下代码屏蔽@hmz
//showString = showString.Replace(" ", "");
return DrawDynamicTextUVs(showString, pos, scale, color, 0.1f, isCrit);
}
}
- 简单测试代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class MyMeshText : MonoBehaviour
{
UIMesh mesh;
public UnityEngine.UI.Text text;
private List<int> m_meshArry = new List<int>();
void Start()
{
mesh = new UIMesh(gameObject, "mymesh", text.font, true, 1024);
m_meshArry = mesh.DrawDamage("闪避", new Vector3(978, 529, 0), 0.4f, Color.black, false);
}
int i = 0;
// Update is called once per frame
void Update()
{
if (null != mesh)
mesh.Update();
mesh.Show(true);
if (Input.GetKeyDown(KeyCode.A))
{
i += 100;
mesh.ReleaseVert(m_meshArry);
m_meshArry.Clear();
m_meshArry = mesh.DrawDamage("44444525", new Vector3(978, 529 + i, 0), 0.4f, Color.black, false);
}
}
}
这样我们只需要对一个Mesh操作就能实现很多伤害飘血。而不需要像之前那样美一条伤害飘血都去创建一个UIText显示。