如何优化UGUI的ugui scrollrect 优化

Unity3D UGUI中ScrollRect的一些知识点 - 推酷
Unity3D UGUI中ScrollRect的一些知识点
这几天在公司里,项目需要将游戏游戏中的2D城堡界面在拉动的时候显示出3D的拉近效果。当时是在Cocos2d-x下实现的。回家的时候自己重新用Unity实现的了一遍。
虽然现在Unity已经到了5.0时代,从4.6时代起Unity就开始支持原生2D了,网络上大部分的教程还是NGUI。毕竟原生的也是开源的,详细以后也会慢慢取代NGUI。
需要在拉动的过程中显示出由远及近不通层次的效果,自然想到了利用Scroll类型的控件。Unity中原生2D中使用到的时ScrollRect组件。
在Canvas中,我新建了一个ScrollRect。修改名字为ScrollView。 ScrollRect 的使用十分的简单, Content 与滚动内容进行关联后就可以直接使用。 Horizontal,Vertical 设置十分允许在水平、垂直方向滚动。 MovementType 可以设置3中滚动类型。 Inertia 可以控制是否在拖动结束后继续惯性滑行一段距离。具体参数说明Unity官方有详细的API资料。
创建ScrollView成功之后,添加了需要滚动的控件。我要做的是在ScrollRect滚动的时候,根据滚动的情况对其内部控件进行缩放。
在insparcter面板的右下角同时列出了ScrollRect在运用工程中可以使用的控件。
我需要在拖动的时候进行操作,这里就需要用到OnDrag事件。
1 using UnityE
2 using UnityEngine.UI;
3 using UnityEngine.EventS
4 using System.C
6 public class BackgroundManager : MonoBehaviour,IDragHandler
ScrollRect scrollR
public float startNum = 263f;
public float scaleArg1 = 0.5f;
public float scaleArg2 = 0.2f;
public float scaleArg3 = 0.1f;
public GameO
public GameO
public GameO
void Start ()
scrollRect = gameObject.GetComponent&ScrollRect& () as ScrollR
content = scrollRect.
public void OnDrag (PointerEventData data)
//Debug.Log (content.position);
float changeScale1 = GetChangeScale (content.position.y, 1);
float changeScale2 = GetChangeScale (content.position.y, 2);
float changeScale3 = GetChangeScale (content.position.y, 3);
buttom.gameObject.transform.localScale =
new Vector3 (changeScale1, changeScale1, 1);
middle.gameObject.transform.localScale =
new Vector3 (changeScale2, changeScale2, 1);
top.gameObject.transform.localScale =
new Vector3 (changeScale3, changeScale3, 1);
float GetChangeScale (float changeCondition, int position)
float changeScale = 1f;
switch (position) {
changeScale = 1 + Mathf.Sin ((startNum - changeCondition) * Mathf.PI / 224) * scaleArg1;
changeScale = 1 + Mathf.Sin ((startNum - changeCondition) * Mathf.PI / 224) * scaleArg2;
changeScale = 1 + Mathf.Sin ((startNum - changeCondition) * Mathf.PI / 224) * scaleArg3;
changeScale = 1 + Mathf.Sin ((startNum - changeCondition) * Mathf.PI / 224);
return changeS
我这里只由于只使用到OnDrag,所以只继承了 IDragHander 接口。
将写好的脚本添加到ScrollRect中,初始化运行后就可以看到效果了。
使用到了滚动层,在实际的应用中自然少不了遮罩的问题。在之前的博文中,我有写到了文字跑马灯的实现。其实可以直接使用ScrollRect+遮罩的方式进行实现。
原生2D中的 Mash 可以很方便的实现。在Mash中添加 Image 可以控制Mash的样式。
也可以设置Image的 Source Image 自定义遮罩的形状。
原生的ScrollRect用起来还是比较方便的,游戏开发中道具的展示,场景的切换控制都常需要用到。
有需要的朋友可以下载源代码自己运行:下载
博客地址:
博客版权: 本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。
如文中有不妥或者错误的地方还望高手的指出,以免误人子弟。如果觉得本文对您有所帮助请【推荐】一下!如果你有更好的建议,不妨留言一起讨论,共同进步! 再次感谢您耐心的读完本篇文章。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致您当前的位置: &
如何优化UGUI的ScrollRect
查看: 431|
|原作者: 钱康来
UGUI的ScrollRect在加载太多物体的时候,第一次弹出界面会非常卡顿,而且不在界面里的内容依然会参与绘制,导致毫无意义的浪费。笔者对此进行了一番研究,并将心得与大家分享。介绍每个元素知道自己的序号,可以根据需要修改自己的内容、大小等信息。此外支持了ScrollBar,支持横向、纵向及正反向。在关闭Mask后可以看到,只有当需要的时候才动态实例化元素,使用完后回收。最原始版本的代码是@ivomarel的InfinityScroll。我改到后来,基本和原始版没啥相同的了。原代码使用了sizeDelta作为大小,但是这个在锚点不重合情况下是不成立的支持了GridLayout在启动时检查锚点和轴心,方便使用修复了原代码在往前拖拽会卡顿的问题优化代码,提升性能支持反向滑动支持ScrollBar (在无尽模式下不起作用;如果元素大小不一致会出现滚动条瑕疵)此外,我修改了Easy Object Pool作为池子,循环利用元素。警告: 为了解决原始代码回拉卡顿的问题,我直接复制了一份UGUI中的ScrollRect代码,而没有继承。这是因为老的做法是在onDrag里停止并立即启动滚动,而我通过修改两个私有变量保证了滑动顺畅。所有我的代码都用==========LoopScrollRect==========这样的注释包起来,维护起来就像打patch了。框架思路和UGUI自带的ScrollRect有所不同,我拆分出了LoopHorizontalScrollRect和LoopVerticalScrollRect两个类,分别代表水平滚动条和水平滚动条。下面我们以LoopVerticalScrollRect为例,水平版本类似。1. 判定cell大小LoopScrollRect要解决的核心问题是:如何计算每个元素的大小。这里我使用了Content Size Fitter配合Layout Element来控制每个cell的长宽,因此对于GridLayout直接取高度,否则取Preferred Height。需要注意的是,除了元素本身的大小之外,我们还要将padding考虑进去。protected override float GetSize(RectTransform item){
float size = contentS
if (m_GridLayout != null)
size += m_GridLayout.cellSize.y;
size += LayoutUtility.GetPreferredHeight(item);
}}这个其实也是最核心的一个地方:在能够准确计算格子大小的基础上,后续工作就好实现了。2. 如何优雅的增删元素对于每个ScrollRect,其实只需要考虑在头部和尾部是否需要增加或者删除元素。在这里以头部的各种情况为例进行解释,因为在正向滑动情况下,必须保证在修改元素之后整个ScrollRect内容显示一致不跳变;这些情况比尾部处理会麻烦一些。NewItemAtStart函数实现了在头部增加一个(或一行,针对GridLayout)元素,并返回这些元素的高度;DeleteItemAtStart代表删除头部的一个元素。需要注意的是,在修改头部元素之后要及时修改content的anchoredPosition,这样才能保证整个内容区域不会因为多了或者少了一行而产生跳变。protected float NewItemAtStart(){
float size = 0;
for (int i = 0; i & contentConstraintC i++)
// Get Element from ObjectPool
if (!reverseDirection)
// Modify content.anchoredPosition
}}protected float DeleteItemAtStart(){
float size = 0;
for (int i = 0; i & contentConstraintC i++)
// Return Element to ObjectPool
if (!reverseDirection)
// Modify content.anchoredPosition
}}3. 何时需要增删元素这里需要有两个概念viewBounds和contentBounds:前者是指ScrollRect本身的大小,一般也对应Mask;后者是指ScrollRect里所有cell组成的内容部分的大小。在这个基础上就简单了:如果contentBounds的最上面比viewBounds的最上面要低,那么尝试在顶部增加元素;如果contentBounds的最上面比viewBounds的最上面高很多,那么尝试删除元素。protected override bool UpdateItems(Bounds viewBounds, Bounds contentBounds){
bool changed =
// cases for NewItemAtEnd/DeleteItemAtEnd
if (viewBounds.max.y & contentBounds.max.y - 1)
float size = NewItemAtStart();
if (size & 0)
else if (viewBounds.max.y & contentBounds.max.y - threshold)
float size = DeleteItemAtStart();
if (size & 0)
}}4. 对象池交互在新建cell和销毁cell的时候,使用对象池来避免内存碎片;同时这里使用了SendMessage来向每个cell发送必须的信息,保证数据的正确性。private void SendMessageToNewObject(Transform go, int idx){
go.SendMessage("ScrollCellIndex", idx);}private void ReturnObjectAndSendMessage(Transform go){
go.SendMessage("ScrollCellReturn", SendMessageOptions.DontRequireReceiver);
prefabPool.ReturnObjectToPool(go.gameObject);}private RectTransform InstantiateNextItem(int itemIdx){
RectTransform nextItem = prefabPool.GetObjectFromPool(prefabPoolName).GetComponent&RectTransform&();
nextItem.transform.SetParent(content, false);
nextItem.gameObject.SetActive(true);
SendMessageToNewObject(nextItem, itemIdx);
return nextI}5. 滚动条相关这块我其实是估算的,根据当前的长度和当前元素个数/总个数按照比例缩放,这个在所有cell大小一致的情况下是没有问题的;但是如果大小不一致我就无法得到精确结果,所以会产生一定抖动。我暂时没有更好办法,因为得到的信息就是不够用。6. 其他细节我主要遇到了两个坑:增加或者删除元素之后,有时候需要强行调用Canvas.ForceUpdateCanvases()刷新下。注意不要在Build Canvas过程中再次修改元素,从而再次触发Build Canvas。使用示例以竖直滚动条为例,介绍一下步骤。如果觉得麻烦的话,直接打开DemoScene复制粘贴就好。当然你也可以干掉EasyObjPool,自己控制生成和销毁。1. 准备好Prefabs每个物体上需要贴上Layout Element并指定preferred width/height。贴上一个脚本接受void ScrollCellIndex (int idx) 消息,从而对每个位置的元素根据需要灵活修改。2. 在Hierarchy里右键,选择UI/Loop Horizontal Scroll Rect或UI/Loop Vertical Scroll Rect即可。使用Component菜单里的也是一样的。Init in Start:&启动时自动调用Refill cells初始化Prefab Pool:&EasyObjPool物体Prefab Pool Name:&第二步中对应的Cell Prefab名字Total Count:&总共能有多少物体,范围0 ~ TotalCount-1Threshold:&两端预留出来的缓存量(像素数)ReverseDirection:&如果是从下往上或者从右往左拖动,就打开这里Clear Cells:&清除已有元素,恢复到未初始化状态Refill Cells:&初始化并填充元素如果是正向滑动,就设置pivot为1;否则设为0并打开ReverseDirection。我强烈建议你试试在播放状态下修改这些参数。无尽模式如果需要无限滚动模式,将totalCount设为负数即可。其他参考后来搜了下,发现网上也有人提到过UGUI ScrollRect 优化(),不过他的策略是监听ScrollRect的value,然后禁用范围外的cell。最后作者也提到改成动态加载策略。这种基于value的做法我不太确认在在滚动前动态添加新元素的时候是否会出现问题。文末,再次感谢钱康来的分享,如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群)。
微信扫一扫
专注于VR的学习、开发和人才交流温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
阅读(258)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_',
blogTitle:'uGUI练习(六) ScrollView',
blogAbstract:'一、相关组件\nScrollRectMaskGrid Layout GroupScrollbar\n二、步骤\n1、创建一个Panel,命名为ScrollRect,添加 ScrollRect组件\n'
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}&&&&UGUI Scrollrect滚动优化:无限循环利用
UGUI Scrollrect滚动优化:无限循环利用
我的其他资源都是免费的,对于初学游戏者的帮助比较大的,其中有单片机,ARM,数据结构,window编程,MFC编程,cocos2dx,unity3d自己编写的小游戏。
若举报审核通过,可奖励20下载分
被举报人:
举报的资源分:
请选择类型
资源无法下载
资源无法使用
标题与实际内容不符
含有危害国家安全内容
含有反动色情等内容
含广告内容
版权问题,侵犯个人或公司的版权
*详细原因:
VIP下载&&免积分60元/年(1200次)
您可能还需要
移动开发下载排行

我要回帖

更多关于 ugui scrollrect 的文章

 

随机推荐