版本 cocos creator3.3.2
这里我把mask打开,看看效果
长列表优化,隐藏区域外的
20220411_161150
长列表优化一直是游戏优化的重点内容,特别是在真机上。排行榜,背包等等的数据,渲染太多,导致drawCall增加,卡顿
之前我的博客中有另一个方式实现长列表优化,就是只实例化固定数量,然后这个固定数量在滑动中不断的切换显示数据
CocosCreator无尽循环列表,长列表优化drawcall,scrollview列表优化_似水流年wxk的博客-优快云博客
现在介绍一个新的可以通用的方法,就是依然都实例化,只是超过显示区域的隐藏掉,但是content不能加layout来布局,因为加layout,隐藏子节点后,就排序乱了,一定要代码自己设置位置
1.首先说一下纵向滑动列表(非Grid滑动)
(1)content节点的位置,移到显示区域的上面,第一个item的位置
(2) item的根节点要有高度,和item背景一样的高度
看一下我的scrollView 的配置 这是我的content
其他的配置都是默认就行,滑动区域主要是在深色区域 上代码
import { _decorator, Component, Node, ScrollView, UITransform, Vec3, instantiate, Size } from 'cc';
import UIBase from '../../UIFrame/UIBase';
import { UIPackLinkRecordItem } from './UIPackLinkRecordItem';
const { ccclass, property } = _decorator;
/**
* Predefined variables
* Name = UIPackLinkRecord
* DateTime = Mon Apr 11 2022 14:55:36 GMT+0800 (中国标准时间)
* Author = fywxk
* FileBasename = UIPackLinkRecord.ts
* FileBasenameNoExtension = UIPackLinkRecord
* URL = db://assets/scripts/UI/UIknapsack/UIPackLinkRecord.ts
* ManualUrl = https://docs.cocos.com/creator/3.3/manual/zh/
*
*/
@ccclass('UIPackLinkRecord')
export class UIPackLinkRecord extends Component{
@property(Node)
private viewContent: Node = null;// 滑动父节点
@property(ScrollView)
private scrollView: ScrollView = null;//
@property(Node)
private itemNode: Node = null;// item 节点
needJudge = false;// 是否需要判断滑动区域隐藏
itemDis = 6;// 间距
paddingUp = 10;// 开始的偏移,上面的偏移10个像素
itemCount = 60;
start () {
this.refreshUI();
}
requestList()
{
}
// 刷新列表界面
refreshUI()
{
// 销毁之前的数据,不判断隐藏
this.needJudge = false;
this.viewContent.removeAllChildren();
let itemHeight = this.itemNode.getComponent(UITransform).height;// item高度
// 实例化item 60个
for(var i=0;i<this.itemCount ;i++)
{
// 计算位置 第一个是-item高度的一半,后面就是(item高度+间距)*i
let pos = new Vec3(0,-itemHeight/2-this.paddingUp+((-itemHeight-this.itemDis) * i),0);
// 获取item脚本赋值
let a:Node = instantiate(this.itemNode);
a.active = true;
a.getComponent(UIPackLinkRecordItem).setValue("");
a.parent = this.viewContent;
a.setPosition(pos);
}
// 设置content内容的高度,就是内容的总高度
let size = this.viewContent.getComponent(UITransform).contentSize;
this.viewContent.getComponent(UITransform).setContentSize(new Size(size.width,(itemHeight+this.itemDis)*this.itemCount +this.paddingUp));
this.needJudge = true;// 开始计算隐藏
}
update()
{
// 判断滑动超出区域,就隐藏,降低drawcall
if(this.needJudge)
{
let itemHeight = this.itemNode.getComponent(UITransform).height+this.itemDis;// item+间距
let height = this.viewContent.getComponent(UITransform).height;// 总高度
let viewHeight = this.scrollView.getComponent(UITransform).height;// 视口高度
let offsetUp = this.scrollView.getScrollOffset().y;// 相对于左上的滑动偏移
if(height-viewHeight<=0) return;// 不需要滑动,小于显示区域
// 遍历子节点
this.viewContent.children.forEach(item=>{
if(item.position.y+offsetUp>itemHeight) // 不滑动的时候偏移是0
{// 判断上面隐藏 大于一个item高度的隐藏
item.active = false;
}
else if(item.position.y+offsetUp+viewHeight<-itemHeight)
{// 判断下面隐藏 y+偏移+视口高度 小于-item高度
item.active = false;
}
else item.active = true;// 其他的都显示
})
}
}
}
2.首先说一下纵向滑动Grid滑动,和上面的代码大同小异,就是设置位置的问题
(1)content节点的位置,移到显示区域的上面,第一个item的位置
(2) item的根节点要有高度,和item背景一样的高度
上代码
import { _decorator, Component, Node, v2, Vec3, Label, Color, math, v3, instantiate, UITransform, Size, ScrollView, view } from 'cc';
import { RowBetween } from '../../../../contractReactProject/src/components/Row';
import { UIPackLinkItem } from './UIPackLinkItem';
import { UIPackLinkRecord } from './UIPackLinkRecord';
const { ccclass, property } = _decorator;
/**
* Predefined variables
* Name = UIPackUpLink
* DateTime = Sat Apr 09 2022 15:53:05 GMT+0800 (中国标准时间)
* Author = fywxk
* FileBasename = UIPackUpLink.ts
* FileBasenameNoExtension = UIPackUpLink
* URL = db://assets/scripts/UI/UIknapsack/UIPackUpLink.ts
* ManualUrl = https://docs.cocos.com/creator/3.3/manual/zh/
*
*/
@ccclass('UIPackUpLink')
export class UIPackUpLink extends Component{
@property(Node)
private closeButton: Node = null;
@property(Node)
private recordButton: Node = null;
@property(Node)
private pageBtnParent: Node = null;// 页签父节点
@property(Node)
private goodsPageBtnParent: Node = null;// 物品页签父节点
@property(Node)
private viewContent: Node = null;// 滑动父节点
@property(ScrollView)
private scrollView: ScrollView = null;//
@property(Node)
private itemNode: Node = null;// item
needJudge = false;// 是否需要判断滑动区域隐藏
lineNum = 6;// 每行数量
itemCount = 60;// 总数
itemDis = 17;// 上下左右间距
pageType:"";// 页面类型 up/down
start () { this.refreshUI();
}
// 刷新列表界面
refreshUI()
{
this.needJudge = false;
this.viewContent.removeAllChildren();
let itemHeight = this.itemNode.getComponent(UITransform).height;
let itemWidth = this.itemNode.getComponent(UITransform).width;
let posX = -this.viewContent.getComponent(UITransform).width/2+itemWidth/2+1;
// 实例化item 60个
for(var i=0;i<this.itemCount;i++)
{
// 这里计算一下位置,x:每行有6个 0或者6的倍数除6求余,得到是0就是第一个,其他的都往后排
// y:总数 /6 是行数 乘以item的高度加间距
let pos = new Vec3(i%this.lineNum==0?posX: posX+(itemWidth+this.itemDis)*(i%this.lineNum),-itemHeight/2+((-itemHeight-this.itemDis) * Math.floor(i/this.lineNum)),0);
let a:Node = instantiate(this.itemNode);
a.active = true;
a.getComponent(UIPackLinkItem).setValue(this.pageType);
a.parent = this.viewContent;
a.setPosition(pos);
}
// 设置高度
let size = this.viewContent.getComponent(UITransform).contentSize;
this.viewContent.getComponent(UITransform).setContentSize(new Size(size.width,(itemHeight+this.itemDis)*Math.ceil(this.itemCount /this.lineNum)));
this.needJudge = true;
}
update()
{
// 判断滑动超出区域,就隐藏,降低drawcall
if(this.needJudge)
{
let itemHeight = this.itemNode.getComponent(UITransform).height+this.itemDis;
let height = this.viewContent.getComponent(UITransform).height;// 总高度
let viewHeight = this.scrollView.getComponent(UITransform).height;// 视口高度
let offsetUp = this.scrollView.getScrollOffset().y;// 相对于左上的滑动偏移
if(height-viewHeight<=0) return;// 不需要滑动
this.viewContent.children.forEach(item=>{
if(item.position.y+offsetUp>itemHeight)
{// 判断上面隐藏
item.active = false;
}
else if(item.position.y+offsetUp+viewHeight<-itemHeight)
{// 判断下面隐藏
item.active = false;
}
else item.active = true;
})
}
}
}
注意:这套代码,只要设置好间距,总数,开始的偏移(可没有),再加上item预制体的高度,content的位置,几乎可以通用在任何长列表