【转】NGUI研究院之为什么打开界面太慢(十三)
NGUI打开界面太慢了,起初一直以为是unity的问题,最近经过我的全面测试我发现这和unity没有关系。一般一个比较复杂的界面大概需要150个GameObject 或者 UISprite 。我用NGUI直接载入发现竟然需要250多毫秒,仅仅只是两张小图。同样的GameObject 我用unity2d的Sprite载入只需要70多毫米,可见Unity2d的效率要比NGUI高多少。。我可能说的不完全对,因为U3D是闭源的,我只能猜测。
在普及一下基础知识。
C#
|
1
2
|
GameObject go = GameObject.Instantiate(Resources.Load(“prefabName”)) as GameObject;
go.AddComponent<Test>();
|
我想上面这一行代码,大家应该再也熟悉不过了。实例化一个Prefab,然后给它身上帮一条脚本。如下图所示,我用的是 红米作为测试机器。实例化对象我们可以拆成4部分。我用NGUI加载了150个UISpirte = 41 + 4 + 30 + 194 = 269毫秒,一般打开界面超过500毫秒的话用户就会明显感觉卡顿了。而我这个仅仅是一张图而已,事实证明NGUI加载太慢了,到底为什么这么慢?

1.Resources.Load
Resources.Load是一个”同步”耗时操作,Unity内部维护了资源的内存池,但是调用Load的时候Unity会自动的把Prefab上所引用的资源在加入内存池,它不会重复加载资源。也就是说当你加载相同的UIAtlas的时候,只会第一次比较卡。你可以试试一些线上的unity游戏,一般第一次打开某界面的时候要比以后打开此界面时间长一些。
2.GameObject.Instantiate
很多人认为加载慢的原因罪魁祸首是Instantiate()。其实我告诉你它的时间反而是最快的,上面的截图我相信就是最好的证明。第一次Instantiate要比以后执行Instantiate要慢一些,可能Unity在做一些特殊处理吧。
3.第一次添加脚本。
添加脚本一般会有两种形式,第一种是通过AddComponent<Script>的形式把脚本添加给游戏对象,还有一种是你的Prefab天生就带着这个脚本。无论哪种加载时间都是一样的。第一次加载脚本要比以后加载慢,我觉得应该是和Resources缓存池的原理一样吧。
4.第二次以后的GameObject.Instantiate 和 AddComponent<Script>
GameObject.Instantiate 就不用说了,它载入很快,这里要详细的说说Script。
对!导致于你界面打开慢的原因就是prefab上绑的脚本,罪魁祸首就是脚本。
AddComponent<Script> 以后 或者 Prefab上预先绑定的脚本。当你GameObject.Instantiate()同步方法执行的时候,并不是把脚本挂上去就完了,而它要等脚本里面的一些方法执行完毕才算结束。
脚本中有两个很典型的方法 Awake 和 OnEnable。当Prefab 用Instantiate()方法载入的时候,它的脚本必须执行完Awake和OnEnable两个方法以后才算完整载入。那么如果你的脚本这里面有一些耗时操作,那么必然载入会慢了。。
C#
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
void Awake()
{
for(int i =0 ;i <1000; i++)
{
}
}
void OnEnable()
{
for(int i =0 ;i <1000; i++)
{
}
}
|
如果你在Awake() 或者 OnEnable()方法里面继续去实例化对象,继续绑定脚本,那么依然还需要把新实例化对象的 Awake()和 OnEnable()方法执行完毕才会结束。。。
这里并没有完,还有一个地方也会引起打开界面慢。代码中用Pubilc 声明的对象,然后是在编辑器拖拽赋值。
C#
|
1
|
public GameObject go;
|
拖拽赋值,如果是资源很大的话unity需要load ,然而load就是一个同步耗时操作,那么它也会影响打开界面的时间。
如下图所示,NGUI里面 UISprite UITexture UILabe 这三个脚本上面都有 public 绑定的对象。 NGUI打开界面慢的罪魁祸首就在这里,我尝试把public 绑定的代码全部取消, 发现 20几毫秒 就载入完成了。。。 知道原因了,但是我们也没办法,因为不能随便乱改它的代码。。

一定要把一个界面的所有GameObject做成一个Prefab,有些人不想用unity的Prefab,想通过一种规则程序运行时利用GameObject.Instantiate() 和 AddComponent<Script> 来生成界面的树状结构。我做过测试如果单纯加载一个Prefab和 代码动态生成对应树状结构 前者要比后者快30%左右。所以如果做UI编辑器的话,一定要先把Prefab生成出来,一定要只加载一个Prefab。
至于Unity 的Sprite载入 为什么要比NGUI的Sprite载入快,那么唯一可以解释的就是Unity可能后台用的是C语言,而NGUI用的是纯C#,从执行效率上C会快很多,所以我们还是早日期待Unity可以自身完美的解决做界面的问题。unity4.6预览版看起来很赞,不过我更期待unity5的到来。
最后我们在说说怎么让NGUI打开界面的速度能快一些。
1.修改界面结构,尽可能让界面上绑定UISprite UITexture UILabe这样的游戏对象少一些。
2.如果界面没法拆开,那么就把界面的prefab拆成多个,比如底框是一个Prefab , 内容是一个Prefab ,列表是一个Prefab ,这样打开界面的时候用协同任务 一个一个打开,这样用户就不会感觉到界面卡顿了。。
3.期待您的补充。。
- 本文固定链接: http://www.xuanyusong.com/archives/2799
- 转载请注明: 雨松MOMO 2014年06月20日 于 雨松MOMO程序研究院 发表
这个问题刚好我也遇到了,在一个场景里有几千个的UISprite和UILabel,然后初始化的时候……你懂得,半分钟算快的了,后来找来找去终于知道罪魁祸首了……然后用的是协同程序解决的
对。我也是用协同解决的。。
【转】NGUI研究院之为什么打开界面太慢(十三)的更多相关文章
- [转载来之雨松:NGUI研究院之为什么打开界面太慢(十三)]
本文固定链接: http://www.xuanyusong.com/archives/2799
- 关于 pyspider Web预览界面太小的解决方法
本人最近在学习pyspider时,遇到Web预览界面太小而无法很好的进行开发,于是在网上搜索解决方法. 准备: css代码: body{margin:;padding:;height:%;overfl ...
- 前端嫌弃原生Swagger界面太low,于是我给她开通了超级VIP
缘由 接口文档想必是许多开发小伙伴的噩梦,不仅要写详细,还要及时维护文档与后端代码保持一致,稍有没及时更新接口文档,前端同学肯定会抱怨后端同学给的文档与实际情况不一致. 于是,引入了Swagger组件 ...
- ffmpeg 打开视频流太慢(上)
新版ffmpeg打开网络视频流需要调用avformat_find_stream_info方法,很多朋友会发现调用改方法耗费很多时间造成打开视频流太慢.有两个参数可以减少avformat_find_st ...
- 界面为ScrollView时打开界面会自动滚动到底部之解决方法
开发中遇到了这样的一个问题,界面最外层是ScrollView,然后里面有嵌套了一个ListView还有其他可以获取焦点的View,然后每次打开界面都会自动滚动到最底部,经过一番折腾,发现了一个简单的方 ...
- lua------------------Unity3D研究院编辑器之打开unity不可识别的文件(十三)
Unity3D研究院编辑器之打开unity不可识别的文件(十三) 雨松MOMO [Unity3D拓展编辑器] 围观8597次 9 条评论 编辑日期:2017-03-02 字体:大 中 小 有些特殊 ...
- Android:解决重复打开界面问题
点击界面A按钮,打开界面B,由于startActivity操作是异步执行的,假如在短时间内快速点击按钮,可能会导致打开多个B界面,这个时候可以重写Activity的startActivity事件. p ...
- 【转】NGUI研究院之自适应屏幕(十)
http://www.xuanyusong.com/archives/2536 现在用unity做项目 90%都是用NGUI,并且我个人觉得NGUI应该算是比较成熟的UI插件,虽然他也存在很多问题,但 ...
- NGUI研究院之UISprite和UITexture浅谈
NGUI的三大组件,UILabel.UISprite.UITexture,它们三个同时都继承UIWidget.先回到一个很郁闷的话题上,到底是优化DrawCall还是优化内存. UISprite : ...
随机推荐
- Codeforces Round #346 (Div. 2)
前三题水 A #include <bits/stdc++.h> typedef long long ll; const int N = 1e5 + 5; int main() { int ...
- 模拟 Codeforces Round #288 (Div. 2) A. Pasha and Pixels
题目传送门 /* 模拟水题:给定n*m的空白方格,k次涂色,将(x,y)处的涂成黑色,判断第几次能形成2*2的黑色方格,若不能,输出0 很挫的判断四个方向是否OK */ #include <cs ...
- java工厂模式实例化class
import java.io.*; import java.util.*; interface fruit { public abstract void eat(); } class Apple im ...
- Path形状获取字符串型变量数据
Path形状获取字符串型变量数据: var path = new Path(); path.Data = Geometry.Parse("M 100,200 C 100,25 400,350 ...
- pointers on c (day 1,chapter1)
c语言的优先级 优先级 运算符 名称或含义 使用形式 结合方向 说明 1 [] 数组下标 数组名[常量表达式] 左到右 () 圆括号 (表达式)/函数名(形参表) . 成员选择(对象) 对象.成员名 ...
- ccc 函数中写函数
attackOnTarget: function (atkDir, targetPos) { var self = this; let deg = cc.radiansToDegrees(cc.pAn ...
- word 批量修改表格格式
For i = 1 To ActiveDocument.Tables.Count ActiveDocument.Tables(i).Cell(1, 1).Select With Selection . ...
- ACM 关于521
关于521 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 Acm队的流年对数学的研究不是很透彻,但是固执的他还是想一头扎进去. 浏览网页的流年忽然看到了网上有人用玫 ...
- js+css立体旋转
纯 CSS3 制作可口可乐罐 这个效果相信大家很多人看过了,纯css实现的立体可口可乐罐,看起来相当高大上~ 于是今天我这小菜鸟试着研究下,稍微遗憾的是,没有看到源码,还是直接F12吧,貌似实现也不 ...
- [WP8.1UI控件编程]Windows Phone理解和运用ItemTemplate、ContentTemplate和DataTemplate
2.2.5 ItemTemplate.ContentTemplate和DataTemplate 在理解ItemTemplate.ContentTemplate和DataTemplate的关系的之前,我 ...