使用NGUI 3.5.5创建高效的超大Scroll View

来源:互联网 发布:绝地求生优化太差 编辑:程序博客网 时间:2024/05/21 07:42

在使用NGUI的Scroll View的时候,碰到Scroll Item太多的话(超过100个),在滑动的过程中就会明显掉帧。究其原因就是NGUI每帧会对所有的Scroll Item进行更新,无论它是否显示。

NGUI 3.5.5加入了UIWrapContent,它会将不显示的Scroll Item设为disabled,这样就使得每帧更新的Scroll Item减少到当前显示的那几个,就再也不会出现掉帧的情况了。

不过UIWrapContent只能创建循环的Scroll View,不过只需要简单的几处修改,就能实现在普通的Scroll View上。

复制一份UIWrapContent.cs,重命名为UIBetterGrid.cs,修改类名

// line: 19 - 20, file: UIWrapContent.cs [AddComponentMenu("NGUI/Interaction/Wrap Content")] public class UIWrapContent : MonoBehaviour 

修改后的代码如下:

// line: 19 - 20, file: UIBetterGrid.cs [AddComponentMenu("NGUI/Interaction/Better Grid")] public class UIBetterGrid : MonoBehaviour 

修改初始化代码
// line: 52 - 54, file: UIWrapContent.csmScroll.restrictWithinPanel = false; if (mScroll.dragEffect == UIScrollView.DragEffect.MomentumAndSpring) mScroll.dragEffect = UIScrollView.DragEffect.Momentum; 

修改后的代码如下:

// line: 52 - 54, file: UIBetterGrid.cs mScroll.restrictWithinPanel = true; //if (mScroll.dragEffect == UIScrollView.DragEffect.MomentumAndSpring) //mScroll.dragEffect = UIScrollView.DragEffect.Momentum; 

注释创建首尾循环的代码

// line 159 - 170, file: UIBetterGrid.cs//if (distance < -extents) //{ //     t.localPosition += new Vector3(extents * 2f, 0f, 0f); //        distance = t.localPosition.x - center.x; //     UpdateItem(t, i); //} //else if (distance > extents) //{ //     t.localPosition -= new Vector3(extents * 2f, 0f, 0f); //        distance = t.localPosition.x - center.x; //     UpdateItem(t, i); //} // line 190 - 201, file: UIBetterGrid.cs //if (distance < -extents) //{ //        t.localPosition += new Vector3(0f, extents * 2f, 0f); //        distance = t.localPosition.y - center.y; //     UpdateItem(t, i); //} //else if (distance > extents) //{ //     t.localPosition -= new Vector3(0f, extents * 2f, 0f); //        distance = t.localPosition.y - center.y; //     UpdateItem(t, i); //} 

修改UIScrollView.cs

// line 173, file: UIWrapContent.csmBounds = NGUIMath.CalculateRelativeWidgetBounds(mTrans, mTrans); 
修改后的代码如下:

// line 173, file: UIBetterGrid.csmBounds = NGUIMath.CalculateRelativeWidgetBounds(mTrans, mTrans,true); 


最后,使用NGUI自带的例子Example 7 - Scroll View (Panel).unity测试下性能吧。把例子中的UIGrid替换为UIBetterGrid,试试复制成百上千个scroll item,跑起来一点也不会卡。


最后完整的代码如下,UIScrollView的代码别忘了

//----------------------------------------------//            NGUI: Next-Gen UI kit// Copyright © 2011-2014 Tasharen Entertainment//----------------------------------------------using UnityEngine;/// <summary>/// This script makes it possible for a scroll view to wrap its content, creating endless scroll views./// Usage: simply attach this script underneath your scroll view where you would normally place a UIGrid:/// /// + Scroll View/// |- UIWrappedContent/// |-- Item 1/// |-- Item 2/// |-- Item 3/// </summary>[AddComponentMenu("NGUI/Interaction/Wrap Content")]public class UIBetterGrid : MonoBehaviour{/// <summary>/// Width or height of the child items for positioning purposes./// </summary>public int itemSize = 100;/// <summary>/// Whether the content will be automatically culled. Enabling this will improve performance in scroll views that contain a lot of items./// </summary>public bool cullContent = true;Transform mTrans;UIPanel mPanel;UIScrollView mScroll;bool mHorizontal = false;BetterList<Transform> mChildren = new BetterList<Transform>();/// <summary>/// Initialize everything and register a callback with the UIPanel to be notified when the clipping region moves./// </summary>protected virtual void Start (){SortBasedOnScrollMovement();WrapContent();if (mScroll != null){mScroll.GetComponent<UIPanel>().onClipMove = OnMove;mScroll.restrictWithinPanel = true;//if (mScroll.dragEffect == UIScrollView.DragEffect.MomentumAndSpring)//mScroll.dragEffect = UIScrollView.DragEffect.Momentum;}}/// <summary>/// Callback triggered by the UIPanel when its clipping region moves (for example when it's being scrolled)./// </summary>protected virtual void OnMove (UIPanel panel) { WrapContent(); }/// <summary>/// Immediately reposition all children./// </summary>[ContextMenu("Sort Based on Scroll Movement")]public void SortBasedOnScrollMovement (){if (!CacheScrollView()) return;// Cache all children and place them in ordermChildren.Clear();for (int i = 0; i < mTrans.childCount; ++i)mChildren.Add(mTrans.GetChild(i));// Sort the list of children so that they are in orderif (mHorizontal) mChildren.Sort(UIGrid.SortHorizontal);else mChildren.Sort(UIGrid.SortVertical);ResetChildPositions();}/// <summary>/// Immediately reposition all children, sorting them alphabetically./// </summary>[ContextMenu("Sort Alphabetically")]public void SortAlphabetically (){if (!CacheScrollView()) return;// Cache all children and place them in ordermChildren.Clear();for (int i = 0; i < mTrans.childCount; ++i)mChildren.Add(mTrans.GetChild(i));// Sort the list of children so that they are in ordermChildren.Sort(UIGrid.SortByName);ResetChildPositions();}/// <summary>/// Cache the scroll view and return 'false' if the scroll view is not found./// </summary>protected bool CacheScrollView (){mTrans = transform;mPanel = NGUITools.FindInParents<UIPanel>(gameObject);mScroll = mPanel.GetComponent<UIScrollView>();if (mScroll == null) return false;if (mScroll.movement == UIScrollView.Movement.Horizontal) mHorizontal = true;else if (mScroll.movement == UIScrollView.Movement.Vertical) mHorizontal = false;else return false;return true;}/// <summary>/// Helper function that resets the position of all the children./// </summary>void ResetChildPositions (){for (int i = 0; i < mChildren.size; ++i){Transform t = mChildren[i];t.localPosition = mHorizontal ? new Vector3(i * itemSize, 0f, 0f) : new Vector3(0f, -i * itemSize, 0f);}}/// <summary>/// Wrap all content, repositioning all children as needed./// </summary>public void WrapContent (){float extents = itemSize * mChildren.size * 0.5f;Vector3[] corners = mPanel.worldCorners;for (int i = 0; i < 4; ++i){Vector3 v = corners[i];v = mTrans.InverseTransformPoint(v);corners[i] = v;}Vector3 center = Vector3.Lerp(corners[0], corners[2], 0.5f);if (mHorizontal){float min = corners[0].x - itemSize;float max = corners[2].x + itemSize;for (int i = 0; i < mChildren.size; ++i){Transform t = mChildren[i];float distance = t.localPosition.x - center.x;                //if (distance < -extents)                //{                //    t.localPosition += new Vector3(extents * 2f, 0f, 0f);                //    distance = t.localPosition.x - center.x;                //    UpdateItem(t, i);                //}                //else if (distance > extents)                //{                //    t.localPosition -= new Vector3(extents * 2f, 0f, 0f);                //    distance = t.localPosition.x - center.x;                //    UpdateItem(t, i);                //}if (cullContent){distance += mPanel.clipOffset.x - mTrans.localPosition.x;if (!UICamera.IsPressed(t.gameObject))NGUITools.SetActive(t.gameObject, (distance > min && distance < max), false);}}}else{float min = corners[0].y - itemSize;float max = corners[2].y + itemSize;for (int i = 0; i < mChildren.size; ++i){Transform t = mChildren[i];float distance = t.localPosition.y - center.y;                //if (distance < -extents)                //{                //    t.localPosition += new Vector3(0f, extents * 2f, 0f);                //    distance = t.localPosition.y - center.y;                //    UpdateItem(t, i);                //}                //else if (distance > extents)                //{                //    t.localPosition -= new Vector3(0f, extents * 2f, 0f);                //    distance = t.localPosition.y - center.y;                //    UpdateItem(t, i);                //}if (cullContent){distance += mPanel.clipOffset.y - mTrans.localPosition.y;if (!UICamera.IsPressed(t.gameObject))NGUITools.SetActive(t.gameObject, (distance > min && distance < max), false);}}}}/// <summary>/// Want to update the content of items as they are scrolled? Override this function./// </summary>protected virtual void UpdateItem (Transform item, int index) {}}


文章转载自使用NGUI 3.5.5创建高效的超大Scroll View,感谢JJCat提供好文章

0 0
原创粉丝点击