UGUI表情系统解决方案

UGUI表情系统解决方案

聊天是游戏中必不可少的功能,发送表情也是聊天系统的一个重要组成部分。笔者的项目中使用UGUI开发UI,在制作表情系统时也遇到了同样的问题,可是UGUI中的Text组件本身并不支持图文混编。为此,笔者提供了一套解决方案,供大家参考。


Unity推荐的方式是使用TextMesh解决混编问题。TextMesh的确可以实现混编,但是却存在和UGUI较难整合的问题(Mask遮罩、自适应等),同时也会因为使用多个材质导致无法使用动态批次合并。网上也有人使用Text+Image的形式来处理图文混编,但是需要解决排序等问题。最好的解决方案还是能让UGUI的Text能够自身支持图文混编。

通过查看UGUI的源代码和其Shader,可以重写Text生成Mesh的方法以及最终渲染的Shader,以此来实现图文混编的功能,后文会为大家一步步介绍实现方法。


◆◆
整合表情图片

请输入图片描述

这是原始的表情资源,按照表情名_序列帧的形式统一命名,然后通过代码打成一张Atlas,为了能够支持动态表情,需要在Shader中使用UV动画,但是因为所有的表情都在一张Atlas中,帧数又不统一,因此需要再生成一张可以标识每一个表情有多少帧的数据贴图。
请输入图片描述
表情和数据Atlas,这两张图片会在最终渲染的Shader中使用。

请输入图片描述
当然还需要生成一张数据表,用户标识表情名和Text替代符的对应关系,以及每一个表情的UV位置。其中Key中的内容就是在Text中的表情替代符,至于为什么使用这种格式会在后面内容介绍。


◆◆
重写Text中生成顶点的方法

这是比较关键的步骤,UGUI中Text生成顶点的规律是每个字符生成4个顶点,构成2个面。例如字符串:这是一个Text,在UGUI中会生成8x4=32个顶点,中文、英文、其他字符都是等价的,只是顶点之间的间距不同。因此可以在将表情替代符中的多个顶点修改成适合表情的4个顶点,使用第二套UV标识这部分顶点引用表情贴图,而非字体贴图。例如一个字符串:这里是表情[

请输入图片描述
读取配置文件,用于后面替换表情符。

请输入图片描述
利用正则表达式找出全部的表情符,并且匹配是否为系统所支持的表情符(上面读取的配置文件)。

请输入图片描述
重新生成顶点位置和UV坐标。


◆◆◆
重写渲染部分

这是最后一步,重写一个Shader用来渲染。相较于原始Shader增添了几个新的属性。
请输入图片描述
其中_EmojiSize表示EmojiTexture每一行拥有几个表情,因为本示例中每一行有4个表情,所以这个位置填写4。其他的属性就不做阐述了。

请输入图片描述
引入第二套uv坐标。

请输入图片描述
VS几乎没多大变化,只是传递第二套UV坐标。

请输入图片描述
PS中先判断第二套UV坐标是否有数值,有数值则表明是表情,从_EmojiTex中绘制,从_EmojiDataTex中读取表情帧数,用于做uv动画。

请输入图片描述
至此,就实现了UGUI的表情系统,可以和原生的其他UGUI控件使用。同时因为只有一个材质,一个Pass,所以也可以进行动态批次合并。

工程代码笔者以上传到自己的Github中,https://github.com/zouchunyi/EmojiText,欢迎大家Clone。


这是侑虎科技第147篇原创文章,感谢作者邹春毅(QQ:442319386,作者博客:https://github.com/zouchunyi)供稿。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:793972859)

同时,作者也是U Sparkle活动参与者,UWA欢迎更多开发朋友加入U Sparkle开发者计划,这个舞台有你更精彩!

  • Unity琐碎(3) UGUI 图文混排解决方案和优化 R11; 94007技术网 发表在 2023年03月31日 回复

    [...]Shader中渲染图片:Uwa UGUI表情系统解决方案 直接再shader中渲染图片,这个方案对于outline、shadow时避免图片也被处理的问题没想到好的方案,就放弃了。[...]

  • Unity琐碎(3) UGUI 图文混排解决方案和优化 R11; 94007技术网 发表在 2023年03月31日 回复

    [...]Shader中渲染图片:Uwa UGUI表情系统解决方案 直接再shader中渲染图片,这个方案对于outline、shadow时避免图片也被处理的问题没想到好的方案,就放弃了。[...]

  • 薛雪 发表在 2018年04月26日 回复

    能单独改变图文混排里面的图片大小吗?现在看的是,图片的宽高是跟着文字的大小变化的,不知道怎么单独的设置图片的大小

  • 李胜如 发表在 2018年04月15日 回复

    表情的大小和间距可以调整吗

  • 李胜如 发表在 2018年04月12日 回复

    表情超过32个的时候,通过key值取到的表情会出错

  • Felix 发表在 2018年03月06日 回复

    有测试过PS的采样性能以及发热吗?if-else分支中各有一次采样,在GPU中并行执行时,这两个分支都会执行

  • leeman 发表在 2018年02月26日 回复

    用了这个方法 有时候会出现 文字花屏的现象,大家有遇到么?

  • 董宸 发表在 2018年02月16日 回复

    看了一下源码……没有对perfect pixel做处理……
    导致打开perfect pixel就变回普通text了 - -

  • 沛权 发表在 2017年03月16日 回复

    我用5.4版本unity,如果把data图删掉,重新build一下,生成data图,发现动态表情播放错了,发现unity导入图片自动压缩问题,可以在unity属性面板改为不压缩,我自己在代码设置就好,遇到这个坑,分享一下。

  • mrzivchu 发表在 2016年12月08日 回复

    大赞!看来我也要努力学习图形渲染学方面的知识了

  • 张洋凡 发表在 2016年11月26日 回复

    为什么重新生成的DATA图集 和源文件的不同了

    • 邹春毅 发表在 2016年11月26日 回复

      每一个32x32的图片只取一个像素生成data图集,在shader中每一个表情都会取在Data图集中的同一点获取帧数。这样做可以减少Data图集的大小。