【Unity3D游戏开发】基于NGUI的表情图文混排解决方案 (二二)

2024-03-24 19:32

本文主要是介绍【Unity3D游戏开发】基于NGUI的表情图文混排解决方案 (二二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

使用 unity3d也有两年时间了,最近比较闲,有功夫梳理一下去年一年来学到以及用到的知识,分享给大家,顺便方便自己查阅。如有错误以及不当的地方,欢迎各位指正。谢谢。
去年五月份的时候,刚加入项目不久,老大交给我一个关于聊天系统任务,期初觉得应该很容易,但是看了文档之后,瞬间头都大了_(:з」∠)_,因为需要支持表情!当时Unity3D版本4.3.x,NGUI版本3.5x,当时版本的NGUI已经支持动态字体,我们的项目也不例外,赶忙就用上了。但是,表情的 问题要怎么解决?总不能用颜文字吧(╯‵□′)╯︵┻━┻。如果不用动态字体而使用自己制作的图集字体,倒是可以将表情图片打进字库解决。但是既然我们已经用了动态字体,我就只能另想办法了。
经过两天的研究实践,最终找到一个能够实现的解决办法。主要思路是:
1.定义一个标准行宽度,以此作为基准对文字以及表情进行分行处理;
2.使用特殊符号标记表情(例如:#e001),遍历字符串,凡遇到表情标记则将之与位置记录下来,并使用“ ”(空格,具体数量视表情大小而定)将特殊标记替换。
3.使用Vector3记录以上信息,x为表情的横坐标,y为表情所在行数(即纵坐标),z为表情的ID,即刚才的001,以此确定是哪个表情。使用一个List将所有表情信息存放起来,显示时遍历List即可。
有了以上基本思路,下面只要编码实现,但是在编码过程中还是不可避免的问题——如何得到一段文字的长度?这时,就需要用到一个NGUI封装的一个方法NGUIText.CalculatePrintedSize传入参数为string,返回一个Vector2,表示这段文字的长和宽。下面是核心代码。

[code]csharpcode:

protected void CalculateExpressionPos(ref string text)
{NGUIText.finalSize = m_chatInput.label.defaultFontSize;//设置当前使用字体大小lineList.Clear();int row = 0;int textWidth = 0;int lastStartIndex = 0;string curLine = "";int length = text.Length;for (int i = 0; i < length; i++){ if (text[i] == '#' && i + 4 < length && text[i + 1] == 'e'){string eName = text.Substring(i + 2, 3);int eIndex = 0;Vector3 ePos = Vector3.zero;if (int.TryParse(eName, out eIndex)){float fx = 0;text = text.Remove(i, 5);text = text.Insert(i, space);//space = "       ";length = text.Length;//这里的CalculatePrintedSize是重载过的,//与原本方法相比多的一个参数自定义行款,替换原方法中的rectWidth即可textWidth = Mathf.RoundToInt(NGUIText.CalculatePrintedSize(text.Substring(lastStartIndex, i - lastStartIndex),BASELINEWIDTH + 30).x);//BASELINEWIDTH为标准行宽度,30是根据表情大小确定的,//这里的表情大小是30*30if (textWidth > BASELINEWIDTH - 30)         {curLine = text.Substring(lastStartIndex, i - lastStartIndex + 1);lineList.Add(curLine);if (textWidth <= BASELINEWIDTH - 15 ||textWidth >= BASELINEWIDTH)//行末尾不够需换行{fx = 0;row++;lastStartIndex = i;ePos.x = fx - m_offsetX;ePos.y = row;ePos.z = eIndex;}else   //行末尾足够不需换行{fx = textWidth;lastStartIndex = i + space.Length;ePos.x = fx - m_offsetX;ePos.y = row;ePos.z = eIndex;row++;}}else{fx = textWidth;ePos.x = fx - m_offsetX;ePos.y = row;ePos.z = eIndex;}}if (eIndex != 0){eList.Add(ePos);}if (!expInLine.ContainsKey(row))        //有表情无表情行,以此确定行间距{expInLine.Add(row, true);}}else      //记录换行起始Index{if (i - lastStartIndex < 0) continue;float curWidth = Mathf.RoundToInt(NGUIText.CalculatePrintedSize(text.Substring(lastStartIndex, i - lastStartIndex + 1),BASELINEWIDTH + 30).x);if (curWidth > BASELINEWIDTH){curLine = text.Substring(lastStartIndex, i - lastStartIndex + 1);lineList.Add(curLine);lastStartIndex = i + 1;row++;}if (i == length - 1){if (i - lastStartIndex < 0) continue;curLine = text.Substring(lastStartIndex, i - lastStartIndex + 1);lineList.Add(curLine);}}}
}
      经过以上处理,输出的lineList即为聊天内容,eList为表情信息,expInLine字典存放每行是否存在表情信息。将表情图标打入一个图集,命名为001_1、001_2。。。在显示表情时使用UISpriteAnimation脚本可实现动态表情。最终效果如下:

原文链接: http://www.manew.com/blog-3649-2595.html
参考文章: NGUI研究院之有点坑爹的图文混排(十四)

这篇关于【Unity3D游戏开发】基于NGUI的表情图文混排解决方案 (二二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/842564

相关文章

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决

SpringBoot开发中十大常见陷阱深度解析与避坑指南

《SpringBoot开发中十大常见陷阱深度解析与避坑指南》在SpringBoot的开发过程中,即使是经验丰富的开发者也难免会遇到各种棘手的问题,本文将针对SpringBoot开发中十大常见的“坑... 目录引言一、配置总出错?是不是同时用了.properties和.yml?二、换个位置配置就失效?搞清楚加

SpringSecurity显示用户账号已被锁定的原因及解决方案

《SpringSecurity显示用户账号已被锁定的原因及解决方案》SpringSecurity中用户账号被锁定问题源于UserDetails接口方法返回值错误,解决方案是修正isAccountNon... 目录SpringSecurity显示用户账号已被锁定的解决方案1.问题出现前的工作2.问题出现原因各

Python中对FFmpeg封装开发库FFmpy详解

《Python中对FFmpeg封装开发库FFmpy详解》:本文主要介绍Python中对FFmpeg封装开发库FFmpy,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、FFmpy简介与安装1.1 FFmpy概述1.2 安装方法二、FFmpy核心类与方法2.1 FF

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

使用Python开发一个现代化屏幕取色器

《使用Python开发一个现代化屏幕取色器》在UI设计、网页开发等场景中,颜色拾取是高频需求,:本文主要介绍如何使用Python开发一个现代化屏幕取色器,有需要的小伙伴可以参考一下... 目录一、项目概述二、核心功能解析2.1 实时颜色追踪2.2 智能颜色显示三、效果展示四、实现步骤详解4.1 环境配置4.