unity 环形循环切换UI

环形ui管理器

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
using System.Collections;
using Unity.VisualScripting;

public class LevelSelector : MonoBehaviour
{
    public GameObject levelButtonPrefab; // 关卡按钮的Prefab

    public Transform levelGroup;
    public int levelCount = 6; // 关卡数量
    public float radius = 300f; // 半径
    public float moveDuration = 1f; // 移动持续时间
    public float yOffsetStep = 80f; // Y轴偏移步长

    public Button nextLevelButton;
    public Button previousLevelButton; 

    private List<GameObject> levelButtons = new List<GameObject>();
    private List<float> yOffsets;
    private List<int> sortOrders;
    private float angleStep;
    private float currentAngle = 0f;
    void Start()
    {
        // 计算每个按钮之间的角度
        angleStep = 360f / levelCount;

        // 自动计算对称的Y轴偏移量
        yOffsets = CalculateSymmetricYOffsets(levelCount);
        // 初始化排序顺序
        sortOrders = CalculateRenderingOrder(levelCount);

        // 创建关卡按钮并设置它们的位置
        for (int i = 0; i < levelCount; i++)
        {
            GameObject levelButton = Instantiate(levelButtonPrefab, levelGroup);
            levelButton.gameObject.name = i.ToString();
            levelButton.GetComponentInChildren<Text>().text = i.ToString();
            levelButton.GetComponent<LevelButton>().RegisterLevelSelector(this);
            levelButtons.Add(levelButton);
        }

        UpdateButtonPositions();

        if (nextLevelButton != null)
        {
            nextLevelButton.onClick.AddListener(OnNextLevelButtonClicked);
        }

        if (previousLevelButton != null)
        {
            previousLevelButton.onClick.AddListener(OnPreviousLevelButtonClicked); // 添加上一关按钮的监听器
        }
    }
    void UpdateButtonPositions()
    {
        for (int i = 0; i < levelButtons.Count; i++)
        {
            float angle = (360f / levelButtons.Count) * i;
            float x = Mathf.Sin(angle * Mathf.Deg2Rad) * radius;
            float z = Mathf.Cos(angle * Mathf.Deg2Rad) * radius;

            // 获取计算后的Y轴偏移
            float yOffset = yOffsets[i];

            // 设置按钮位置
            RectTransform rectTransform = levelButtons[i].GetComponent<RectTransform>();
            rectTransform.anchoredPosition3D = new Vector3(x, yOffset, z);

            // 设置Canvas的sortingOrder
            Canvas canvas = levelButtons[i].GetComponent<Canvas>();
            canvas.sortingOrder = sortOrders[i];

            // 设置透明度和缩放值
            SetButtonAppearance(levelButtons[i], sortOrders[i]);
        }

        // 打印最上层和最下层按钮的名称
        PrintTopButtonName();
        PrintBottomButtonName();
    }
    void OnNextLevelButtonClicked()
    {
        RotateButtons(-1);
    }
    void OnPreviousLevelButtonClicked()
    {
        RotateButtons(1);
    }
    Coroutine moveCoroutine;
    public  void MoveLevelToBottom(int index)
    {
        int bottomIndex = sortOrders.IndexOf(sortOrders.Count/2);

        int currentIndex =int.Parse(levelButtons[bottomIndex].name);

        bool isCounterclockwise = true;
        Debug.Log("当前显示 "+currentIndex);
        int movesRequired =index - currentIndex;
        if (movesRequired < 0)
        {
            isCounterclockwise=false;
            movesRequired = -movesRequired;
        }
        Debug.Log("需要偏移"+movesRequired);
        if (moveCoroutine != null)
        {
            return;
        }
        moveCoroutine = StartCoroutine(MoveButtonCoroutine(movesRequired, isCounterclockwise));
    }
    IEnumerator MoveButtonCoroutine(int movesRequired ,bool isCounterclockwise)
    {
        int t = 0;
        int diction = isCounterclockwise ? -1 : 1;
        while (movesRequired>t)
        {
            RotateButtons(diction);
            Debug.Log("移动一次");

            yield return new WaitForSeconds(moveDuration);
            t++;
        }
        moveCoroutine = null;
    }
    void RotateButtons(int direction)
    {
        nextLevelButton.interactable = false;
        previousLevelButton.interactable = false;

        List<Vector3> targetPositions = new List<Vector3>();
        List<float> targetYOffsets = new List<float>();
        List<int> newSortOrders = new List<int>();

        // 计算目标位置、Y轴偏移和顺序
        for (int i = 0; i < levelButtons.Count; i++)
        {
            int targetIndex = (i + direction + levelCount) % levelCount;
            float angle = currentAngle + angleStep * targetIndex;
            float x = Mathf.Sin(angle * Mathf.Deg2Rad) * radius;
            float z = Mathf.Cos(angle * Mathf.Deg2Rad) * radius;
            float yOffset = yOffsets[targetIndex];

            targetPositions.Add(new Vector3(x, yOffset, z));
            targetYOffsets.Add(yOffset);
            newSortOrders.Add(sortOrders[targetIndex]);
        }

        // 更新排序顺序
        sortOrders = newSortOrders;
        for (int i = 0; i < levelButtons.Count; i++)
        {
            Canvas canvas = levelButtons[i].GetComponent<Canvas>();
            canvas.sortingOrder = sortOrders[i];
            // 更新透明度和缩放值
            SetButtonAppearance(levelButtons[i], sortOrders[i]);
        }

        // 平滑移动并更新Y轴偏移和排序顺序
        for (int i = 0; i < levelButtons.Count; i++)
        {
            RectTransform rectTransform = levelButtons[i].GetComponent<RectTransform>();
            int index = i;

            // 平滑移动位置
            rectTransform.DOAnchorPos3D(targetPositions[i], moveDuration).OnComplete(() =>
            {
                // 更新Y轴偏移
                if (index < yOffsets.Count)
                {
                    yOffsets[index] = targetYOffsets[index];
                }
                if (index == levelButtons.Count - 1)
                {
                    Debug.Log("完成移动");
                    // 重新启用按钮
                    nextLevelButton.interactable = true;
                    previousLevelButton.interactable = true;

                    // 打印最上层和最下层按钮的名称
                    PrintTopButtonName();
                    PrintBottomButtonName();
                }
            });
        }

        // 更新角度
        currentAngle += angleStep * direction;
    }
    void PrintTopButtonName()
    {
        int topIndex = sortOrders.IndexOf(0); // 假设排序顺序0是最上层
        if (topIndex >= 0 && topIndex < levelButtons.Count)
        {
            string topButtonName = levelButtons[topIndex].name;
            Debug.Log("最上层按钮的名称: " + topButtonName);
        }
    }
    void PrintBottomButtonName()
    {
        int bottomIndex = sortOrders.IndexOf(sortOrders.Count/2);
        string bottomButtonName = levelButtons[bottomIndex].name;
        Debug.Log("最下层按钮的名称: " + bottomButtonName);
    }
    List<float> CalculateSymmetricYOffsets(int count)
    {
        List<float> offsets = new List<float>();
        float step = yOffsetStep;
        int half = count / 2;
        float y = 0;
        for (int i = 0; i < count; i++)
        {
            if (i != 0)
            {
                y = i * step;
                if (i > half)
                {
                    y = (count - i) * step;
                }
            }
            offsets.Add(y);
        }
        return offsets;
    }
    List<int> CalculateRenderingOrder(int count)
    {
        List<int> order = new List<int>();
        int middle = count / 2;
        int number = 0;
        for (int i = 0; i < count; i++)
        {
            if (i <= middle)
            {
                number = middle - i;
            }
            else
            {
                number = order[count - i];
            }
            order.Add(number);
        }
        return order;
    }
    void SetButtonAppearance(GameObject button, int sortOrder)
    {
        float alpha = Mathf.Lerp(0.3f, 1f, (float)sortOrder / (levelCount / 2));
        float scale = Mathf.Lerp(0.8f, 1f, (float)sortOrder / (levelCount / 2));

        // 设置透明度
        CanvasGroup canvasGroup = button.GetComponent<CanvasGroup>();
        if (canvasGroup != null)
        {
            canvasGroup.alpha = alpha;
        }

        // 设置缩放值
        RectTransform rectTransform = button.GetComponent<RectTransform>();
        if (rectTransform != null)
        {
            rectTransform.localScale = new Vector3(scale, scale, scale);
        }
    }
}

关卡按钮代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class LevelButton : MonoBehaviour
{
    private LevelSelector levelSelector;
   [SerializeField]  private Button levelButton;
    public void RegisterLevelSelector(LevelSelector levelSelector)
    {
        this.levelSelector = levelSelector;
        levelButton.onClick.AddListener(() =>
        {
            levelSelector.MoveLevelToBottom(int.Parse(gameObject.name));

        });
    }

 
}

配置

如果关卡按钮被背景遮住

给添加canvas组件,Overrider Sorting 打开 sort order 为-1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值