在unity中实现分页滚动的效果和吸附功能(UGUI)(1)

在不少游戏中都会有自动滚动的效果
我们这里用UGUI的Scroll View来实现一下
我建议大家在开始做之前 首先先了解一下这个的基本用法
我之前也没写过关于这个的使用方法

然后先给大家一个效果图片(里边的水印大家凑活看一下)
在这里插入图片描述
可以看到 当我们鼠标不移上去的时候 他是自己滚动的 当我们自己鼠标移动上去并且拖拽的时候
他可以被我们拖动 而且 通过代码自动检测区域 然后吸附过去

实现过程

首先我们现在unity中搭建所要的Scrool View
在这里插入图片描述
content上的组件在这里插入图片描述
之后就是代码了 其中计算比较麻烦 仔细看看其实也不是特别复杂

public class PageScrollview : MonoBehaviour,IEndDragHandler,IBeginDragHandler
{
    #region 声明对象
    public enum ScrolType
    {
        //滑动类型(分为两种 横纵两种)
        HorizontalType,
        VerticalType
    }

    ScrollRect rect;
    private int pagecount;//选项个数

    private RectTransform content;
    private   float[] pages;//位置

    [Header("滚动参数")]
    public float movetime = 0.3f;//移动的时间
    public float timer = 0;//计时器
    public float startmovepos;//开始移动的位置
    public int currentindex = 0;//当前所处页数
    private bool ismoving = false;

    private bool isDraging = false;//是否在拖动中


    [Header("自动滚动参数")]
    public  bool isAutoScrol=true ;//是否自动滚动
    public float AutoTime = 2f;//自动滚动时间间隔
    public float autotimer = 0;//自动计时器

    [Header("滑动类型")]
    public ScrolType scroltype = ScrolType.HorizontalType;
    #endregion
    private void Start()
    {
        Init();//初始化
    }
   
    private void Update()
    {
        listenermove();
        listenerAutoScroll();
    }


    private void Init()
    {
        rect = GetComponent<ScrollRect>();
        if (rect == null)
        {
            Debug.LogError("不存在组件ScrollRect");

        }
        content = GameObject.Find("Content").GetComponent<RectTransform>();
        pagecount = content.childCount;//子节点数量
        pages = new float[pagecount];//初始化

        if (pages.Length == 1)
        {
            Debug.LogError("只有一页 不用滚动");
        }
        for (int i = 0; i < pages.Length; i++)
        {

            switch (scroltype)
            {
                case ScrolType.HorizontalType:
                    pages[i] = i * (1.0f / (float)(pagecount - 1));//给位置的数组赋值
                    break;
                case ScrolType.VerticalType:
                    pages[i] = 1 - i * (1.0f / (float)(pagecount - 1));//给位置的数组赋值
                    break;
            }
        }
    }

    private  void listenermove()//监听滑动
    {
        if (ismoving)
        {
            timer += Time.deltaTime * movetime;
           
            //灵魂就在这里
            switch (scroltype)
            {
                case ScrolType.HorizontalType:
                    rect.horizontalNormalizedPosition = Mathf.Lerp(startmovepos, pages[currentindex], timer);
                    break;
                case ScrolType.VerticalType:
                    rect.verticalNormalizedPosition = Mathf.Lerp(startmovepos, pages[currentindex], timer);
                    break;
            }

            if (timer >= 1)
            {
                ismoving = false;
            }
        }
    }

    private void listenerAutoScroll()//自动滑动
    {
        if (isDraging)
        {
            return;
        }
        if (isAutoScrol)
        {
            autotimer += Time.deltaTime;
            if (autotimer > AutoTime)
            {
                autotimer = 0;
                currentindex++;
                currentindex %= pagecount;//取余形成循环
                scrolltopage(currentindex);
            }
        }
    }

    private void scrolltopage(int page)
    {
        ismoving = true;
        this.currentindex = page;
        timer = 0;
       

        switch (scroltype)
        {
            case ScrolType.HorizontalType:
                startmovepos = rect.horizontalNormalizedPosition;
                break;
            case ScrolType.VerticalType:
                startmovepos = rect.verticalNormalizedPosition;
                break;
        }
    }

    //取消拖动的接口
    public void OnEndDrag(PointerEventData eventData)
    {
        int min = 0;
        //计算当最近的一页是哪个
       for(int i = 0; i < pages.Length; i++)
        {
            switch (scroltype)
            {
                case ScrolType.HorizontalType:
                    if (Mathf.Abs(pages[i] - rect.horizontalNormalizedPosition) < Mathf.Abs(pages[min] - rect.horizontalNormalizedPosition))
                    {
                        min = i;
                    }
                    break;
                case ScrolType.VerticalType:
                    if (Mathf.Abs(pages[i] - rect.verticalNormalizedPosition) < Mathf.Abs(pages[min] - rect.verticalNormalizedPosition))
                    {
                        min = i;
                    }
                    break;
            }
        }
        scrolltopage(min);
        isDraging = false;
        autotimer = 0;
    }


    //开始拖动的接口
    public void OnBeginDrag(PointerEventData eventData)
    {
        isDraging = true;
    }
}

里边使用了一个枚举 使用来方便数轴上的修改的

希望这篇博文对你有所帮助
如果有问题或者是合作 主页有我的联系方式(知无不答)

之后我还会持续更新这个方面的内容

猜你喜欢

转载自blog.csdn.net/weixin_44302602/article/details/108037935