今天来说说一直都让我在项目中头疼的其中一个问题,NGUI 的scrollView 列表性能问题,实现循环使用item减少性能上的开销。

希望能够给其他同学们使用和提供一个我个人的思路,这个写的不是太完美,目前我在项目中使用了,希望大神能够给更多的建议来优化scrollView.

思   路:通过调整item位置来实现item循环使用,在通过delegate来实现数据刷新

功   能:

SetGrid(int imax, ScrollGridSetItem sc)
NextIndex()
PreIndex()
GotoIndex(int index)
ClearChild()

上代码:

/***
****************** scrollView 循环 item 减少性能消耗 ************
*@2015/03/31
*@author fastHro
*
*基于NGUI Version 3.7.7
*使用说明:在scrollView 下新建空物体,然后把此脚本挂在上面然后设置相关属性.
*注意:scrollGrid 下不需要有item ,由脚本自动创建关联的item
* 刷新item数据通过 委托函数scrollGridSetItem 来设置
*
*/
using UnityEngine;
using System.Collections; public class ScrollGrid : MonoBehaviour {
public delegate void ScrollGridSetItem(Transform[] trans, int start, int end);
/** @index -1 start, 0 start and end, 1 end, 2 center */
public delegate void ScrollGridMessage(int index);
private ScrollGridSetItem scrollGridSetItem;
private ScrollGridMessage scrollGridMessage;
#region 外部数据
/** 最多显示几个 */
public int defaultShowMaxLine;
/** 默认生成几个 */
public int defaultMaxLine;
/** 每一行的间距 */
public int space;
/** 每一行的size */
public Vector2 size; /** gotoIndex 速率 */
public float autoVelocity = 8f;
/** 当数据个数小于defaultMaxLine 列表是否可以移动 */
public bool moveScrollViewLessMaxLine = true;
/** 每次滑动之后是否使item显示在中心 */
public bool centerScrollViewOnChild = false;
#endregion #region 内部数据
private int indexStar = ;
private int indexEnd = ;
private int indexMax = ;
private Vector3 panelPos = Vector3.zero;
private int lastIndex = ;
private int showStartIndex = ;
#endregion #region scrollView
private UIPanel panel;
private UIScrollView sView;
/** 列表的 cliping size */
public Vector2 vSize;
/** 列表移动方式 */
private UIScrollView.Movement movement;
private Transform panelTransfrom;
#endregion #region item
public GameObject ItemPrefab;
private Transform[] itemTrans;
#endregion void Awake()
{
sView = transform.GetComponentInParent<UIScrollView> ();
panel = sView.transform.GetComponentInParent<UIPanel> ();
panelTransfrom = panel.gameObject.transform;
} #region init
/** 初始化设置 */
public void SetGrid(int imax, ScrollGridSetItem sc)
{
if (!moveScrollViewLessMaxLine) {
if(imax < defaultShowMaxLine)
{
sView.enabled = false;
}
}
if (defaultMaxLine > imax) {
defaultMaxLine = imax;
}
initGrid ();
indexMax = imax;
scrollGridSetItem = sc;
if (scrollGridSetItem != null) {
scrollGridSetItem(itemTrans, indexStar, indexEnd);
}
SetMessage ();
} public void SetGrid(int imax, ScrollGridSetItem sc, ScrollGridMessage sm)
{
scrollGridMessage = sm;
SetGrid (imax, sc);
} /** 向后滑动一格 */
public void NextIndex()
{
int ix = GetShowStartIndex ();
//Debug.Log ("next = " + ix);
GotoIndex (ix + );
} /** 向前滑动一格 */
public void PreIndex()
{
int ix = GetShowStartIndex ();
//Debug.Log ("pre = " + ix);
GotoIndex (ix - );
} /**直接跳到指定位置*/
public void GotoIndex(int index)
{
if (index < ) {
return;
}
if (index > indexMax - defaultShowMaxLine) {
return;
}
float ip = GetPanelPositionByIndex (index);
ip = Mathf.Abs (ip);
Vector3 v3 = Vector3.zero;
Vector2 v2 = Vector2.zero; if(movement == UIScrollView.Movement.Horizontal)
{
v3.x = panel.clipSoftness.x - ip;
v2.x = ip + panel.clipSoftness.x;
if(panelTransfrom.localPosition.x == ip)
{
return;
}
}
else if(movement == UIScrollView.Movement.Vertical){
v3.y = ip - panel.clipSoftness.y;
v2.y = -ip + panel.clipSoftness.y;
if(panelTransfrom.localPosition.y == ip)
{
return;
}
} SpringPanel.Begin (sView.panel.cachedGameObject, v3, autoVelocity);
} /** 初始化 */
void initGrid()
{
ClearChild (); itemTrans = new Transform[defaultMaxLine];
for (int i = ; i < defaultMaxLine; i++) {
itemTrans[i] = CreatItemTransfrom(i);
} movement = sView.movement; sView.onDragStarted = onDragStarted;
sView.onDragFinished = onDragFinished;
sView.onMomentumMove = onMomentumMove;
sView.onStoppedMoving = onStoppedMoving; /** 初始化位置 */
ResetPostion (); /** 初始化数据 */
indexStar = ;
indexEnd = defaultMaxLine - ;
indexMax = ;
panelPos = Vector3.zero;
lastIndex = ;
showStartIndex = ;
if (scrollGridSetItem != null) {
scrollGridSetItem(itemTrans, indexStar, indexEnd);
}
SetMessage();
ResetScrollPanelPosition ();
} void ResetPostion()
{
float fristCoord = ;
bool hasFristCoord = false;
Vector3 np = Vector3.zero;
float vp = ;
float ip = ;
float fp = ;
if(movement == UIScrollView.Movement.Horizontal)
{
vp = vSize.x;
ip = size.x;
}else if(movement == UIScrollView.Movement.Vertical)
{
vp = vSize.y;
ip = size.y;
}
for(int i = ; i < itemTrans.Length; i++)
{
if(!hasFristCoord)
{
fristCoord = vp / 2.0f - ip / 2.0f;
if(fristCoord > vp / 2.0f)
{
fristCoord = vp / 2.0f;
}
hasFristCoord = true;
fp = fristCoord;
}else{
fp = fristCoord - (ip + space) * i;
}
if(movement == UIScrollView.Movement.Horizontal)
{
np.x = -fp;
}else if(movement == UIScrollView.Movement.Vertical)
{
np.y = fp;
}
itemTrans[i].localPosition = np;
}
}
#endregion #region switch Item
void SwitchItem(int id)
{
indexStar = id;
//Debug.Log("indexStar : " + indexStar.ToString());
if(movement == UIScrollView.Movement.Horizontal)
{
//Debug.Log("indexStar : " + indexStar.ToString());
//Debug.Log("stop : " + (indexMax - defaultMaxLine).ToString());
if(indexStar > )
{
indexStar = ;
return;
}
if(indexStar < -(indexMax - defaultMaxLine))
{
indexStar = indexMax - defaultMaxLine;
return;
}
indexStar = Mathf.Abs(indexStar);
}else if(movement == UIScrollView.Movement.Vertical)
{
/** star */
if(indexStar < )
{
indexStar = ;
return;
}
/**end*/
if(indexStar > indexMax - defaultMaxLine)
{
indexStar = indexMax - defaultMaxLine;
return;
}
} if (lastIndex != indexStar) {
if (lastIndex < indexStar) {
Transform t = itemTrans[];
for(int i = ; i < itemTrans.Length - ; i++)
{
itemTrans[i] = itemTrans[i+];
} float fy = ;
Vector3 v3 = t.localPosition;
if(movement == UIScrollView.Movement.Horizontal)
{
fy = itemTrans[itemTrans.Length - ].localPosition.x + size.x + space;
v3.x = fy;
}else if(movement == UIScrollView.Movement.Vertical)
{
fy = itemTrans[itemTrans.Length - ].localPosition.y - size.y - space;
v3.y = fy;
} t.localPosition = v3;
itemTrans[itemTrans.Length - ] = t;
}else{
Transform t = itemTrans[itemTrans.Length - ];
for(int i = itemTrans.Length - ; i > ; i--)
{
itemTrans[i] = itemTrans[i-];
} float fy = ;
Vector3 v3 = t.localPosition;
if(movement == UIScrollView.Movement.Horizontal)
{
fy = itemTrans[].localPosition.x - size.x - space;
v3.x = fy;
}else if(movement == UIScrollView.Movement.Vertical)
{
fy = itemTrans[].localPosition.y + size.y + space;
v3.y = fy;
} t.localPosition = v3;
itemTrans[] = t;
} lastIndex = indexStar; if (scrollGridSetItem != null) {
scrollGridSetItem(itemTrans, indexStar, indexEnd);
}
sView.UpdatePosition();
}
} /** 重置scroll panel */
void ResetScrollPanelPosition()
{
if(movement == UIScrollView.Movement.Horizontal)
{
if (indexStar == ) {
ResetPostion ();
Vector3 v3 = Vector3.zero;
v3.x = panel.clipSoftness.x;
Vector2 v2 = Vector2.zero;
v2.x = -panel.clipSoftness.x;
panelTransfrom.localPosition = v3;
panel.clipOffset = v2;
}
}
else if(movement == UIScrollView.Movement.Vertical){
if (indexStar == ) {
ResetPostion ();
Vector3 v3 = Vector3.zero;
v3.y = -panel.clipSoftness.y;
Vector2 v2 = Vector2.zero;
v2.y = panel.clipSoftness.y;
panelTransfrom.localPosition = v3;
panel.clipOffset = v2;
}
}
} void SetItemPostion(){
float fristCoord = GetPositionByIndex(indexStar);
//Debug.Log ("fristCoord = " + fristCoord + " indexStar " + indexStar);
Vector3 np = Vector3.zero;
float ip = ;
float fp = ;
if(movement == UIScrollView.Movement.Horizontal)
{
ip = size.x;
}else if(movement == UIScrollView.Movement.Vertical)
{
ip = size.y;
}
for(int i = ; i < itemTrans.Length; i++)
{
fp = fristCoord - (ip + space) * i;
if(movement == UIScrollView.Movement.Horizontal)
{
np.x = -fp;
}else if(movement == UIScrollView.Movement.Vertical)
{
np.y = fp;
}
itemTrans[i].localPosition = np;
}
} /** 通过index 获得item位置 */
public float GetPositionByIndex(int index)
{
float fristCoord = ;
bool hasFristCoord = false;
Vector3 np = Vector3.zero;
float vp = ;
float ip = ;
float fp = ;
if(movement == UIScrollView.Movement.Horizontal)
{
vp = vSize.x;
ip = size.x;
}else if(movement == UIScrollView.Movement.Vertical)
{
vp = vSize.y;
ip = size.y;
}
fristCoord = vp / 2.0f - ip / 2.0f;
if(fristCoord > vp / 2.0f)
{
fristCoord = vp / 2.0f;
} fp = fristCoord - (ip + space) * index;
return fp;
} /** 通过index 获得panel位置 */
public float GetPanelPositionByIndex(int index)
{
if(movement == UIScrollView.Movement.Horizontal)
{
return (size.x + space) * index;
}else if(movement == UIScrollView.Movement.Vertical)
{
return (size.y + space) * index;
}
return ;
} /** 获得列表显示的第一个的index */
int GetShowStartIndex()
{
Vector3 v3 = panelTransfrom.localPosition;
if(movement == UIScrollView.Movement.Horizontal)
{
if(indexStar > )
{
int index = (int)((v3.x - panel.clipSoftness.x) / (size.x + space));
return Mathf.Abs(index);
}
}else if(movement == UIScrollView.Movement.Vertical)
{
if(indexStar > )
{
int index = (int)((v3.y + panel.clipSoftness.y) / (size.y + space));
return index;
}
}
return indexStar;
}
#endregion #region 创建 和 清空Item
Transform CreatItemTransfrom(int index)
{
GameObject go = Instantiate (ItemPrefab, Vector3.zero, Quaternion.identity) as GameObject;
if (go != null) {
go.transform.parent = transform;
go.transform.localScale = Vector3.one;
go.transform.localPosition = Vector3.zero;
go.transform.localRotation = Quaternion.identity;
go.name = "ScrollGrid Item " + index.ToString(); return go.transform;
}
Debug.LogError ("scrollGrid creat item prefab ");
return null;
} public void ClearChild()
{
if (transform.childCount < ) {
return;
}
Transform t = transform.GetChild ();
t.parent = null;
Destroy (t.gameObject);
ClearChild ();
}
#endregion #region scroll delegate void onDragStarted()
{
//Debug.Log ("onDragStarted");
}
void onDragFinished()
{
//Debug.Log ("onDragFinished");
SetItemPostion();
if (centerScrollViewOnChild) {
GotoIndex(GetShowStartIndex());
}
} void onMomentumMove()
{
//Debug.Log ("onMomentumMove"); }
void onStoppedMoving()
{
//Debug.Log ("onStoppedMoving");
ResetScrollPanelPosition ();
}
#endregion #region update and LateUpdate
int stepIndex = ;
void LateUpdate (){
panelPos = panel.gameObject.transform.localPosition; if(movement == UIScrollView.Movement.Horizontal)
{
stepIndex = (int)(panelPos.x / (size.x + space));
}else if(movement == UIScrollView.Movement.Vertical)
{
stepIndex = (int)(panelPos.y / (size.y + space));
}
SwitchItem (stepIndex);
SetMessage();
}
#endregion #region message
/** 通知是否到两头 */
void SetMessage()
{
if (scrollGridMessage != null) {
int index = GetShowStartIndex();
if(index == )
{
if(indexMax <= defaultShowMaxLine)
{
scrollGridMessage();
}else{
scrollGridMessage(-);
}
}else{
if(indexMax - defaultShowMaxLine > index)
{
if(movement == UIScrollView.Movement.Horizontal)
{
if(index + == indexMax - defaultShowMaxLine)
{
if(Mathf.Abs(itemTrans[itemTrans.Length - ].localPosition.x) == Mathf.Abs(GetPositionByIndex(indexMax - )))
{
scrollGridMessage();
}else{
scrollGridMessage();
}
}else{
scrollGridMessage();
} }else if(movement == UIScrollView.Movement.Vertical)
{
if(index + == indexMax - defaultShowMaxLine)
{
if(Mathf.Abs(itemTrans[itemTrans.Length - ].localPosition.y) == Mathf.Abs(GetPositionByIndex(indexMax - )))
{
scrollGridMessage();
}else{
scrollGridMessage();
}
}else{
scrollGridMessage();
}
} }else{
scrollGridMessage();
}
}
}
}
#endregion
}
*********************************** 测试 **********************************
在unity里首先需要按照:
List为scrollView 的父类(空GameObject)

ScrollView为NGUI自带的组件

ScrollGrid为我们自己的脚本
最后在用测试代码来测试
using UnityEngine;
using System.Collections; public class UITest : MonoBehaviour {
public ScrollGrid sg;
void Update()
{
if (Input.GetKeyDown (KeyCode.A)) {
sg.SetGrid(, setItem);
}
else if (Input.GetKeyDown (KeyCode.S)) {
sg.GotoIndex();
}
} void Start()
{
sg.SetGrid(, setItem);
}
void setItem(Transform[] t, int start, int end)
{
for (int i = ; i < t.Length; i++) {
t[i].GetComponent<ItemTest>().Name = "item " + (start + i).ToString();
}
}
}
******************** 测试结果 ***********************
*******************************************************
希望我写的还算详细,就写到这里了!!!!!! 支持原创转载请注明出处http://home.cnblogs.com/u/fastHro/
 

 

NGUI ScrollView 循环 Item 实现性能优化的更多相关文章

  1. php 大数组 foreach 循环嵌套的性能优化

    前提:最近在做后台的时候,页面加载太慢,故第一时间想到的自然是优化SQL, 优化后sql查询速度从 2秒变成了零点几秒, 以为就这麽完事了,然并卵,加载竟然花费30秒! 这麽慢,然后在代码中分块记录它 ...

  2. javascript循环---性能优化

    循环是编程中是最为常见的结构,优化循环是性能优化中很重要的一个部分. 减值迭代:大多数循环使用一个从0开始.增加到某个特定值的迭代器.在很多情况下,从最大值开始,在循环中不断减值的迭代器更加高效. 简 ...

  3. 菜鸟要做架构师(二)——java性能优化之for循环

    完成同样的功能,用不同的代码来实现,性能上可能会有比较大的差别,所以对于一些性能敏感的模块来说,对代码进行一定的优化还是很有必要的.今天就来说一下java代码优化的事情,今天主要聊一下对于for(wh ...

  4. for循环实战性能优化之使用Map集合优化

           笔者在<for循环实战性能优化>中提出了五种提升for循环性能的优化策略,这次我们在其中嵌套循环优化小循环驱动大循环的基础上,借助Map集合高效的查询性能来优化嵌套for循环 ...

  5. JavaScript性能优化

    如今主流浏览器都在比拼JavaScript引擎的执行速度,但最终都会达到一个理论极限,即无限接近编译后程序执行速度. 这种情况下决定程序速度的另一个重要因素就是代码本身. 在这里我们会分门别类的介绍J ...

  6. 【腾讯Bugly干货分享】跨平台 ListView 性能优化

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/FbiSLPxFdGqJ00WgpJ94yw 导语 精 ...

  7. (转) Android开发性能优化简介

    作者:贺小令 随着技术的发展,智能手机硬件配置越来越高,可是它和现在的PC相比,其运算能力,续航能力,存储空间等都还是受到很大的限制,同时用户对手机的体验要求远远高于PC的桌面应用程序.以上理由,足以 ...

  8. Android应用性能优化(转)

    人类大脑与眼睛对一个画面的连贯性感知其实是有一个界限的,譬如我们看电影会觉得画面很自然连贯(帧率为24fps),用手机当然也需要感知屏幕操作的连贯性(尤其是动画过度),所以Android索性就把达到这 ...

  9. Android UI性能优化实战, 识别View中的性能问题

    出自:[张鸿洋的博客]来源:http://blog.csdn.net/lmj623565791/article/details/45556391 1.概述 2015年初google发布了Android ...

随机推荐

  1. Missing letters

    function fearNotLetter(str) { //return str; var arr = str.split(''); var temp = []; var start = str. ...

  2. Java学习笔记16--异常

    异常 异常是导致程序中断运行的一种指令流,如果不对异常进行正确的处理,则可能导致程序的中断执行,造成不必要的损失, 所以在程序的设计中必须要考虑各种异常的发生,并正确的做好相应的处理,这样才能保证程序 ...

  3. zabbix使用sendEmail发送邮件报警

    sendEmail是一个轻量级,命令行的SMTP邮件客户端.如果你需要使用命令行发送邮件,那么sendEmail是非常完美的选择:使用简单并且功能强大.这个被设计用在php.bashperl和web站 ...

  4. sd_cms置顶新闻,背景颜色突击显示

    维护之前的一个客户网站,使用的是sd_cms系统,因为好久没有维护了,看到这网站的时候,真不敢相信,自己也曾做出过这样的网站. 客户要求置顶新闻始终在最上面,有背景颜色突击显示. 找到对应的代码,修改 ...

  5. VS经常报错的link error 2019

    VS经常报错的link error 2019 原因如下: 可能是找得到头文件,但是相关的dll或者lib找不到,需要在配置里面添加相应的库文件. project=>configuration.. ...

  6. [Chapter 3 Process]Practice 3.3 Discuss three major complications that concurrent processing adds to an operating system.

    3.3  Original version of Apple's mobile iOS operating system provied no means of concurrent processi ...

  7. C# 基础(2)

    打开一个解决方案,以.sin后缀名,.csproj是项目文件的后缀名. Console.WriteLine("这是我的第二个项目!");你想显示的内容 Console.ReadKe ...

  8. shell语法快速入门(1)

    #得到绝对路径 DIR=$(cd `dirname $0`;pwd) $DIR/file.txt #去掉#注释 egrep -v "(#|^$)" /etc/zabbix/zabb ...

  9. Tomcat7.0安装配置详细

    说明:Tomcat服务器上一个符合J2EE标准的Web服务器,在tomcat中无法运行EJB程序,如果要运行可以选择能够运行EJB程序的容器WebLogic,WebSphere,Jboss等:Tomc ...

  10. maven工程引用外部jar包

    maven工程经常回遇到引用外部jar包,需要先安装在jar包,然后再在工程中pom.xml文件中添加依赖. 示例: 命令行中运行: mvn install:install-file -Dfile=E ...