NGUI ScrollView 循环 Item 实现性能优化

时间:2023-03-09 00:17:08
NGUI ScrollView 循环 Item 实现性能优化

今天来说说一直都让我在项目中头疼的其中一个问题,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)

NGUI ScrollView 循环 Item 实现性能优化

ScrollView为NGUI自带的组件
NGUI ScrollView 循环 Item 实现性能优化
ScrollGrid为我们自己的脚本
NGUI ScrollView 循环 Item 实现性能优化 最后在用测试代码来测试
NGUI ScrollView 循环 Item 实现性能优化
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();
}
}
}
******************** 测试结果 ***********************
NGUI ScrollView 循环 Item 实现性能优化 *******************************************************
希望我写的还算详细,就写到这里了!!!!!! 支持原创转载请注明出处http://home.cnblogs.com/u/fastHro/