什么是Mesh

Mesh是指的模型的网格,3D模型是由多边形拼接而成,而多边形实际上又是由多个三角形拼接而成的。即一个3D模型的表面其实是由多个彼此相连的三角面构成。三维空间中,构成这些三角形的点和边的集合就是Mesh

为什么要用Mesh实现战斗飘血

我们都做游戏的时候,都是知道一个很熟悉的词汇“预设体”,它在游戏开发过程中有这举足轻重的地位,时刻时刻都能见到他的身影。我们可以通过预设体的特征克隆出大量的具有相同性质的游戏物体,我上一个项目的的飘血实现就是用不断的克隆预设体实现的。由于战斗的节奏很快,所以会创建很多的飘血对象。比如场景有一百条飘血展示,这个时候客户端就需要存在一百条飘血的对象。这个对内存的消耗是很大,并且没有必要的。
问:“有什么改进的方法吗”?
答:“有的”。

工作原理

我们可以通过Mesh来实现,

  1. 创建Mesh对象
  2. 初始化Mash的顶点数据,UV数据
  3. 根据输入的内容设置顶点数据,UV数据
  4. 在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);elseDebugger.LogError("静态字体没有文字[{0}],请修复", c);}return true;}}
}
  1. 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;     // 正在绘制Uvprivate 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;}//构建Meagpublic 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);}
}
  1. 简单测试代码
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 framevoid 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显示。

Unity Mash实现战斗飘血相关推荐

  1. Unity 伤害飘血效果

    Unity 伤害飘血效果 前言 一.效果演示 二.相关代码 前言 一个对于战斗中飘字飘血的功能,比较简单. 一.效果演示 字的颜色没调整好,所以有点不好看. 二.相关代码 根据自定义曲线控制飘字效果 ...

  2. Unity3d自学记录 利用TextMesh制作飘血数字

    安利一个源码网站:http://www.9miao.com/forum-49-1.html 最近在学习源码,自己写的代码总是太丑..(无奈脸),看的一个简单的RPGDemo(AppStore里的),代 ...

  3. unity制作类似DNF动态血条(仅一层血条)

    unity制作类似DNF动态血条(仅一层血条) 这是某个游戏公司的招聘题目,我的思路给大家参考一下 上图为效果图 如下代码: using System.Collections; using Syste ...

  4. Unity 战斗飘字飘血 ShootTextPro

    前言,写了一个小工具,主要就是战斗中对应的飘字,源码相应的注释已经标注,非常方便自定义改动,其中ShootTextProController可以做成单例,传入对应的tranform即可,为了展示示例, ...

  5. unity实现文字飘血

    效果如下: 下载链接:https://download.csdn.net/download/weixin_44350205/12849600

  6. [Unity][Animator][UGUI]伤害飘字跟随角色不停的移动

    在相关资料1的基础上实现,伤害飘字 特效 跟随 玩家角色. 逻辑图 UIFollowManage using System.Collections.Generic; using UnityEngine ...

  7. Unity实现各种样式的血条

    我将讲述三种不同类型血条UI的实现 第一种是常见的进度条样式的血条实现: 进度条式的血条样式如图示 要实现进度条式的血条,我们需要使用到unity的UI中的滑动条,它分为Slider滑动条,Backg ...

  8. Unity 3D游戏十:血条制作

    前言 中山大学数据科学与计算机学院3D游戏课程学习记录博客. 游戏代码: gitee 参考师兄的博客: 师兄博客 游戏视频:bilibili 游戏要求 血条(Health Bar)的预制设计. 具体要 ...

  9. Unity UGUI实现分段式血条

    我们可以看到像英雄联盟等游戏里英雄头顶的血条显示并非是纯色的,而是根据血量的多少而显示一定量的格子,这种方式明显是比较友好.比较美观的,事实上我们的游戏里面也想实现这样的效果,那该怎么办呢?根据血量的 ...

最新文章

  1. CSS:响应式下的折叠菜单(条纹式)
  2. 向PHP使用Post方式上传文件
  3. 释疑の语法Unpackpack
  4. for循环只执行一次_Python中for循环和while循环有什么区别?
  5. [JSP暑假实训] 四.MyEclipse+Servlet+JSP实现火车票网站查询、修改、删除操作
  6. centos安装nginx,配置负载均衡
  7. 【ujson】pip安装ujson报错: error:Microsoft Visual C++ 14.0 is required
  8. springboot多环境配置_编辑 SpringBoot|第五章:多环境配置
  9. 编译加速 remote cache
  10. python 逐行读取文本
  11. Android自定义gif进度条,Android自定义view-圆形百分比进度条效果
  12. 记录点滴——2019年终总结
  13. 邱锡鹏《神经网络与深度学习》蒲公英书学习笔记
  14. 【期末复习】现代管理科学基础
  15. 解决kafka传输超大图片消费者接收失败问题
  16. 鲁豫有约--之分享李连杰的私密生活
  17. U盘插入电脑需要格式化,数据恢复
  18. 2021春招Java面试题大全(精华六)
  19. Linux中C语言编程经验总结
  20. 移动客户端触屏滑动事件

热门文章

  1. 21世纪出现的现代「文明病」 五种被社群媒体影响的症状
  2. 微信“史诗级”更新,小而美终于回来啦!
  3. 【Python模块学习】pandas模块简介
  4. 2021-10-262021年茶艺师(高级)考试题及茶艺师(高级)考试内容
  5. 使用matlab发送SCPI,怎么使用matlab创建和发送arb
  6. delay 芯片时序output_综合和静态时序分析
  7. Apache IoTDB源码解析(0.11.2版本):Session的源码解析
  8. 高中数学基础02:反函数与基本初等函数
  9. 最适合失恋男生唱的10首歌
  10. 诗经 -小雅 - 鱼丽