Unity实现滚动菜单吸附功能

本文详细介绍了如何在Unity中实现滚动菜单的吸附功能,通过利用Unity的Update函数和数学运算,使得菜单项在滚动到边界时能够平滑吸附,提升用户体验。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using DG.Tweening;

public class CltUGUI : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler, IPointerDownHandler
{
    RectTransform rectTrandform;
    bool isMoving = true;
    bool Drag = false;
    Vector2 DragDelta = Vector2.zero;
    Vector3 lastMouPos;
    Vector3 CurMouPos;
    List<RectTransform> allRect = new List<RectTransform>();
    [SerializeField] int CurIndex = 1;
    [SerializeField] float value;
    Vector2 maxScal = Vector2.zero;
    Vector2 mixScal = Vector2.zero;
    Vector2 endRectPos;
    [SerializeField] RectTransform CurSelet;


    public void OnBeginDrag(PointerEventData eventData)
    {
        Drag = false;

    }
    public void OnDrag(PointerEventData eventData)
    {
        if (eventData.dragging)
        {
            Drag = true;
            DragDelta = eventData.delta;
        }

    }
    public void OnEndDrag(PointerEventData eventData)
    {
        DragDelta = Vector2.zero;
        endRectPos = rectTrandform.anchoredPosition;
        for (int i = 0; i < allRect.Count - 2; i++)
        {
            if ((endRectPos.x - (-i * (maxScal.x + 106.7f - 253))) < (maxScal.x + 106.7f) / 2)
            {
                value = Mathf.Clamp(-(i) * (maxScal.x + 106.7f - 253), -(allRect.Count - 3) * (maxScal.x + 600 - 253), 0f);
                rectTrandform.anchoredPosition = new Vector2(value, rectTrandform.anchoredPosition.y);
                CurIndex = i + 1;
            }
        }
        CtrlSele(CurIndex);
        CtrlScal();
        CtrlRot(CurIndex);
    }
    void Start()
    {
        CurIndex = 1;
        rectTrandform = this.transform.GetChild(0).GetComponent<RectTransform>();
        foreach (RectTransform item in this.transform.GetChild(0).GetComponent<RectTransform>())
        {
            if (item.GetSiblingIndex() == 1)
            {
                item.sizeDelta = new Vector2(1858, 1254);
                maxScal = item.sizeDelta;
            }
            else
            {
                item.sizeDelta = new Vector2(1605f, 1254);
                mixScal = item.sizeDelta;
            }
            allRect.Add(item);
        }
        CtrlRot(CurIndex);
        GlobalEntity.GetInstance().AddListener<int>(MenuEvent.ChangeMenu, ChangeMenu);
        GlobalEntity.GetInstance().AddListener<bool>(MenuEvent.MainMenu, CtrlMainMenuActive);

    }

    // Update is called once per frame
    void Update()
    {
        if (Drag && isMoving)
        {
            float Offect = rectTrandform.anchoredPosition.x;
            Offect += DragDelta.x;
            value = Mathf.Clamp(Offect, -(allRect.Count - 3) * (maxScal.x + 106.7f - 253), 0f);
            rectTrandform.anchoredPosition = new Vector2(value, rectTrandform.anchoredPosition.y);
            SliderCtrlRot();
        }
        MouseMoving();
    }
    void MouseMoving()
    {

        if (Input.GetMouseButtonDown(0))
        {
            lastMouPos = Input.mousePosition;
        }

        if (Input.GetMouseButton(0))
        {
            CurMouPos = Input.mousePosition;
            if (Vector3.Distance(lastMouPos, CurMouPos) > 0)
            {
                isMoving = true;
            }
            else
            {
                isMoving = false;
            }

            lastMouPos = CurMouPos;
        }
        if (Input.GetMouseButtonUp(0))
        {
            isMoving = false;
        }
    }

    //控制当前选择
    void CtrlSele(int index)
    {
        index = ((index - 1) * 200) + 30;
        index = Mathf.Clamp(index, 30, 1030);
        Tween t = CurSelet.DOAnchorPosX(index, 0.2f);
        t.OnComplete(() =>
        {

            t.Kill();
        });

    }

    //大小转变
    void CtrlScal()
    {
        for (int i = 0; i < allRect.Count; i++)
        {
            if (i == CurIndex)
            {
                Tween t = allRect[i].DOSizeDelta(maxScal, 0.2f);
                t.OnComplete(() =>
                {
                    t.Kill();
                });
            }
            else
            {
                Tween t = allRect[i].DOSizeDelta(mixScal, 0.2f);
                t.OnComplete(() =>
                {

                    t.Kill();
                });
            }
        }
    }
    //数字控制转换
    void ChangeMenu(int index)
    {
        float Offect = -(index - 1) * (maxScal.x + 106.7f - 253);
        CurIndex = index;
        rectTrandform.anchoredPosition = new Vector2(Offect, rectTrandform.anchoredPosition.y);
        CtrlScal();
        CtrlSele(index);
        CtrlRot(CurIndex);
    }

    private void OnDestroy()
    {
        GlobalEntity.GetInstance().RemoveListener<int>(MenuEvent.ChangeMenu, ChangeMenu);
        GlobalEntity.GetInstance().RemoveListener<bool>(MenuEvent.MainMenu, CtrlMainMenuActive);
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        GlobalEntity.GetInstance().Dispatch(MenuEvent.HideSecondaryNavigation);
    }

    void CtrlMainMenuActive(bool ison)
    {
        this.gameObject.SetActive(ison);
    }

    void CtrlRot(int index)
    {
        allRect[index].DORotate(new Vector3(0, 0, 0), 0.2f);
        for (int i = 0; i < allRect.Count; i++)
        {
            if (i < CurIndex)
            {
                allRect[i].DORotate(new Vector3(0, -45, 0), 0.2f);
            }
            if (i > CurIndex)
            {

                allRect[i].DORotate(new Vector3(0, 45, 0), 0.2f);
            }
        }

    }


    void SliderCtrlRot()
    {
        Vector2 pos = rectTrandform.anchoredPosition;
        float Space = maxScal.x + 106.7f - 253;
        allRect[CurIndex + 1].localEulerAngles = new Vector3(0, (((CurIndex * Space - Mathf.Abs(pos.x)) / Space)) * 45, 0);
        //左小右大
        if (Mathf.Abs(rectTrandform.anchoredPosition.x) > (CurIndex-1) * Space)
        {
            //左滑
            allRect[CurIndex].sizeDelta = new Vector3((((CurIndex * Space - Mathf.Abs(pos.x)) / Space) * 253) + 1605, 1254, 0);
            //逐步减少
            allRect[CurIndex + 1].sizeDelta = new Vector3(((1 - ((CurIndex * Space - Mathf.Abs(pos.x)) / Space)) * 253) + 1605, 1254, 0);
        }
        else if (Mathf.Abs(rectTrandform.anchoredPosition.x) < (CurIndex-1) * Space)
        {
            Debug.Log(((CurIndex * Space - Mathf.Abs(pos.x)) / Space)+"往右滑动");
            allRect[CurIndex].sizeDelta = new Vector3(((2 - ((CurIndex * Space - Mathf.Abs(pos.x)) / Space)) * 253) + 1605, 1254, 0);
            allRect[CurIndex-1].sizeDelta = new Vector3(((((CurIndex * Space - Mathf.Abs(pos.x)) / Space)-1) * 253) + 1605, 1254, 0);
        }
        allRect[CurIndex].localEulerAngles = new Vector3(0, -(1 - ((CurIndex * Space - Mathf.Abs(pos.x)) / Space)) * 45, 0);
        allRect[CurIndex - 1].localEulerAngles = new Vector3(0, -(1 + (1 - ((CurIndex * Space - Mathf.Abs(pos.x)) / Space))) * 45, 0);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一丁目赠我

谢谢你的打赏,感谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值