游戏UI动态加载图片优化
说到UI优化,很多人对其并不以为意,UI的制作无非使用UGUI或者NGUI。UI优化主要是针对图集,还有一些依赖项的优化,针对的是内存优化,上面这些都是关于静态UI的优化,这个是作为程序员都要经历的阶段。其实很多开发者对使用UGUI或者NGUI已经墨守成规了,我们如果真想去优化,其实完全可以自己封装一套UI的底层代码,效率很高的,摒弃了UGUI和NGUI影响效率的代码,自己封装的简单实用,在我的视频课程——飞车竞速
在这个游戏中使用的UI都是自己封装的,游戏 UI底层代码封装如下所示:
这个UI底层封装的是针对我们项目的需求开发的,在这里是给读者拓展一下思路,UI优化并不仅限于图集和图片大小的优化,代码层面也是可以做的。
以上给读者介绍的都是关于静态UI的制作与优化,本篇博客主要是给读者介绍一下关于UI的动态图片优化,首先明白什么是动态加载图片,比如我们创建的角色ICON,还有游戏生成的怪物ICON等等,就是说这些ICON不是事先就有的,而是根据游戏动态加载到场景中的,我们的优化就是针对这些动态加载的ICON去做优化,在程序运行的过程中打图集,下面我们先实现一个2D动作播放的动态图集生成的Demo。
在Unity中如下图所示:
上图就是我们常见的序列帧动画,它的制作方式很多,我们可以事先将其打成图集,按照顺序播放,也可以直接播放,我们接下来实现的是动态的加载,动态的打图集算法。我们实现的思路是首先获取到需要打图集的图片,然后将其按照顺序依次在已创建的空白图片上把序列帧图片粘贴上,同时我们还需要使用一个Json文件记录我们对应图片的信息,这个信息非常重要,它主要目的是帮助我们找到对应的图片,这个信息包含:图片所在位置,图片的宽,高,图片的名字。
这样我们就完成了图集的动态生成,接下来就是逻辑代码的编写了。
第一步:获取动态加载的文件,在这里我们是将其拷贝到一个指定的目录下面,方便我们打图集,这个目录我们自己指定,就是模拟程序运行时动态获取到图片,然后去加载,代码如下:
CopyPasteFoldersAndPNG(Application.dataPath + "/SpriteGenerator/Demos/Sprites", Application.persistentDataPath);string[] files = Directory.GetFiles(Application.persistentDataPath + "/Textures", "*.png");
第二步:定义图集大小,将获取到的图片在图集上进行排列, 核心算法如下:
protected IEnumerator createPack(string savePath = "") {if (savePath != "") {if (deletePreviousCacheVersion && Directory.Exists(Application.persistentDataPath + "/AssetPacker/" + cacheName + "/"))foreach (string dirPath in Directory.GetDirectories(Application.persistentDataPath + "/AssetPacker/" + cacheName + "/", "*", SearchOption.AllDirectories))Directory.Delete(dirPath, true);Directory.CreateDirectory(savePath);}List<Texture2D> textures = new List<Texture2D>();List<string> images = new List<string>();foreach (TextureToPack itemToRaster in itemsToRaster) {WWW loader = new WWW("file:///" + itemToRaster.file);yield return loader;textures.Add(loader.texture);images.Add(itemToRaster.id);}int textureSize = allow4096Textures ? 4096 : 2048;List<Rect> rectangles = new List<Rect>();for (int i = 0; i < textures.Count; i++)if (textures[i].width > textureSize || textures[i].height > textureSize)throw new Exception("A texture size is bigger than the sprite sheet size!");elserectangles.Add(new Rect(0, 0, textures[i].width, textures[i].height));const int padding = 1;int numSpriteSheet = 0;while (rectangles.Count > 0) {Texture2D texture = new Texture2D(textureSize, textureSize, TextureFormat.ARGB32, false);Color32[] fillColor = texture.GetPixels32();for (int i = 0; i < fillColor.Length; ++i)fillColor[i] = Color.clear;RectanglePacker packer = new RectanglePacker(texture.width, texture.height, padding);for (int i = 0; i < rectangles.Count; i++)packer.insertRectangle((int) rectangles[i].width, (int) rectangles[i].height, i);packer.packRectangles();if (packer.rectangleCount > 0) {texture.SetPixels32(fillColor);IntegerRectangle rect = new IntegerRectangle();List<TextureAsset> textureAssets = new List<TextureAsset>();List<Rect> garbageRect = new List<Rect>();List<Texture2D> garabeTextures = new List<Texture2D>();List<string> garbageImages = new List<string>();for (int j = 0; j < packer.rectangleCount; j++) {rect = packer.getRectangle(j, rect);int index = packer.getRectangleId(j);texture.SetPixels32(rect.x, rect.y, rect.width, rect.height, textures[index].GetPixels32());TextureAsset textureAsset = new TextureAsset();textureAsset.x = rect.x;textureAsset.y = rect.y;textureAsset.width = rect.width;textureAsset.height = rect.height;textureAsset.name = images[index];textureAssets.Add(textureAsset);garbageRect.Add(rectangles[index]);garabeTextures.Add(textures[index]);garbageImages.Add(images[index]);}foreach (Rect garbage in garbageRect)rectangles.Remove(garbage);foreach (Texture2D garbage in garabeTextures)textures.Remove(garbage);foreach (string garbage in garbageImages)images.Remove(garbage);texture.Apply();if (savePath != "") {File.WriteAllBytes(savePath + "/data" + numSpriteSheet + ".png", texture.EncodeToPNG());File.WriteAllText(savePath + "/data" + numSpriteSheet + ".json", JsonUtility.ToJson(new TextureAssets(textureAssets.ToArray())));++numSpriteSheet;}foreach (TextureAsset textureAsset in textureAssets)mSprites.Add(textureAsset.name, Sprite.Create(texture, new Rect(textureAsset.x, textureAsset.y, textureAsset.width, textureAsset.height), Vector2.zero, pixelsPerUnit, 0, SpriteMeshType.FullRect));}}OnProcessCompleted.Invoke();}
代码虽然比较长,但是理解起来不难,没有用任何算法,它只是按照顺序去排列,然后保存成图集和json文件,最终的图集如下所示:
Json文件如下所示:
{"assets":[{"x":0,"y":0,"width":286,"height":387,"name":"walking0004"},{"x":0,"y":388,"width":286,"height":387,"name":"walking0005"},{"x":0,"y":776,"width":286,"height":387,"name":"walking0003"},{"x":0,"y":1164,"width":286,"height":387,"name":"walking0001"},{"x":0,"y":1552,"width":286,"height":387,"name":"walking0002"},{"x":287,"y":0,"width":286,"height":387,"name":"walking0006"},{"x":287,"y":388,"width":286,"height":387,"name":"walking0010"},{"x":287,"y":776,"width":286,"height":387,"name":"walking0011"},{"x":287,"y":1164,"width":286,"height":387,"name":"walking0009"},{"x":287,"y":1552,"width":286,"height":387,"name":"walking0007"},{"x":574,"y":0,"width":286,"height":387,"name":"walking0008"}]}
接下来就是播放动画了,也就是最后一步。
第三步:播放动画逻辑代码实现如下:
IEnumerator LoadAnimation() {Sprite[] sprites = assetPacker.GetSprites("walking");int j = 0;while (j < sprites.Length) {anim.sprite = sprites[j++];yield return new WaitForSeconds(0.1f);if (j == sprites.Length)j = 0;}}
实现效果如下所示:
这样就完成了动态图集的生成,当然我们还可以生成大的图集,这个一般在端游中使用的,效果如下图所示:
以上是关于动态图集的生成,我们测试了一下实现500个矩形,类似500个小ICON,花费时间是8ms,非常理想。该技术可以应用到项目开发中。。。。。。
项目下载地址:链接:https://pan.baidu.com/s/1bV6hepy2H6t1Xnzg88JOdg 密码:tybj
游戏UI动态加载图片优化相关推荐
- Delphi FastReport动态加载图片
Delphi FastReport动态加载图片 2011-01-06 作者:李海彬 阅读:684 以前用FastReport制作报表,从来没有打印过图片,这段时间做了个打印个人简历的 ...
- vue+elementui 中src动态加载图片的时候不起作用
vue+elementui 中src动态加载图片的时候不起作用 代码如下: <el-table-column align="center" label="宠物图片& ...
- vue 动态加载图片路径报错解决方法
vue 动态加载图片路径报错解决方法 参考文章: (1)vue 动态加载图片路径报错解决方法 (2)https://www.cnblogs.com/qingcui277/p/8930507.html ...
- jQuery页面滚动 动态加载图片等元素
相信大家见过好多随着页面滚动,动态加载图片等元素的网站,我也是,以前见了好多,只是没时间去研究,今天晚上有空,百度了一下找了一个jquery插件,作者张鑫旭,效果挺好,代码也很简单,使用更方便,废话不 ...
- 解决问题:swiper动态加载图片后无法滑动
解决问题:swiper动态加载图片后无法滑动 参考文章: (1)解决问题:swiper动态加载图片后无法滑动 (2)https://www.cnblogs.com/yangguoe/p/9857398 ...
- html5动态加载图片和加载视频
这两在做一个动态加载图片的东西,有点类似QQ发说说里面附带图片的那种,经过测试可以任意添加.删除,然后该删除的位置被后一位自动填充,还有一个bug,就是最后一个图片的控件没做处理,删掉最后一个就会导致 ...
- RecyclerView使用 及 滑动时加载图片优化方案
RecyclerView使用 及 滑动时加载图片优化方案 简述 本篇博文主要给大家分享关于RecyclerView控件的使用及通过继承RecyclerView来实现滑动时加载图片的优化方案,也同样能解 ...
- 动态加载图片,实现瀑布流效果
瀑布流 1.瀑布流 瀑布流,可以有多列,每一列的高度可以不相同,但是宽度必须一样: 排列的方式是,从左往右排列,哪一列总高度最小,就优先排序,把图片放在这一列. 这样排完所有的图片后,可以保证每一列的 ...
- viewer动态加载图片第一次点击预览图片失败的问题
如果您搜到这篇文章的话,那估计您遇到跟我一样的问题了. 众所周知,每一个插件都有很多坑,比如说市面上比较火爆的 图片浏览插件viewer,有js版本和jqery版本的,尽管这两个版本不一样,但是大同小 ...
最新文章
- AI 芯片的分类及技术
- ubuntu设置自启动服务程序
- 如何搭建企业局域网共享
- Ubuntu 搭建 GitLab 笔记 ***
- 【数据结构的魅力】001.认识复杂度二分法异或运算
- 黑马程序员全套Java教程_Java基础入门视频教程零基础自学Java必备教程视频讲义(3)
- 树莓派与阿里云服务器进行socket通信
- 果然天蝎座的人积分落户最容易...
- 周记——20151221
- ctab提取dna流程图_CTAB法提取植物DNA原理以及步骤
- 使用VNC连接树莓派4b如何全屏1080p分辨率,一次更改永久有效!
- 基于单片机的语音风扇的设计与实现
- 追爱系列电影电视剧书籍
- 前端切图案例课程一则-姜威-专题视频课程
- 导出百度网盘共享文件库目录清单的脚本
- 本周言论 之 C2C模式
- 网页版ASN1解码工具使用教程
- java获取屏幕_抓取当前屏幕信息
- Android 9(Pie) 新特性介绍
- 每年降本100万元+!企业研发管理该怎么做?
热门文章
- 自己定义头像处理,轻巧有用,非常多强大的小技巧在里面哦,快来赞美我一下吧^_^...
- kali安装无线网卡安装过程,RTL8812BU网卡,其他网卡安装同理,更换驱动文件即可
- 苹果原全球副总裁戈峻入职天九共享集团
- android listview qq,Android中使用listview实现qq/微信好友列表
- VSCode 搜索所有中文
- 软件开发常见模型(瀑布模型、V模型、W模型、敏捷开发模型)
- 《黑客攻防技术宝典Web实战篇》.Dafydd.Stuttard.第2版中文高清版pdf
- 小程序苹果手机地图授权问题
- redis构建微博(redis应用构建篇)
- Android闲鱼版本大全,闲鱼下载2021安卓最新版_手机app官方版免费安装下载_豌豆荚...