使用Unity3d和C#进行背包滚动(可设置多行)

引入

我们在玩游戏时,大多数游戏都有背包这个界面,譬如王者荣耀的背包,那么多的格子,如果完全加载出来是非常消耗性能的。我们在使用Unity3d和C#结合进行游戏开发时,也少不了背包这个功能,那么今天就来教大家先实现一个简单的背包滚动 (本人小白,不对的地方还请大佬指正·-·)

什么是无限滚动

我们加载完背包的时候,如果有1000的背包容量,那么我们没必要完全加载这1000个背包格子,我们可以设计20个格子,然后让这20个格子滚动起来,只改变其中的信息,这样就减少了CPU的加载消耗,可以说非常节省性能。

代码设计思路

滚动的思路的主干思路就是设计一个Gameobject类型的list,作用是按顺序存储当前显示的背包格子,同时设定一个firstindex和lastindex作为最开始显示和最后显示的索引,在预设体生成的时候让其按照顺序加到list里面,同时让lastindex++。在左右滑动滑出去的时候,会将消失的部分补到显示的部分。下面是详细思路

一、设计Scrollview部分

1.思路说明

首先我们要用到的是ScrollView这个组件,这个组件中包括了三个部分,分别是Viewport、Scrollbar Horizontal以及Scrollbar Vertical,其中Scrollbar Horizontal和Scrollbar Vertical分别表示水平和垂直的移动滑块(好不专业),Viewport中的Content就是显示各种东西的地方了。
简单介绍完这个组件以后,下面说一下思路:
1.首先要设计好一个存放所有数据的大小(设置Viewport里面的content大小即可),因为我设计的是左右滑动,这里就需要设置:
(1)长度是(一个预设体的长度)×(总预设体个数/行数)
(2)高度是(一个预设体的高度)× (行数)

2.设计好一个显示的区域(直接设置ScrollView的大小)
(1)长度是(一个预设体的长度)×(显示的预设体个数/行数)
(2)高度是(一个预设体的高度)× (行数)

3.设计好Viewport的content的锚点 (如下图),从而实现左对齐 在这里插入图片描述

3.设计好一个背包格子的预设体(一定要有Text组件)

2.代码部分

获取组件

superScrollRect = GetComponent<ScrollRect>();//获取到ScrollerView上的ScrollRect
superRect = superScrollRect.content.transform.GetComponent<RectTransform>();//获取到ScrollRect上的content的RectTransform组件

设置滚动条content的宽度、锚点以及ScrollView的长宽,当然锚点要设置在(0, 0)和(0, 1)的位置上,这样可以让content进行左对齐

   public void SetContentWidth()
    {
        transform.GetComponent<RectTransform>().sizeDelta = new Vector2(itemWidth * maxItemNum / queue, (_obj.GetComponent<RectTransform>().sizeDelta.y + 20) * queue);
        superRect.sizeDelta = new Vector2(itemNum * itemWidth / queue , 0);
        superRect.anchorMin = new Vector2(0, 0);
        superRect.anchorMax = new Vector2(0, 1);
    }

二、初始化生成预设体

1.思路说明

我们是要做自定义多行的滚动,那么我们就需要一个二维数组进行生成预设体以及定义其锚点等。但是因为我们是横向滚动,我们的生成顺序应当是从上到下,所以内层的循环按照行数循环,外层则是根据每行的预设体个数+1进行循环的(至于为什么加一,嘿嘿嘿,大家可以先进行思考,下文进行揭晓),为了方便大家理解这个循环的方式,附加一张图
在这里插入图片描述
那么循环说完了,接下来说循环内部我们要干的事情,也就是生成、对背包赋值、以及设置位置和将游戏对象按顺序加到显示list当中的操作了,生成,赋值大家根据代码研究一下吧,有点简单,位置重点说一下,我设置位置的思路是首先设置背包格子的锚点,然后设置其锚点位置的,锚点位置可以理解以锚点的中心坐标为原点的相对位置。
要补充的是我们需要在生成的过程中,让lastindex随着生成的循环而加一最终使得lastindex指向显示的最后一个格子
在这里插入图片描述

2.代码部分
     public void InsCountitemWidth()
    {
        int needItemNum = Mathf.Clamp(maxItemNum, 0, itemNum);
        for (int j = 0; j < needItemNum / queue + 1; j++)
        {
            for (int i = 0; i < queue; i++)
            {

                //生成
                GameObject obj = Instantiate(_obj, superRect);
                //取名和赋值
                obj.name = (j * queue + i).ToString();
                obj.transform.Find("Text").GetComponent<Text>().text = obj.name;
                //设定锚点以及锚点位置
                RectTransform _rect = obj.transform.GetComponent<RectTransform>();
                _rect.pivot = new Vector2(0, 1);
                _rect.anchorMin = new Vector2(0, 1);
                _rect.anchorMax = new Vector2(0, 1);
                _rect.anchoredPosition = new Vector2(j * itemWidth, -itemHeight * i);
                //将游戏对象按顺序加到显示list当中
                item.Add(obj);


            }
        }
        //设置最后的索引
        lastIndex = needItemNum - 1 + queue;
    }
    }

三、左右滑动的过程

1.添加滑动时的监听事件介绍

滑动事件使用以下的代码来添加
ScrollRect.onValueChanged.AddListener((Vector2 vec) => {});
这句话的意思我也不是很懂,然后就从API截屏给大家康康
在这里插入图片描述
其中需要添加的委托必须是带有一个Vector2类型参数的委托,这个参数表示的就是Scrollbar中Scrollbar组件的value值。

2.监听事件思路

我们首先要思考,什么时候需要一列消失,然后替换到最后去
下图可能会给你很好的灵感
在这里插入图片描述
在这里插入图片描述
从上面第一张图滑到第二张图的时候,第一列的0, 1, 2应当消失,那这个点我们应该怎么去判断呢?还记得一开始我们设定过一个content吗,它代表着总数据的长度,我们可以用content.anchoredPosition.x(content的位置)的绝对值跟一个预设体宽度×当前显示的第一个索引/行数作比较(这是多行的关键),如果前者大于后者,那么代表着已经到达第二张图的位置,然后我们就写一个循环(从上到下依次)循环里面我们要记录下item[0],也就是第一个显示索引的gameobject,然后
1.将其从item中移除,再添加到最后
2.设定其位置是x = (lastindex+1)/行数×宽度,y = 其之前的y
3.让firstindex和lastindex分别加一也就是指针后移
4.修改文本以及数据
以上是从左往右滑的思路,从右往左的思路大家可以参考以上思路和下面的代码进行自己的归纳整理。

3.代码部分
     private void OnScrollMoveWidth(Vector2 pVec)
    {
        //从左往右
        while (Mathf.Abs(superRect.anchoredPosition.x) > itemWidth * (firstIndex / queue ) && lastIndex < itemNum - 1)
        {
            for (int i = 0; i < queue; i++)
            {
                GameObject _first = item[0];
                RectTransform _firstRect = _first.GetComponent<RectTransform>();
                item.RemoveAt(0);
                item.Add(_first);
                _firstRect.anchoredPosition = new Vector2(((lastIndex + 1) / queue) * itemWidth, _firstRect.anchoredPosition.y);
                firstIndex++;
                lastIndex++;
                //修改显示
                _first.name = lastIndex.ToString();
                _first.transform.Find("Text").GetComponent<Text>().text = _first.name;

            }
        }
        //从右往左
        while (Mathf.Abs(superRect.anchoredPosition.x) < itemWidth * firstIndex / queue && firstIndex > 0)
        {
            for (int i = 0; i < queue; i++)
            {
                GameObject _last = item[item.Count - 1];
                RectTransform _lastRect = _last.GetComponent<RectTransform>();
                item.RemoveAt(item.Count - 1);
                item.Insert(0, _last);
                _lastRect.anchoredPosition = new Vector2(((firstIndex - 1) / queue) * itemWidth, _lastRect.anchoredPosition.y);

                firstIndex--;
                lastIndex--;
                //修改显示
                _last.name = firstIndex.ToString();
                _last.transform.Find("Text").GetComponent<Text>().text = _last.name;
            }

        }
    }

巩固和提升

下面发的脚本文件除了本文讲的左右的滑动还额外写了一个上下单行滑动的代码,感兴趣的朋友可以将此代码改进!

脚本文件地址及使用方法

这是我第一篇文章,写的不大好希望大家见谅,然后以上表述可能有不清晰的地方,那么我会弄一个脚本文件,脚本文件使用方法:
1.直接挂载在Scrollview上
2.创建一个带有text组件的预设体拖到脚本上去

百度网盘脚本地址
链接:https://pan.baidu.com/s/1fRcbv2TYysgmtx0gNph8Tw
提取码:iikp
百度网盘unitypackage地址
链接:https://pan.baidu.com/s/1O2PcVcehMeg9B05hqOuzAA
提取码:ocwn

希望大家能从本文学到一些东西!蟹蟹!
——PM翔翔

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值