UGUI表情系统解决方案
在游戏中,聊天是一项必不可少的功能,而发送表情则是聊天系统的重要组成部分。在笔者参与的项目中,采用UGUI进行UI开发,在制作表情系统时遇到了一个问题:UGUI中的Text组件本身并不支持图文混编。为了解决这一问题,笔者提供一套解决方案,供大家参考。
现有解决方案分析
Unity推荐使用TextMesh解决图文混编问题。TextMesh确实能够实现混编功能,然而它与UGUI较难整合,比如在处理Mask遮罩、自适应等方面存在困难,同时由于使用多个材质,无法进行动态批次合并。网上也有人采用Text + Image的形式处理图文混编,但这种方式需要解决排序等问题。因此,让UGUI的Text自身支持图文混编是较为理想的解决方案。
实现思路概述
通过查看UGUI的源代码及其Shader,我们可以重写Text生成Mesh的方法以及最终渲染的Shader,以此实现图文混编功能。下面将逐步介绍具体的实现方法。
整合表情图片
表情资源命名与打包
原始的表情资源需按照“表情名_序列帧”的形式统一命名,然后通过代码将这些表情资源打成一张Atlas。为了支持动态表情,需要在Shader中使用UV动画。但由于所有表情都在一张Atlas中,且各表情的帧数不统一,所以需要再生成一张数据贴图,用于标识每一个表情的帧数。
关键贴图与数据表
表情Atlas和数据Atlas这两张图片将在最终渲染的Shader中使用。此外,还需要生成一张数据表,用于标识表情名和Text替代符的对应关系,以及每个表情的UV位置。数据表中Key的内容就是在Text中使用的表情替代符,后续会详细介绍采用这种格式的原因。
重写Text中生成顶点的方法
这是实现图文混编的关键步骤。在UGUI中,Text生成顶点的规律是每个字符生成4个顶点,构成2个面。例如,对于字符串“这是一个Text”,在UGUI中会生成8 x 4 = 32个顶点,无论是中文、英文还是其他字符,每个字符都会生成4个顶点,只是顶点之间的间距有所不同。
具体操作步骤如下:
- 读取配置文件:读取之前生成的配置文件,用于后续替换表情符。
- 匹配表情符:利用正则表达式找出字符串中所有的表情符,并与配置文件中系统支持的表情符进行匹配。
- 重新生成顶点和UV坐标:将表情替代符中的多个顶点修改为适合表情显示的4个顶点,并使用第二套UV来标识这部分顶点引用的是表情贴图,而非字体贴图。
重写渲染部分
这是实现UGUI表情系统的最后一步,需要重写一个Shader用于渲染。相较于原始Shader,新的Shader增添了几个新的属性。
Shader新属性说明
其中,_EmojiSize
表示 EmojiTexture
每一行拥有的表情数量。在本示例中,每一行有4个表情,因此该属性的值填写为4。其他属性在此不做详细阐述。
坐标处理与渲染逻辑
在新的Shader中,需要引入第二套UV坐标。Vertex Shader(VS)部分几乎没有太大变化,主要是传递第二套UV坐标。Pixel Shader(PS)中,首先判断第二套UV坐标是否有数值,如果有数值,则表明当前处理的是表情,从 _EmojiTex
中进行绘制,并从 _EmojiDataTex
中读取表情帧数,用于实现UV动画。
总结
通过以上步骤,我们成功实现了UGUI的表情系统。该系统可以与原生的其他UGUI控件配合使用,并且由于只使用了一个材质和一个Pass,还可以进行动态批次合并,提高渲染效率。