Unity UGUI图文混排源码(一):http://blog.csdn.net/qq992817263/article/details/51112304

Unity UGUI图文混排源码(二):http://blog.csdn.net/qq992817263/article/details/51112311

为了方便整理,申请了一个专栏,链接:Unity UGUI图文混排专栏

图文混排解决方案二:

通过继承Text组件来获取文字的UIVertex并得到他的位置,通过Text富文本的<quad />来为图片占位,这样来实现图文混排,这里参考了一篇博客:http://blog.csdn.net/akof1314/article/details/49028279

1.这里我们会使用到一个SpriteAsset,具体的创建方法:http://blog.csdn.net/qq992817263/article/details/50958025

2.自定义一个渲染组件,用来渲染图片,后面我会将他放在Text文本下,这里会用一个参数,就是上面的SpriteAsset文件,具体代码如下

using UnityEngine;
using UnityEngine.UI;
using System.Collections;public class SpriteGraphic : MaskableGraphic {public SpriteAsset m_spriteAsset;public override Texture mainTexture{get{if (m_spriteAsset == null)return s_WhiteTexture;if (m_spriteAsset.texSource == null)return s_WhiteTexture;elsereturn m_spriteAsset.texSource;}}#if UNITY_EDITOR//在编辑器下 protected override void OnValidate(){base.OnValidate();//Debug.Log("Texture ID is " + this.texture.GetInstanceID());}
#endifprotected override void OnRectTransformDimensionsChange(){// base.OnRectTransformDimensionsChange();}/// <summary>/// 绘制后 需要更新材质/// </summary>public new void UpdateMaterial(){base.UpdateMaterial();}
}

3.自定义一个脚本用来继承Text,这里就是一个较为核心的代码,里面写了较为详细的注释

using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using System.Text.RegularExpressions;public class InlieText : Text {/// <summary>/// 用正则取标签属性 名称-大小-宽度比例/// </summary>private static readonly Regex m_spriteTagRegex =new Regex(@"<quad name=(.+?) size=(\d*\.?\d+%?) width=(\d*\.?\d+%?) />", RegexOptions.Singleline);/// <summary>/// 需要渲染的图片信息列表/// </summary>private List<InlineSpriteInfor> listSprite;/// <summary>/// 图片资源/// </summary>private SpriteAsset m_spriteAsset;/// <summary>/// 标签的信息列表/// </summary>private List<SpriteTagInfor> listTagInfor;/// <summary>/// 图片渲染组件/// </summary>private SpriteGraphic m_spriteGraphic;/// <summary>/// CanvasRenderer/// </summary>private CanvasRenderer m_spriteCanvasRenderer;/// <summary>/// 初始化 /// </summary>protected override void OnEnable(){base.OnEnable();if (m_spriteGraphic == null)m_spriteGraphic = GetComponentInChildren<SpriteGraphic>();if (m_spriteCanvasRenderer == null)m_spriteCanvasRenderer = m_spriteGraphic.GetComponentInChildren<CanvasRenderer>();m_spriteAsset = m_spriteGraphic.m_spriteAsset;}/// <summary>/// 在设置顶点时调用/// </summary>public override void SetVerticesDirty(){base.SetVerticesDirty();//解析标签属性listTagInfor = new List<SpriteTagInfor>();foreach (Match match in m_spriteTagRegex.Matches(text)){SpriteTagInfor tempSpriteTag = new SpriteTagInfor();tempSpriteTag.name = match.Groups[1].Value;tempSpriteTag.index = match.Index;tempSpriteTag.size = new Vector2(float.Parse(match.Groups[2].Value)*float.Parse(match.Groups[3].Value), float.Parse(match.Groups[2].Value));listTagInfor.Add(tempSpriteTag);}}/// <summary>/// 绘制模型/// </summary>/// <param name="toFill"></param>protected override void OnPopulateMesh(VertexHelper toFill){base.OnPopulateMesh(toFill);//获取所有的UIVertex,绘制一个字符对应6个UIVertex,绘制顺序为012 203List<UIVertex> listUIVertex = new List<UIVertex>();toFill.GetUIVertexStream(listUIVertex);//通过标签信息来设置需要绘制的图片的信息listSprite = new List<InlineSpriteInfor>();for (int i = 0; i < listTagInfor.Count; i++){//UGUIText不支持<quad/>标签,表现为乱码,我这里将他的uv全设置为0,清除乱码for (int m = listTagInfor[i].index*6; m < listTagInfor[i].index*6 + 6; m++){UIVertex tempVertex = listUIVertex[m];tempVertex.uv0 = Vector2.zero;listUIVertex[m] = tempVertex;}InlineSpriteInfor tempSprite = new InlineSpriteInfor();//如果图片在第一个位置,则计算他的位置为文本的初始点位置//否,则返回上一个字符的第三个UIVertex的position,这是根据他的顶点的绘制顺序所获得的if (listTagInfor[i].index == 0){Vector2 anchorPivot = GetTextAnchorPivot(alignment);Vector2 rectSize = rectTransform.sizeDelta;tempSprite.textpos = -rectSize / 2.0f + new Vector2(rectSize.x * anchorPivot.x,rectSize.y*anchorPivot.y- listTagInfor[i].size.y);}elsetempSprite.textpos = listUIVertex[listTagInfor[i].index * 6 - 4].position;//设置图片的位置tempSprite.vertices = new Vector3[4];tempSprite.vertices[0] = new Vector3(0, 0, 0) + tempSprite.textpos;tempSprite.vertices[1] = new Vector3(listTagInfor[i].size.x, listTagInfor[i].size.y, 0) + tempSprite.textpos;tempSprite.vertices[2] = new Vector3(listTagInfor[i].size.x, 0, 0) + tempSprite.textpos;tempSprite.vertices[3] = new Vector3(0, listTagInfor[i].size.y, 0) + tempSprite.textpos;//计算其uvRect spriteRect = m_spriteAsset.listSpriteInfor[0].rect;for (int j = 0; j < m_spriteAsset.listSpriteInfor.Count; j++){//通过标签的名称去索引spriteAsset里所对应的sprite的名称if (listTagInfor[i].name == m_spriteAsset.listSpriteInfor[j].name)spriteRect = m_spriteAsset.listSpriteInfor[j].rect;}Vector2 texSize = new Vector2(m_spriteAsset.texSource.width, m_spriteAsset.texSource.height);tempSprite.uv = new Vector2[4];tempSprite.uv[0] = new Vector2(spriteRect.x / texSize.x, spriteRect.y / texSize.y);tempSprite.uv[1] = new Vector2((spriteRect.x + spriteRect.width) / texSize.x, (spriteRect.y + spriteRect.height) / texSize.y);tempSprite.uv[2] = new Vector2((spriteRect.x + spriteRect.width) / texSize.x, spriteRect.y / texSize.y);tempSprite.uv[3] = new Vector2(spriteRect.x / texSize.x, (spriteRect.y + spriteRect.height) / texSize.y);//声明三角顶点所需要的数组tempSprite.triangles = new int[6];listSprite.Add(tempSprite);}//清除<quad />标签的乱码 重新绘制toFill.Clear();toFill.AddUIVertexTriangleStream(listUIVertex);DrawSprite();}/// <summary>/// 绘制图片/// </summary>void DrawSprite(){Mesh m_spriteMesh = new Mesh();List<Vector3> tempVertices = new List<Vector3>();List<Vector2> tempUv = new List<Vector2>();List<int> tempTriangles = new List<int>();for (int i = 0; i < listSprite.Count; i++){for (int j = 0; j < listSprite[i].vertices.Length; j++){tempVertices.Add(listSprite[i].vertices[j]);}for (int j = 0; j < listSprite[i].uv.Length; j++){tempUv.Add(listSprite[i].uv[j]);}for (int j = 0; j < listSprite[i].triangles.Length; j++){tempTriangles.Add(listSprite[i].triangles[j]);}}//计算顶点绘制顺序for (int i = 0; i < tempTriangles.Count; i++){if (i % 6 == 0){int num = i / 6;tempTriangles[i] = 0 + 4 * num;tempTriangles[i + 1] = 1 + 4 * num;tempTriangles[i + 2] = 2 + 4 * num;tempTriangles[i + 3] = 1 + 4 * num;tempTriangles[i + 4] = 0 + 4 * num;tempTriangles[i + 5] = 3 + 4 * num;}}m_spriteMesh.vertices = tempVertices.ToArray();m_spriteMesh.uv = tempUv.ToArray();m_spriteMesh.triangles = tempTriangles.ToArray();if (m_spriteMesh == null)return;m_spriteCanvasRenderer.SetMesh(m_spriteMesh);m_spriteGraphic.UpdateMaterial();}}[System.Serializable]
public class SpriteTagInfor
{/// <summary>/// sprite名称/// </summary>public string name;/// <summary>/// 对应的字符索引/// </summary>public int index;/// <summary>/// 大小/// </summary>public Vector2 size;
}[System.Serializable]
public class InlineSpriteInfor
{// 文字的最后的位置public Vector3 textpos;// 4 顶点 public Vector3[] vertices;//4 uvpublic Vector2[] uv;//6 三角顶点顺序public int[] triangles;
}

4.开始测试效果,创建一个InlieText组件,并在其组件下,添加一个SpriteGraphic组件,输入文字加标签测试

InlieTex组件:

SpriteGraphic组件:

文字测试:

5.做了一个聊天测试:

6.同时在测试的时候就发现了些许bug,这里并不想写出来,有兴趣的可以一起修改讨论。

工程使用的unity版本为unity的版本为:5.3.1f1

最后给出工程链接:https://code.csdn.net/qq992817263/uguitextpro/tree/master

Unity UGUI图文混排源码(二)相关推荐

  1. Unity UGUI图文混排源码(三) -- 动态表情

    这里是根据图文混排源码(二)进一步修改的,其他链接也不贴了,就贴一个链接就好了,第一次看这文章的同学可以先去看看其他几篇文章 Unity UGUI图文混排源码(二):http://blog.csdn. ...

  2. Unity UGUI图文混排源码--优化版

    前言 因为有不少同学反应在使用图文混排的时候,出现很大的性能问题,导致画面帧率不稳定,甚至极低.博主对此非常抱歉,当时仅凭兴趣,在一个个功能上不断叠加,几乎没有考虑到性能的优化.这次有几天的空余时间, ...

  3. Unity UGUI图文混排(六) -- 超链接

    图文混排更新到超链接这儿,好像也差不多了,不过就在最后一点,博主也表现得相当不专业,直接整合了山中双木林同学提供的超链接的解决方案,博主甚至没来得及细看就直接复制了,但感觉还是挺好用的. 博主已经将超 ...

  4. Unity UGUI图文混排(七) -- 下划线

    之前更新超链接的时候,忘了搭配实现一个下划线的功能,这篇文章就是来补上这一个功能,时间有点长,一方面没有很好的思路,一方面也没多少时间. 先在网上收集了一下下划线的实现操作,一种是在文本下再创建一个文 ...

  5. Unity TextMeshPro图文混排

    笔者最近项目使用TextMeshPro完成图文混排的需求,以及图文超链接,总的来说功能很强大,没遇到什么坑. 这里记录一下图文混排实现的基本流程流程. 制作需要混排图片.asset文件 方式一 使用图 ...

  6. UGUI图文混排插件Text Mesh Pro

    Text Mesh Pro插件下载地址: https://github.com/UnityTechnologies/Test_ShaderGraphBlog 插件在线文档: http://digita ...

  7. Unity UGUI实现图文混排

    目前在unity实现图文混排的好像都是通过自定义字体然后在文本获取字符的位置,用图片替换掉图片标签,这样对于支持英文来说,并没有什么影响.然后对于中文来说就是一个相当麻烦的事了,毕竟图文混排多用于游戏 ...

  8. android多媒体图文混排,android图文混排

    背景 最近我们的产品来了个新的模块,给学生做题提高成绩的.需求如下: 支持单选.多选.填空题 支持图片文字混排 输入框有交互,排版精致美观 为了体验优化,不能使用网页实现效果 思路分析 我们的图文混排 ...

  9. 【游戏开发实战】Unity UGUI Text图文混排(聊天文字混表情),支持动态表情,出招吧表情帝

    文章目录 一.前言 二.最终效果 三.具体使用 1.导入表情素材 2.设置图片格式 3.生成表情图集 4.UI-EmojiFont.shader 5.材质球 四.测试 五.结束语 一.前言 点关注不迷 ...

最新文章

  1. java管理系统用怎么框架做_java 使用servlet做学生管理系统(无框架)
  2. Free Download Top 100 Hacking Books
  3. linux手动生成dump文件权限不足_来玩一玩Linux常见命令~
  4. HDU Problem - 4289 Control(最大流)
  5. 加密机工作原理_三相异步电动机的工作原理
  6. 录音机 在launcher中显示_「 腾讯 微信事业部 社招二面」——一个APP从启动到主页面显示经历了哪些过程?...
  7. 以鶸ice为例,手撸一个解释器(一)明确目标
  8. 13款宝马x5质量到底怎么样_2020款宝马X5价格新变化 都市越野绝佳之选_搜狐汽车...
  9. eclipse 设置虚拟机内存(可用)
  10. SpringMVC学习(四)结果跳转的方式:转发和重定向
  11. 算术编码数据压缩Matlab报告,用matlab实现算术编码
  12. PLC供电系统电源模块的选择
  13. 创建数据库表提示Working outside of application context.
  14. Lipschitz 条件或者Lipschitz连续
  15. 授权服务是如何颁发授权码和访问令牌的?
  16. 解密宝典——十招教你学会软件破解
  17. 韩信点兵(Hanxin)(C++)
  18. RS232电平 RS485电平 RS422电平
  19. Drools Accumulate 语法解析及使用
  20. Arista EOS log level

热门文章

  1. 倍控3865U软路由安装网络行为管控插件Fros
  2. 倾一世烟花,爱已成痴
  3. thinksnsv4.6运行php,SNS社交系统“ThinkSNS V4.6”活动应用功能详解及应用场景举例...
  4. Map--7-14 电话聊天狂人(25 分)
  5. 酒店在线订房小程序开发解决方案
  6. 0基础学Linux-从小白到大牛(3)Linux命令
  7. 毕业生之瞳——《技术之瞳——叩开阿里之门之在线笔试》
  8. linux time 查看cp,Linux命令:cp、time、cut、awk 、獲取文件大小命令
  9. FPV无人机集训召集令~
  10. win10怎么连接宽带