在项目中需要一个环形UI并且循环往复的效果,这个方法思路为提前预设好位置,让UI根据坐标预设的移动,然后使用mask遮罩达到循环往复效果的目的。
下图分别分为了三个列表
第一个列表poslist是提前预设的位置
第二个列表为背景暂时不用看
第三个列表btnlist为实际的移动UI
在这里插入图片描述
脚本上首先把路径放入,路径要比实际UI多两个是为了制作进入退出的动画效果,路径可以是空物体,实际作用就是为了定位移动。
第二个列表就为实际的操作UI
中心点设置是根据路径列表长度,如果是2那就是路径列表第[2]个,根据自己的列表调整
剩下两个列表为文字显示使用,方便显示各个btn要显示的名称
在这里插入图片描述
以下就是具体实现代码,代码不复杂理解一下就能愉快的玩耍了

using Cysharp.Threading.Tasks;
using DG.Tweening;
using QFramework;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Cysharp.Threading.Tasks.CompilerServices;
using System.Threading;
using TMPro; // 关键命名空间

public class LoopUI : MonoBehaviour
{

    public List<RectTransform> posList = new List<RectTransform>();
    public List<RectTransform> itemlist = new List<RectTransform>();
    bool is_是否处于动画 = true;
    public int index_中心点 = 2;
    public CanvasGroup BG_背景动画;

    public List< TextMeshProUGUI> texts   =new List<TextMeshProUGUI>();

    public List<string> btn_names=new List<string>();

    void Start()
    {
        Ins_初始化item坐标();


    }
    void Ins_初始化item坐标()
    {
        for (int i = 0; i < itemlist.Count; i++)//第一步先吧 需要移动的放到相应的位置
        {
            itemlist[i].anchoredPosition = posList[i + 1].anchoredPosition;
            var aa = itemlist[i];
            itemlist[i].GetComponent<Button>().onClick.AddListener(() => SetPos(aa));
        }

        //实例化第一个和最后一个用于 进行动画过渡 
        //把第一个的实力放在最下面,取名为1因为这是实例化列表中的第一个
        var ins = Instantiate(itemlist[0], posList[posList.Count - 1].position, posList[posList.Count - 1].rotation, itemlist[0].parent);
      //  ins.name = "1";
        //把第二个的示例放在最上面        取名为6因为这是实例化列表中的最后一个
        var ins2 = Instantiate(itemlist[itemlist.Count - 1], posList[0].position, posList[0].rotation, itemlist[itemlist.Count - 1].parent);
      //  ins2.name = "6";
        //位置放过后 路径排序为123456  UI实际排序为234516,因为实际ui就只有2345,1和6都是实例化生成进行动画过渡的,所以5后面跟1进行动画衔接
        itemlist.Insert(0,ins);
        ins.GetComponent<Button>().onClick.AddListener(() => SetPos(ins));
        itemlist.Add(ins2);
        ins2.GetComponent<Button>().onClick.AddListener(() => SetPos(ins2));

        for (int i = 0; i < texts.Count; i++)
        {
            texts[i].text = btn_names[i];
        }
    }

    async UniTask UImove(float chat, bool istrue)
    {
        if (istrue)
        {
            //移动过后删除隐藏起来的并移除
      
            Destroy(itemlist[0].gameObject);
            Destroy(itemlist[itemlist.Count - 1].gameObject);
            itemlist.Remove(itemlist[0]);
            itemlist.Remove(itemlist[itemlist.Count - 1]);


            //生成新的第一与最后一位,进行下一次动画移动
            var ins = Instantiate(itemlist[0], posList[posList.Count - 1].position, posList[posList.Count - 1].rotation, itemlist[0].parent);

            var ins2 = Instantiate(itemlist[itemlist.Count - 1], posList[0].position, posList[0].rotation, itemlist[itemlist.Count - 1].parent);
            //生成的第一个放到倒数第二个 最后一个还是放在最后
            itemlist.Add(ins);
            ins.GetComponent<Button>().onClick.AddListener(() => SetPos(ins));

            itemlist.Add(ins2);
            ins2.GetComponent<Button>().onClick.AddListener(() => SetPos(ins2));

            var s = btn_names[0];
            btn_names.Remove(btn_names[0]);
            btn_names.Add(s);


            for (int i = 0; i < texts.Count; i++)
            {
                texts[i].text = btn_names[i];
            }

            for (int x = 0; x < itemlist.Count; x++)
            {
                itemlist[x].DOAnchorPos(posList[x].anchoredPosition, chat).SetEase(Ease.Linear).ToUniTask().Forget();
            }



            await UniTaskManager.Instance.DelayedOperation(chat, () =>
            { 
             
                is_是否处于动画 = true;
            });
        }
        else
        {
            Destroy(itemlist[0].gameObject);
            Destroy(itemlist[itemlist.Count - 1].gameObject);
            itemlist.Remove(itemlist[0]);
            itemlist.Remove(itemlist[itemlist.Count - 1]);

            //生成新的第一与最后一位,进行下一次动画移动
            var ins = Instantiate(itemlist[0], posList[posList.Count - 1].position, posList[posList.Count - 1].rotation, itemlist[0].parent);

            var ins2 = Instantiate(itemlist[itemlist.Count - 1], posList[0].position, posList[0].rotation, itemlist[itemlist.Count - 1].parent);        
            //生成的第一个放到倒数第二个 最后一个还是放在最后
            itemlist.Insert(0, ins2);
            ins2.GetComponent<Button>().onClick.AddListener(() => SetPos(ins2));
            itemlist.Insert(0, ins);
            ins.GetComponent<Button>().onClick.AddListener(() => SetPos(ins));


            //把按钮名称排序
            var s = btn_names[btn_names.Count - 1];
         
            btn_names.Remove(btn_names[btn_names.Count - 1]);
            btn_names.Insert(0, s);
            for (int i = 0; i < texts.Count; i++)
            {
                texts[i].text = btn_names[i];
            }
            for (int x = 0; x < itemlist.Count; x++)
            {
                itemlist[x].DOAnchorPos(posList[x].anchoredPosition, chat).SetEase(Ease.Linear).ToUniTask().Forget();
            }
            await UniTaskManager.Instance.DelayedOperation(chat, () => { is_是否处于动画 = true;});

        }
    }
    private async void SetPos(RectTransform a)
    {

        if (!is_是否处于动画) return;
        is_是否处于动画 = false;
        //首先获取当前在列表中属于第几位
        var t = itemlist.IndexOf(a);
        //获取距离中心点差多少
        float chat = t - index_中心点;
    

        if (chat > 0)//算算当前要移动几下
        {
            BG_背景动画.DOFade(0, 0.5f).SetEase(Ease.Linear).OnComplete(() => {
             
                BG_背景动画.DOFade(1, 0.5f).SetEase(Ease.Linear); }).ToUniTask().Forget();
            for (int i = 0; i < chat; i++)
            {
                await UImove(1f / chat, true);
            }
        
        }
        else if (chat < 0)
        {
            BG_背景动画.DOFade(0, 0.5f).SetEase(Ease.Linear).OnComplete(() => {
               
                BG_背景动画.DOFade(1, 0.5f).SetEase(Ease.Linear); }).ToUniTask().Forget();
            for (int i = 0; i > chat; i--)
            {

                await UImove(1f / Mathf.Abs(chat), false);
            }
         
        }
        else { is_是否处于动画 = true; }







    }
    // Update is called once per frame
    void Update()
    {

    }
}

更多推荐