Unity 实现简单的无限循环ScrollView

反正实现的效果就是如标题所示了,无限循环的scrollView。注意这里的方法是比较粗浅的,也当抛砖引玉。反正效果是实现了,然后性能也还行。 先看效果:
之所以要实现这种效果,主要是因为scrollview底下的内容量有时候可能会非常的多,比如说物品背包栏,可能包含成千上万个物品。直接使用原生scrollview的话,那性能消耗是蛮夸张的。毕竟屏幕里能显示的内容数量就那么几个,但是却吃那么多的性能多少有点怪。解决这种情况的方法,一种是无限scrollview,就是再显示区域外再多提供两个格子,一个为头部,一个为尾部,不停的调换位置就行了。 另外一种就是分页了,就提供固定几个格子,然后按照分页修改格子的内容。 代码分两个部分,一个与scrollview相关,一个与scrollbar相关。具体的代码分析实在是写的头痛,有需要的话自己看看就行了。不是什么很难的东西。 下边的scrollview的代码:
using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; public class UnlimitedScrollView : MonoBehaviour, IEndDragHandler { [Header("内容条目的数量")] public int ItemNum; [Header("Item高度间隔")] public int ItemSizeHight; private RectTransform Content; private RectTransform[] ShowItem;//Item数组 public Scrollbar VerticalScrollbar; private float CurrentContentPos; private int CurrentItemNum; private int _Downcurrentiemnum; private int Head, End; private float viewHight; [Header("当前显示的数目")] private int ShowItemNum; [Header("Item的obj")] public GameObject ShowItemObj; // Start is called before the first frame update void Start() { Content = this.GetComponent<ScrollRect>().content; float ItemHight = ShowItemObj.GetComponent<RectTransform>().sizeDelta.y; viewHight = this.GetComponent<RectTransform>().sizeDelta.y; ItemSizeHight = (int)(ItemSizeHight + ItemHight); ShowItemNum = (int)(viewHight / ItemSizeHight) + 3;//竖向显示的数目 float ContentHight = ItemSizeHight * ItemNum; Content.GetComponent<RectTransform>().sizeDelta = new Vector2(Content.sizeDelta.x, ContentHight); CurrentItemNum = 1; _Downcurrentiemnum = CurrentItemNum; Init(); CheckItemAndSet(); Head = 0; End = ShowItem.Length - 1; if (VerticalScrollbar != null) { VerticalScrollbar.onValueChanged.AddListener((float a) => { CheckItemAndSet(); }); VerticalScrollbar.gameObject.AddComponent<MyScrollbar>(); VerticalScrollbar.gameObject.GetComponent<MyScrollbar>().EndDrag.AddListener(() => { CheckItemAndSet(); } ); }//检测有无scrollbar } // Update is called once per frame void Update() { CurrentContentPos = Content.anchoredPosition.y - (ItemSizeHight / 2); CheckItem(); if (CurrentItemNum >= _Downcurrentiemnum + 1) { _Downcurrentiemnum = CurrentItemNum; SwapHeadToEnd(); } else if (CurrentItemNum <= _Downcurrentiemnum - 1) { _Downcurrentiemnum = CurrentItemNum; SwapEndToHead(); } } public void Init() { ShowItem = new RectTransform[ShowItemNum]; ShowItem[0] = ShowItemObj.GetComponent<RectTransform>(); for (int i = 0; i < ShowItemNum; i++) { GameObject showitemobj = GameObject.Instantiate(ShowItemObj, Content, false); ShowItem[i] = showitemobj.GetComponent<RectTransform>(); showitemobj.name = ShowItemObj.name + i; showitemobj.GetComponent<RectTransform>().anchoredPosition = new Vector2(showitemobj.GetComponent<RectTransform>().anchoredPosition.x, -(i) * ItemSizeHight); } ShowItemObj.SetActive(false); } public void CheckItem() { CurrentItemNum = (int)(CurrentContentPos / ItemSizeHight);//当前应该显示的数 } public void SwapHeadToEnd() { ShowItem[Head].anchoredPosition = new Vector2(ShowItem[Head].anchoredPosition.x, ShowItem[End].anchoredPosition.y - ItemSizeHight); ShowItem[Head].transform.SetAsLastSibling(); // ShowItem[Head].GetComponentInChildren<Text>().text = (CurrentItemNum + ShowItem.Length - 1).ToString(); End = Head; Head++; if (Head == ShowItem.Length) { Head = 0; } }//把头部挪到尾部 public void SwapEndToHead() { ShowItem[End].anchoredPosition = new Vector2(ShowItem[End].anchoredPosition.x, ShowItem[Head].anchoredPosition.y + ItemSizeHight); ShowItem[End].transform.SetAsFirstSibling(); // ShowItem[End].GetComponentInChildren<Text>().text = CurrentItemNum.ToString(); Head = End; End--; if (End == -1) { End = ShowItem.Length - 1; } }//把尾部挪到头部 public void CheckItemAndSet() { if (ShowItem[Head].anchoredPosition.y != CurrentItemNum * ItemSizeHight + (ItemSizeHight / 2)) { int _currentitemnum = CurrentItemNum; int _head = Head; for (int i = 0; i < ShowItem.Length; i++) { // ShowItem[_head].GetComponentInChildren<Text>().text = _currentitemnum.ToString(); ShowItem[_head].anchoredPosition = new Vector2(ShowItem[_head].anchoredPosition.x, -_currentitemnum * ItemSizeHight + (ItemSizeHight / 2)); _head++; if (_head == ShowItem.Length) { _head = 0; } _currentitemnum++; } } }//检查一遍当前的item对应位置,错误的话便重新排序位置,并再次赋值 public void OnEndDrag(PointerEventData eventData) { CheckItemAndSet(); } }
然后是一个scrollbar的代码,就是提供一个监听结束拖拽的事件:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; public class DoEventCall : UnityEvent { } public class MyScrollbar : MonoBehaviour,IEndDragHandler { public DoEventCall EndDrag = new DoEventCall(); public void OnEndDrag(PointerEventData eventData) { EndDrag.Invoke(); } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值