UGUI各種優(yōu)化效果
本文所實現(xiàn)的UGUI效果需求如下:?
-?支持縮放滑動效果?
-?支持動態(tài)縮放循環(huán)加載?
-?支持大數(shù)據(jù)固定Item復(fù)用加載?
-?支持不用Mask遮罩無限循環(huán)加載?
-?支持ObjectPool動態(tài)加載?
-?支持無限不規(guī)則子物體動態(tài)加載?
-?支持拖動并點擊和拖拽?
-?支持拖動并拖拽?
-?支持ScrollRect拖動自動吸附功能(拖動是否超過一半自動進退)
縮放滑動效果?
縮放循環(huán)展示卡牌效果
大量數(shù)據(jù)無卡頓動態(tài)加載二汛,并且支持拖拽、點擊和吸附功能
大量數(shù)據(jù)循固定Item復(fù)用?
無限無遮罩動態(tài)加載
不規(guī)則子物體動態(tài)循環(huán)加載
有遮罩無卡頓加載?
思路:并沒有使用UGUI的ScrollRect組件忽舟,擺放幾張卡片任柜,通過移動和縮放來實現(xiàn)
usingUnityEngine;usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine.UI;publicclassEnhancelScrollView : MonoBehaviour{// 縮放曲線publicAnimationCurve scaleCurve;// 位移曲線publicAnimationCurve positionCurve;// 位移系數(shù)publicfloatposCurveFactor =500.0f;// y軸坐標(biāo)固定值(所有的item的y坐標(biāo)一致)publicfloatyPositionValue =46.0f;// 添加到EnhanceScrollView的目標(biāo)對象publicList
有遮罩無卡頓加載?
思路:協(xié)程加載何址,先加載屏幕顯示的數(shù)量民宿,然后返回一幀在繼續(xù)加載,防止出現(xiàn)數(shù)量太大卡頓的現(xiàn)象痴突。
while(CardsList.Count > roleInfo.Count){? ? DestroyImmediate(CardsList[0].gameObject);? ? CardsList.RemoveAt(0);}StartCoroutine(createRoleCards());privateIEnumeratorcreateRoleCards(){? ? List charInfos =newList();? ? charInfos.AddRange(roleInfo);intindex =0;for(inti =0; i < charInfos.Count; i++)? ? {? ? ? ? _createRoleCard(charInfos[i], index++);if(index %10==0)yieldreturnnull;? ? }}privatevoid_createRoleCard(CLocalCharInfo roleInfo,intindex){? ? CUIPlayedCharCardWidget charCardWidget =null;if(CardsList.Count > index)? ? {? ? ? ? charCardWidget = CardsList[index];? ? }else{varobj = Instantiate(Resources.Load("Prefab/RoleCard"))asGameObject;if(obj ==null)? ? ? ? {? ? ? ? ? ? UnityEngine.Debug.LogError("有誤");return;? ? ? ? }? ? ? ? obj.name = roleInfo.Name;? ? ? ? charCardWidget = obj.GetComponent();if(charCardWidget ==null)? ? ? ? {? ? ? ? ? ? UnityEngine.Debug.LogError("有誤");return;? ? ? ? }? ? ? ? obj.transform.parent = Obj_ScrollViewContent.transform;? ? ? ? obj.transform.localScale = Vector3.one;? ? ? ? CardsList.Add(charCardWidget);? ? }? ? CUIPlayedCharCardWidget.CUIContent uiContent =newCUIPlayedCharCardWidget.CUIContent();? ? uiContent.RoleInfo = roleInfo;? ? uiContent.ScrollRectObj = m_ScrollRect;? ? uiContent.FixGridRect = m_FixGrid;? ? charCardWidget.InitContent(uiContent);}
支持ScrollRect拖拽或點擊?
思路:在卡片的Image上添加一個繼承了IBeginDragHandler,IGradHandler,IEndDragHandler的腳本粉渠,重寫接口里面的Drag事件方法。
usingUnityEngine;usingUnityEngine.EventSystems;usingUnityEngine.UI;namespace Mga{? ? [RequireComponent(typeof(Image))]publicclassCPlayedCardOnDrag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler? ? {publicbooldragOnSurfaces =true;publicScrollRect m_ScrollRect =null;publicCFixGridRect m_FixGridRect =null;privateGameObject m_DraggingCard;privateRectTransform m_DraggingPlane;publicboolisVertical =false;privateboolisSelf =false;privateSystem.Action m_OnBeginDragCallBack =null;privateSystem.Action m_OnEndDragCallBack =null;privateSystem.Action m_OnBeginScroll =null;privateSystem.Action m_OnEndScroll =null;publicvoidInit(CLocalCharInfo roleInfo, System.Action beginCallBack =null, System.Action endCallBack =null, System.Action beginScroll =null, System.Action endScroll =null)? ? ? ? {? ? ? ? ? ? m_OnBeginDragCallBack = beginCallBack;? ? ? ? ? ? m_OnEndDragCallBack = endCallBack;? ? ? ? ? ? m_OnBeginScroll = beginScroll;? ? ? ? ? ? m_OnEndScroll = endScroll;? ? ? ? }publicvoidOnBeginDrag(PointerEventData eventData)? ? ? ? {? ? ? ? ? ? Vector2 touchDeltaPosition = Vector2.zero;#ifUNITY_EDITORfloatdelta_x = Input.GetAxis("Mouse X");floatdelta_y = Input.GetAxis("Mouse Y");? ? ? ? ? ? touchDeltaPosition =newVector2(delta_x, delta_y);#elifUNITY_ANDROID || UNITY_IPHONEtouchDeltaPosition = Input.GetTouch(0).deltaPosition;#endifif(isVertical)? ? ? ? ? ? {if(Mathf.Abs(touchDeltaPosition.x) > Mathf.Abs(touchDeltaPosition.y))? ? ? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ? isSelf =true;varcanvas = FindInParents
如果想要實現(xiàn)拖拽到目標(biāo)位置的檢測派哲,還要在目標(biāo)位置放一個Image并且添加上繼承了IDropHandler,IPointerEnterHandler,IPointerExitHanler的組件。
在ScrollRect物體上添加吸附功能組件掺喻,工程里面要使用DoTween插件
usingSystem.Collections.Generic;usingDG.Tweening;usingUnityEngine;usingUnityEngine.EventSystems;usingUnityEngine.UI;//TODO:當(dāng)前只試應(yīng)橫向的ScrollRect芭届,還需要擴展支持縱向publicclassCFixGridRect : MonoBehaviour, IEndDragHandler{publicGameObject content;publicScrollRect scorllRect;publicfloatitemWidth;privateRectTransform contentRectTf;privatefloatformalPosX =0;privatefloatcurrentPosX =0;privatefloathalfItemLength =0;voidStart()? ? {if(itemWidth <=0)? ? ? ? ? ? UnityEngine.Debug.LogError("請設(shè)置Item的寬度");? ? ? ? halfItemLength = itemWidth /2;this.contentRectTf =this.content.GetComponent();? ? }publicvoidOnEndDrag(PointerEventData eventData)? ? {this.scorllRect.StopMovement();? ? ? ? Vector2 afterDragPagePos =this.content.transform.localPosition;? ? ? ? currentPosX = afterDragPagePos.x;//當(dāng)前拖動的位置? 負if(scorllRect.horizontalNormalizedPosition <0|| scorllRect.horizontalNormalizedPosition >1)return;intcount = (int)(Mathf.Abs(currentPosX) / itemWidth);vartargetPos = -(float)(count * itemWidth);if(((float)(count * itemWidth + halfItemLength)) < Mathf.Abs(currentPosX))? ? ? ? {? ? ? ? ? ? targetPos = -(float)((count +1) * itemWidth);? ? ? ? }? ? ? ? formalPosX = targetPos;this.contentRectTf.DOLocalMoveX(targetPos,.2f);? ? }}
usingSystem.Collections.Generic;usingDG.Tweening;usingUnityEngine;usingUnityEngine.EventSystems;usingUnityEngine.UI;namespace Mga{publicenumDragDirection? ? {? ? ? ? Horizontal,? ? ? ? Vertical,? ? }publicclassCFixGridRectBase : MonoBehaviour, IEndDragHandler? ? {publicclassCUIContent? ? ? ? {publicGameObject ScrollRectContent;publicScrollRect m_ScorllRect;publicfloatItemSize;publicfloatItemSpaceLength;//間隙publicfloatMargin =0;//頂部邊緣間隙publicDragDirection m_DragDirection = DragDirection.Vertical;? ? ? ? }privateRectTransform contentRectTf;privatefloathalfItemLength =0;privateCUIContent m_uiContent =null;privateboolm_bWidgetReady =false;voidStart()? ? ? ? {? ? ? ? ? ? m_bWidgetReady =true;? ? ? ? ? ? _initContent();? ? ? ? }publicvoidInitContent(CUIContent uiContent)? ? ? ? {? ? ? ? ? ? m_uiContent = uiContent;if(m_bWidgetReady)? ? ? ? ? ? ? ? _initContent();? ? ? ? }privatevoid_initContent()? ? ? ? {if(m_uiContent ==null)return;if(m_uiContent.ItemSize <=0)? ? ? ? ? ? {? ? ? ? ? ? ? ? UnityEngine.Debug.LogError("請設(shè)置Item的寬度");return;? ? ? ? ? ? }? ? ? ? ? ? halfItemLength = m_uiContent.ItemSize /2;this.contentRectTf = m_uiContent.ScrollRectContent.GetComponent();? ? ? ? }publicvoidOnEndDrag(PointerEventData eventData)? ? ? ? {? ? ? ? ? ? m_uiContent.m_ScorllRect.StopMovement();? ? ? ? ? ? Vector2 afterDragPagePos = m_uiContent.ScrollRectContent.transform.localPosition;varitemLength = m_uiContent.ItemSize + m_uiContent.ItemSpaceLength;if(m_uiContent.m_DragDirection == DragDirection.Horizontal)? ? ? ? ? ? {varcurrentPosX = afterDragPagePos.x;//當(dāng)前拖動的位置? 負currentPosX -= m_uiContent.Margin;intcount = (int)(Mathf.Abs(currentPosX) / m_uiContent.ItemSize);if(m_uiContent.m_ScorllRect.horizontalNormalizedPosition <=0)? ? ? ? ? ? ? ? {return;? ? ? ? ? ? ? ? }elseif(m_uiContent.m_ScorllRect.horizontalNormalizedPosition >=1)//總數(shù)-當(dāng)前顯示的數(shù)量{return;? ? ? ? ? ? ? ? }vartargetPosX = -(float)(count * itemLength);if(((float)(targetPosX + halfItemLength)) < Mathf.Abs(currentPosX))? ? ? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ? count++;? ? ? ? ? ? ? ? ? ? targetPosX = -(float)(count * itemLength);? ? ? ? ? ? ? ? }this.contentRectTf.DOLocalMoveX(targetPosX,.2f);? ? ? ? ? ? }else{varcurrentPosY = afterDragPagePos.y;//當(dāng)前拖動的位置? 正currentPosY -= m_uiContent.Margin;intcount = (int)(Mathf.Abs(currentPosY) / itemLength);if(m_uiContent.m_ScorllRect.verticalNormalizedPosition <=0)? ? ? ? ? ? ? ? {return;? ? ? ? ? ? ? ? }elseif(m_uiContent.m_ScorllRect.verticalNormalizedPosition >=1)//總數(shù)-當(dāng)前顯示的數(shù)量{return;? ? ? ? ? ? ? ? }vartargetPosY = (float)(count * itemLength);if(((float)(targetPosY + halfItemLength)) < Mathf.Abs(currentPosY))? ? ? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ? count++;? ? ? ? ? ? ? ? ? ? targetPosY = (float)(count * itemLength);? ? ? ? ? ? ? ? }this.contentRectTf.DOLocalMoveY(targetPosY,.2f);? ? ? ? ? ? }? ? ? ? }? ? }}
如果代碼創(chuàng)建AnimationCurve默認是曲線,如果想要直線效果感耙,可以在面板里面設(shè)置褂乍,也可以代碼設(shè)置,如果代碼設(shè)置如下:
var curve2 = new AnimationCurve();var key1 = new Keyframe(0,0);key1.outTangent=1;var key2 = new Keyframe(1,1);key2.inTangent=1;curve2.AddKey(key1);curve2.AddKey(key2);curve2.postWrapMode= WrapMode.Loop;curve2.preWrapMode= WrapMode.Loop;
這樣的話就是直線了即硼。