UGUI ScrollRect 高效复用

 最近忙于性能优化,深切体会到二八法则真是指导高(tou)效(lan)工作的有力武器。这个礼拜花了几天解决了一个实际问题:UGUI的ScrollRect加载太多物体的时候,第一次弹出界面会非常卡顿,而且不在界面里的内容依然会参与绘制(毫无意义的浪费…)。

ChangeLog:
      v1.01 重构了好几遍,基本算重写了份…优化了拖动手感和回收部分的计算,增加了反方向滑动支持。升级至Unity 5.2的UGUI API。
      v1.0 这两天基于网上找的一份InfinityScroll代码,把这个功能做了。在加载时间和Draw Call上都提升显著,而且滑动的时候也没有卡顿。
     Demo1: 每个元素知道自己的序号,可以根据需要修改自己的内容、大小等信息。
Demo2: Mask关闭状态下可以看到,只有当需要的时候才动态实例化元素,使用完后回收。


Demo3: 反方向滑动(从下往上或者从右往左)。


介绍
        最原始版本的代码是@ivomarel的InfinityScroll。我改到后来,基本和原始版没啥相同的了…
        原代码使用了sizeDelta作为大小,但是这个在锚点不重合情况下是不成立的;
        支持了GridLayout;
        在启动时检查锚点和轴心,方便使用;
        修复了原代码在往前拖拽会卡顿的问题;
        优化代码,提升性能;
        支持反向滑动。
        此外,我修改了Easy Object Pool作为池子,循环利用元素。
        警告: 为了解决原始代码回拉卡顿的问题,我直接复制了一份UGUI中的ScrollRect代码,而没有继承。这是因为老的做法是在onDrag里停止并立即启动滚动,而我通过修改两个私有变量保证了滑动顺畅。所有我的代码都用==========LoopScrollRect==========这样的注释包起来,维护起来就像打patch了…

无尽模式
        如果需要无限滚动模式,将totalCount设为负数即可。

使用示例
        以竖直滚动条为例,介绍一下步骤。如果觉得麻烦的话,直接打开DemoScene复制粘贴就好 =w= 当然你也可以干掉EasyObjPool,自己控制生成和销毁。

准备好Prefabs
        每个物体上需要贴上Layout Element并指定preferred width/height
        贴上一个脚本接受void ScrollCellIndex (int idx) 消息,从而对每个位置的元素根据需要灵活修改 ScrollCell

UGUI ScrollRect 高效复用_第1张图片

        将刚才做的Prefabs放到EasyObjectPool中 EasyObjectPool

UGUI ScrollRect 高效复用_第2张图片

        对于ScrollRect物体贴上LoopVerticalScrollRect和Mask。我强烈建议你试试在播放状态下试试看修改这些参数。
        Clear Cells: 清除已有元素,恢复到未初始化状态;
        Refill Cells: 初始化并填充元素;
        Init in Start: 启动时自动调用Refill cells初始化;
        Prefab Pool: EasyObjPool物体;
        Prefab Pool Name: 第二步中对应的Cell Prefab名字;
        Total Count: 总共能有多少物体,范围0 ~ TotalCount-1;
        Threshold: 两端预留出来的缓存量(像素数);
        ReverseDirection: 如果是从下往上或者从右往左拖动,就打开这里。

UGUI ScrollRect 高效复用_第3张图片

        在Content上贴Content Size Filter和Vertical Layout Group,注意红色部分里轴心设置。 

UGUI ScrollRect 高效复用_第4张图片

        如果是正向滑动,就设置pivot为1;否则设为0并打开ReverseDirection。
        ps. 刚才搜了下,发现网上也有人提到过UGUI ScrollRect 优化,不过他的策略是监听ScrollRect的value,然后禁用范围外的cell。最后作者也提到改成动态加载策略。这种基于value的做法我不太确认在在滚动前动态添加新元素的时候是否会出现问题。

你可能感兴趣的:(C#)