Unity圆弧滑动列表

Unity圆形滑动列表


经常在拼接UI界面时会被策划要求做成圆形滑动列表,所以自己写了一个简单的圆形滑动列表
下面上代码
将代码挂在item的父物体上就可以了,动画使用的是DoTween插件
DOTweenDLL下载链接

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using DG.Tweening;
using UnityEngine.UI;

/// <summary>
/// 圆弧列表 实例为圆心
/// </summary>
public class CirSlidingManager : MonoBehaviour,IBeginDragHandler, IEndDragHandler, IDragHandler
{
    /// <summary>
    /// 子物体列表
    /// </summary>
    List<RectTransform> childList = new List<RectTransform>();

    /// <summary>
    /// 当前显示物体
    /// </summary>
    [SerializeField]
    List<RectTransform> showchildlist = new List<RectTransform>();
    /// <summary>
    /// 未显示物体
    /// </summary>
    List<RectTransform> noshowchildlist = new List<RectTransform>();

    /// <summary>
    /// 右侧待显示物体
    /// </summary>
    Stack<RectTransform> rightchildlist = new Stack<RectTransform>();
    /// <summary>
    /// 左侧待显示物体
    /// </summary>
    Stack<RectTransform> leftchildlist = new Stack<RectTransform>();
    /// <summary>
    /// 排列位置
    /// </summary>
    List<Vector2> poslist = new List<Vector2>();
    /// <summary>
    /// 记录手指触摸位置
    /// </summary>
    Vector2 previousPos;
    /// <summary>
    /// 左侧隐藏物体坐标
    /// </summary>
    public Vector2 leftmask;

    public Vector2 rightmask;

    /// <summary>
    /// 显示数量
    /// </summary>
    [SerializeField]
    int shownumber = 4;
    /// <summary>
    /// 园半径
    /// </summary>
    public float radius = 500f;
    /// <summary>
    /// 滑动时间
    /// </summary>
    public float slidingtime = 1f;

    // Start is called before the first frame update
    void Start()
    {
        leftmask= (transform as RectTransform).anchoredPosition + GetPosXYByAngle(180 / (shownumber - 1) * -1);
        rightmask= (transform as RectTransform).anchoredPosition + GetPosXYByAngle(180 / (shownumber - 1) * shownumber);

        //获取所有物体
        for (int i = 0; i < transform.childCount; i++)
        {
            RectTransform rect = transform.GetChild(i) as RectTransform;

            if (rect != null)
            {
                if (i < shownumber)
                {
                    showchildlist.Add(rect);
                    //根据角度和显示数量计算当前物体位置
                    Vector2 pos= (transform as RectTransform).anchoredPosition + GetPosXYByAngle(180 / (shownumber - 1) * i);
                    rect.anchoredPosition = pos;
                    //保存位置 滑动时使用
                    poslist.Add(pos);

                }
                else
                {
                    //超出显示数量的物体 保存到右侧待显示列表中等待滑动显示
                    rect.gameObject.SetActive(false);
                    rect.anchoredPosition = rightmask;
                    noshowchildlist.Add(rect);
                }
            }
        }
    }
    /// <summary>
    /// 根据角度拿到相对于圆心的XY坐标
    /// </summary>
    /// <param name="angle"></param>
    /// <returns></returns>
    public Vector2 GetPosXYByAngle(float angle)
    {
        if (angle > 90)
        {
            angle = 180 - angle;
            Vector2 pos = new Vector2();
            pos.y = Mathf.Sin(angle * Mathf.Deg2Rad) * radius;
            pos.x = Mathf.Cos(angle * Mathf.Deg2Rad) * radius;
            return pos;
        }
        else
        {
            Vector2 pos = new Vector2();
            pos.y = Mathf.Sin(angle * Mathf.Deg2Rad) * radius;
            pos.x = -Mathf.Cos(angle * Mathf.Deg2Rad) * radius;
            return pos;
        }


    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        previousPos = eventData.position;
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        //手指向右滑动 列表显示左侧待显示物体
        if(eventData.position.x> previousPos.x)
        {
            LeftTurn();
        }
        else
        {
            RightTurn();
        }
    }

   /// <summary>
   /// 显示右侧物体
   /// </summary>
    void RightTurn()
    {
        //右侧是否有待显示物体
        if (noshowchildlist.Count == 0 && rightchildlist.Count == 0)
            return;

        //当前显示第一个物体加入左侧列表
        AddLeftMask(showchildlist[0]);
        //移除当前显示的第一个物体
        showchildlist.RemoveAt(0);

        if (noshowchildlist.Count != 0)
        {
            showchildlist.Add(noshowchildlist[0]);
            noshowchildlist.RemoveAt(0);
        }
        else
        {
            showchildlist.Add(rightchildlist.Pop());
        }
        //更新按钮位置
        for (int i = 0; i < showchildlist.Count; i++)
        {
            showchildlist[i].gameObject.SetActive(true);
            showchildlist[i].DOAnchorPos(poslist[i], slidingtime);
        }



    }
    /// <summary>
    /// 显示左侧物体
    /// </summary>
    void LeftTurn()
    {
        //左侧是否有待显示物体
        if (leftchildlist.Count == 0)
            return;

        //当前显示最后一个物体加入右侧列表
        AddRightMask(showchildlist[showchildlist.Count - 1]);
        //移除当前显示的第一个物体
        showchildlist.RemoveAt(showchildlist.Count - 1);

        showchildlist.Insert(0,leftchildlist.Pop());

        //更新按钮位置
        for (int i = 0; i < showchildlist.Count; i++)
        {
            showchildlist[i].gameObject.SetActive(true);
            showchildlist[i].DOAnchorPos(poslist[i], slidingtime);
        }
    }

    void AddLeftMask(RectTransform item)
    {
        item.DOAnchorPos(leftmask, slidingtime);
        item.gameObject.SetActive(false);
        leftchildlist.Push(item);
    }
    void AddRightMask(RectTransform item)
    {
        item.DOAnchorPos(rightmask, slidingtime);
        item.gameObject.SetActive(false);
        rightchildlist.Push(item);
    }

    public void OnDrag(PointerEventData eventData)
    {
       
    }
}

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: Unity中的滑动列表复用是一种优化技术,它的主要目的是在滑动列表时减少消耗,提高性能。当一个列表包含大量的元素时,正常的做法是将所有的元素都实例化并显示在列表上,这样无疑会占用大量的内存和CPU资源。 而利用滑动列表复用的技术,只在可视范围内实例化和显示部分元素,其他不可见的元素会被回收,以便在需要显示时能够被快速调用和展示。这样能够有效地减少内存的占用和CPU的计算量,并且提高渲染的效率。 在实现滑动列表复用时,一般需要使用UnityUI组件,如ScrollView和Viewport。其中ScrollView用来处理滑动的逻辑,而Viewport则是实际显示元素的区域。在Viewport区域内,需要使用一个列表容器,如GridLayoutGroup或者VerticalLayoutGroup,用来放置元素的布局。 当滑动列表时,可以通过滑动的位置计算出需要显示的元素范围,然后根据这个范围动态地实例化和回收列表的元素。具体的实现方式可以通过数据绑定、对象池技术等。 通过使用滑动列表复用的技术,可以大大降低性能消耗,提高游戏的流畅度和响应速度。同时,它也适用于各种类型的列表,如角色列表、背包列表等。 ### 回答2: Unity滑动列表复用是指在滑动列表中,为了节省资源和提高性能,只在可见范围内创建和显示列表项,当列表项滑出可见范围后,将其隐藏并放入对象池中,待需要再次显示的时候,直接从对象池中获取,避免频繁地创建和销毁列表项。 实现滑动列表复用的关键是要使用Unity提供的ScrollRect组件和RectTransform组件,以及编写代码来控制列表项的创建、隐藏和显示。 具体实现步骤如下: 1. 创建一个ScrollRect组件,用于实现滑动功能。 2. 在ScrollRect中创建一个Content对象,作为滑动列表的内容容器。 3. 创建一个预制体,作为滑动列表列表项。 4. 编写脚本,控制列表项的创建、隐藏和显示。在脚本中,可以使用对象池技术来管理列表项的复用,即在滑出可见范围时,将其隐藏并放入对象池,需要显示时,从对象池中获取。同时,根据滑动的位置,动态计算需要显示的列表项,将其显示出来。 5. 使用RectTransform组件来设置Content的大小,以便适应滑动列表中的列表项。 通过以上步骤,就可以实现滑动列表的复用。这样做的好处是可以大大减少内存消耗,提高性能,特别是当列表项较多时,效果更为明显。 需要注意的是,滑动列表复用的实现需要根据具体需求和项目的框架来设计和编写,可以根据实际情况进行调整和优化。 ### 回答3: Unity中的滑动列表复用是一种优化技术,用于在滚动容器(例如ScrollView)中动态创建和复用列表项(例如UI元素)。 滑动列表是一个常见的UI设计元素,通常用于显示大量数据或多个列表项。在传统的做法中,为了显示所有的列表项,会将它们全部实例化并放置在容器中。但是当列表项数量过多时,这种做法会导致性能问题,因为每个列表项都需要占用一定的内存和处理计算。 为了解决这个问题,Unity中引入了滑动列表复用的概念。它的工作原理是,只实例化能够同时展示在可见区域内的列表项,而在滑动过程中,通过不断复用已实例化的列表项来避免频繁的创建和销毁操作。 具体实现上,通常会通过计算可见区域的大小和位置,以及每个列表项的大小来确定当前需要显示的列表项范围。然后在滑动过程中,通过改变列表项的位置和内容来实现复用效果。一般会维护一个对象池,保存已实例化的列表项,以便在滑动时快速切换和更新它们的内容,避免频繁的创建和销毁操作。 通过使用滑动列表复用技术,可以显著提升滑动容器的性能和效率。它减少了内存的占用和对象的创建数量,降低了CPU的负载,并提高了滑动的流畅度和响应速度,尤其在处理大型列表时效果更加明显。 总之,滑动列表复用是Unity中一种高效优化滑动容器性能的技术,它通过动态复用和更新列表项,减少内存占用和CPU负载,提高滑动的流畅度和响应速度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值