在b站中看到的视频,想在此记录一下。
实现原理:大概就是,滑动时,找到距离校准点最近的物体,然后获取这个物体的序号(也可以是其他的,只要是能记录,根据自己的需求来),再将scroll对准这个物体即可。
1、首先在场景中创建一些游戏对象2、其中,ItemSlot是Image将它的背景图片和透明度按照自己喜好调整,当然要是有效果更好的
image赋值上去也行。创建一个Image作为ItemSlot的子物体,作为Item,然后HighLIg就是中间那个亮一点的框,用来表示强调选中的Item。LabelLiterName是显示选中物体的信息。
3、UI的准备工作:(1)原始的scrollview里面有两个水平和垂直滑动轴,此处我用不到就可以删除(Scrollbar Horizontal 和 Scrollbar Vertical),同时,在scroll rect里面的取消勾选vertical,因为这里我们只需要水平就行
(2)在content里面添加两个组件Horizontal Layout Group(用来管理content里面的内容)和content size fitter(可加可不加,加了是因为里面的Horizontal fit可以帮助我们直接设置好内容物体的最佳位置)
附上代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SnapToItem : MonoBehaviour
{
//创建变量
public ScrollRect ScrollRect; //获取ScrollView的transform的组件
public RectTransform contentPanel; //获取content的transform的组件
public RectTransform sampleListItem; //获取ItemSlot的transform组件
public HorizontalLayoutGroup HLG; //获取在content组件里 HorizontalLayoutGroup组件
public Text nameLabel;
public string[] itemNames;//Item名字
float snappingSpeed;//当前速度
public float snappingForce;//捕捉力
bool isSnapping;//是否被滑动
void Start()
{
isSnapping = false;
}
// Update is called once per frame
void Update()
{
//取得最近的Item序号
//0减是因为从左往右滑动,contentPanel.localPosition.x逐渐变负数,所以减来获得正数
//算式说明:因为每次滑动的单元都是一个Item的宽度和一个spacing的长度,所以用contentPanel.localPosition.x的长度比上
//前者的总长度就能够得出是几倍的关系,从而记作是序号
int currentItem = Mathf.RoundToInt((0 - contentPanel.localPosition.x / (sampleListItem.rect.width + HLG.spacing)));
//开始捕捉Item
if (ScrollRect.velocity.magnitude < 200 && !isSnapping)
{
ScrollRect.velocity = Vector2.zero;
snappingSpeed += snappingForce * Time.deltaTime;
isSnapping = false; //此时停止捕捉
contentPanel.localPosition = new Vector3(//用Mathf.MoveTowards平滑的移动
Mathf.MoveTowards(contentPanel.localPosition.x, 0 - (currentItem * (sampleListItem.rect.width + HLG.spacing)), snappingSpeed),
contentPanel.localPosition.y,
contentPanel.localPosition.z);
//如果Item停留在HightLight上面
if (contentPanel.localPosition.x == 0 - (currentItem * (sampleListItem.rect.width + HLG.spacing)))
{
isSnapping = true; //此时可以开始捕捉
//显示Ite名称
nameLabel.text = itemNames[currentItem];
}
}
//未捕捉到
if (ScrollRect.velocity.magnitude > 200)
{
isSnapping = false;
snappingSpeed = 0f;
nameLabel.text = "--------";
}
}
}
代码的赋值情况