Unity-UGUI-无限循环列表
前言:项目准备新增一个竞技场排行榜,策划规定只显示0-400名的玩家。我一想,生成四百个游戏物体,怕不是得把手机给卡死?回想原来在GitHub上看到过一个实现思路就是无限循环列表,所以就想自己试试。公司用的是NGUI,花了1个多小时还是没做出来,但是基本思路有了,又到了下班时间,不想赖在公司怕带坏了风气,就回来用自己电脑上的UGUI实现。
实现思路:假设屏幕只显示五行玩家排名,那么就预备十行,上面多两行,下面多三行。每次移动单位距离(一行玩家排名占高),就移动一端的物体到另一端,这样就实现了无限循环。
实现过程:
一、搭建UI
1.先在UI搭建好面板,其中SV物体添加RectMask2D组件,模拟ScrollView的裁剪;将无限循环列表脚本挂在SV上
2.在SV下添加一个Grid(Grid并非组件而是名字)物体,用于模拟移动整个列表
3.Grid物体下添加十个Item,前面隐藏两个,中间显示五个,后面隐藏三个。为什么要多放几个呢?因为想滑动时更加顺滑
二、实现LoopScroll类
1.类中包含字段int[] keys,用于记录下标变换;Dictionary<int,Transform> dic,用于保存下标与Transform之间的映射关系;int gap,用于计算Transform之间应该间隔的距离
2.类中包含方法DownMove(),列表下移时调用;UpMove(),列表上移时调用
public class LoopScroll
{
private Dictionary<int, Transform> dic;
private int[] keys;
private float gap = 0;
public LoopScroll(float gap,params Transform[] items)
{
this.gap = gap;
dic = new Dictionary<int, Transform>(items.Length);
keys = new int[items.Length];
for (int i = 0; i < items.Length; i++)
{
dic.Add(i, items[i]);
keys[i] = i;
}
}
private LoopScroll()
{ } public void DownMove()
{
//TODO 将顶部Trs移动到尾部
int top = keys[0];
for (int i = 0; i < keys.Length-1; i++)
{
keys[i] = keys[i + 1];
}
keys[keys.Length - 1] = top;
int key = keys[keys.Length - 2];
Vector3 pos = dic[top].localPosition;
pos.Set(pos.x, dic[key].localPosition.y - gap, pos.z);
dic[top].localPosition = pos;
} public void UpMove()
{
//TODO 将尾部Trs移动到顶部
int down = keys[keys.Length - 1];
for (int i = keys.Length-1; i > 0; i--)
{
keys[i] = keys[i - 1];
}
keys[0] = down;
int key = keys[1];
Vector3 pos = dic[down].localPosition;
pos.Set(pos.x, dic[key].localPosition.y+gap, pos.z);
dic[down].localPosition = pos;
}
}
讲解:每次移动时,对keys做循环类似的操作,操作完keys后,再通过下标获取对应的Transform,将Transform插入到对应的Position。为什么不直接用Transform[] 数组处理呢?因为我担心移动时会出现,因引用类型的特性,而导致位置混乱,还不如多用一个keys,keys是值类型,操作简单。
三、具体实现
1.因为我是自己做的滑动,所以代码里需要自己写。当按下鼠标左键,并且拖动一定距离时,触发移动方法。在移动方法中判断移动的偏移值的正负性,是向上?还是向下?然后move的position是加还是减?
2.move移动后,判断move移动的距离是否大于等于单位距离(一个item的高),如果移动了单位距离,则触发循环方法。移动的距离是正还是负?可得知是执行DownMove还是UpMove。
public class TestDragScroll : MonoBehaviour
{
public Transform startItem;
public List<Transform> listTrs;
public Transform move;
private const float GAPY = 110f;
private const float PerMoveDetal = 110f;
private LoopScroll scorll; private float prePosY; private float movePrePosY; private void OnValidate()
{
Vector3 startPos = startItem.localPosition;
float startY = startPos.y;
for (int i = 0; i < listTrs.Count; i++)
{
listTrs[i].localPosition = new Vector3(startPos.x, startY, startPos.z);
startY -= GAPY;
}
}
// Start is called before the first frame update
void Start()
{
scorll = new LoopScroll(GAPY, listTrs.ToArray());
prePosY = Input.mousePosition.y;
movePrePosY = move.localPosition.y;
} // Update is called once per frame
void Update()
{
if (Input.GetMouseButton(0))
{
float detal = Input.mousePosition.y - prePosY;
if (Mathf.Abs(detal)>=1f)
{
prePosY = Input.mousePosition.y;
Vector3 pos = move.localPosition;
if (detal>0)
{
pos.Set(pos.x, pos.y + 4f, pos.z);
}
else
{
pos.Set(pos.x, pos.y - 4f, pos.z);
}
move.localPosition = pos;
}
} float moveDetal = move.localPosition.y - movePrePosY;
if (Mathf.Abs(moveDetal)>=PerMoveDetal)
{
if (moveDetal>0)
{
scorll.DownMove();
Debug.Log("Down");
}
else
{
scorll.UpMove();
Debug.Log("Up");
}
movePrePosY = move.localPosition.y;
}
}
}
四、项目实现效果
在自己电脑上用UGUI实现了并非适合项目场景。最终实现时,因为Update中判断移动距离的方法并不可靠,移动距离每次不可能都=113,而我的判断时只要>=113就执行一次循环,那么我滑动226呢?还是只移动了一个item。所以此方法行不通。我的主程告诉我,400个item并不一定要用无限循环列表,如果短时间内做不出来就不要再做了,项目进度要紧。建议我用协程分帧生成400个item,不会卡住的。由于我心烦气乱,最终没有做循环列表的方案。
但是循环列表的雏形是有的,以前都只知道循环列表的思路而未真正实现过,这次实践是第一次,收获颇丰,特写随笔记录
Unity-UGUI-无限循环列表的更多相关文章
- Unity UGUI —— 无限循环List
还记得大学毕业刚工作的时候是做flash的开发,那时候看到别人写的各种各样的UI组件就非常佩服,后来自己也慢慢尝试着写,发现其实也就那么回事.UI的开发其实技术的成分相对来说不算多,但是一个好的UI是 ...
- Unity UGUI —— 无限循环List(转载)
using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEngine.UI; ...
- unity 背景无限循环滚动效果
背景无限循环滚动效果如下示: 步骤如下: 导入背景图片后,设置图片的格式,如下图: 2.图片格式也可以设置是Texture格式,但是Wrap Mode 一定要是Repeat[重复发生]:然后记得App ...
- 详细分析Android viewpager 无限循环滚动图片
由于最近在忙于项目,就没时间更新博客了,于是趁着周日在房间把最近的在项目中遇到的技术总结下.最近在项目中要做一个在viewpager无限滚动图片的需求,其实百度一下有好多的例子,但是大部分虽然实现了, ...
- AlloyTouch之无限循环select插件
写在前面 当滚动的内容很多,比如闹钟里设置秒,一共有60项.让使用者从59ms滚回01ms是一件很痛苦的事情,所以: 在列表项太多的情况下,我们希望能够有个无限循环的滚动.00ms和01ms是无缝链接 ...
- Unity UGUI图文混排源码(二)
Unity UGUI图文混排源码(一):http://blog.csdn.net/qq992817263/article/details/51112304 Unity UGUI图文混排源码(二):ht ...
- 自定义完美的ViewPager 真正无限循环的轮播图
网上80%的思路关于Android轮播图无限循环都是不正确的,不是真正意义上的无限循环, 其思路大多是将ViewPager的getCount方法返回值设置为Integer.MAX_VALUE, 然后呢 ...
- 理解 vue-router的beforeEach无限循环的问题
在理解beforeEach无限循环之前,我们先来看一下beforeEach相关的知识点,该篇文章的项目是基于 express+vue+mongodb+session实现注册登录 这篇文章项目基础之上进 ...
- C#开发Unity游戏教程循环遍历做出判断及Unity游戏示例
C#开发Unity游戏教程循环遍历做出判断及Unity游戏示例 Unity中循环遍历每个数据,并做出判断 很多时候,游戏在玩家做出判断以后,游戏程序会遍历玩家身上大量的所需数据,然后做出判断,即首先判 ...
随机推荐
- 关于websocket制作聊天室的的一些总结
websocket的总结 在一个聊天室系统中,常常使用websocket作为通信的主要方式.参考地址:https://www.jianshu.com/p/00e... 关于自己的看法:websocke ...
- hive启动出错
Hive启动报错:java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument - 狗子的进阶史 - ...
- MapReduce在集群执行任务时报错:Initialization of all the collectors failed. Error in last collector was:java.lang.ClassCastException
报错信息详细: Error: java.io.IOException: Initialization of all the collectors failed. Error in last colle ...
- java中请给出例子程序:找出n到m之间的质数。
9.1 找出100到200之间的质数. public class Test { public static void main(String[] args){ for (in ...
- Spring 和 SpringMVC 常用注解和配置(@Autowired、@Resource、@Component、@Repository、@Service、@Controller的区别)
Spring 常用注解 总结内容 一.Spring部分 1.声明bean的注解 2.注入bean的注解 3.java配置类相关注解 4.切面(AOP)相关注解 5.事务注解 6.@Bean的属性支持 ...
- oracle查询出现科学计数法问题
- eclipse-java-2018-09-win32-x86_64配置tomcat(内含更新eclipse,如何解决添加时找不到最新tomcat版本)
我下的是eclipse精简版,建议下载企业版,可以省略后面的很多步骤(其中的辛酸...) 这里就是说明下载精简版的eclipse如何配置tomcat的步骤,其实还是更新eclipse的步骤 1.首先点 ...
- Docker部署Nginx启动成功,浏览器拒绝访问
今天下午部署完tomcat和mysql之后就接着部署Nginx,本以为Nginx也和之前两个一样简单,但是就因为标题这个问题,花费了我一个小时纠错. 过程复现: 解决完上一篇博客(https://ww ...
- el-menu菜单 -- unique-opened 子菜单唯一性失效
总结: 点击的是 el-sub-menu . 所以 el-sub-menu 的唯一性是必须的.否则 unique-opened 属性不生效
- 广度优先搜索 BFS 学习笔记
广度优先搜索 BFS 学习笔记 引入 广搜是图论中的基础算法之一,属于一种盲目搜寻方法. 广搜需要使用队列来实现,分以下几步: 将起点插入队尾: 取队首 \(u\),如果 $u\to v $ 有一条路 ...