cocos creator scroll view性能优化

本文介绍了一种有效的Unity游戏开发中ScrollView优化方法,通过动态控制滚出屏幕元素的重用,避免了DrawCall的线性增长,显著提高了低端设备的游戏性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

scrollView在游戏优化中还是占得比重比较大的,scrollview随着元素的增加它的drawcall呈线性增长,没有优化之前我添加了100个元素drawcall飙升到413个drawcall这样的话在某些低端机上会出现严重卡顿的情况甚至是程序直接挂掉。这里优化的重点是:

1:scrollview 显示区域就那么大可以把滚出屏幕的那一部分元素挪动到下面去继续显示只是显示的内容变化了这个可以动态的控制,这样drawcall只跟我们设定的显示元素个数这个值有关(初始化的时候就已经完全生成他们,在滑动的时候我们只是移动初始化的元素)

下面是具体的优化代码:

const {ccclass, property} = cc._decorator;
@ccclass
export default class NewClass extends cc.Component {
    @property({
        type: cc.ScrollView
    })
    scroll: cc.ScrollView = null;
    @property({
        type: cc.Prefab
    })
    itemPrefab: cc.Prefab = null;
    @property
    totalCount: number = 0;
    @property
    spacing: number = 20;
    @property
    spawnCount: number = 6;
    // 缓冲区的上边界
    private topY: number = 0;
    // 缓冲区的下边界
    private bottomY: number = 0;
    // 最后的y坐标值
    private lastY: number = 0;
    // 滑动列表的可滑动区域
    private content: cc.Node = null;
    // 盛放已经生成的节点
    private items: Array<cc.Node> = [];
    // 控制时间
    private timeFrame: number = 0;
    // 时间间隔
    private timeInterval: number = 0.2;
    private maxY: number = 0;
    // 开始累加的数字
    private startAdd: number = this.spawnCount;
    // 开始往下追加的开始值
    private startAppend: number = 0;
    onLoad () {
        this.content = this.scroll.content;
        console.log("content is ",this.content);
        console.log("content's parent is ",this.content.parent);
        this.content.height = this.totalCount * this.itemPrefab.data.height + this.totalCount * this.spacing + this.spacing;
        this.topY = 0;
        this.bottomY = -this.content.height;
        for(let i = 0; i < this.spawnCount; i++) {
            let tempNode: cc.Node = cc.instantiate(this.itemPrefab);
            tempNode.getChildByName("score").getComponent(cc.Label).string = i.toString();
            tempNode.getComponent("Item").setItemId(i);
            tempNode.x = 0;
            tempNode.y = -i * (tempNode.height + this.spacing) - this.spacing;
            if(i === this.spawnCount - 1) {
                this.maxY = tempNode.y;
            }
            console.log("tempNode is ",tempNode);
            this.content.addChild(tempNode);
            this.items.push(tempNode);
        }
    }

    start () {

    }

    update (dt) {
        this.timeFrame += dt;
        console.log("timeFrame is ",this.timeFrame);
        // 帧时间小于0.2不执行update提高性能
        if(this.timeFrame < this.timeInterval) {
            return;
        }
        console.log("=====>>>>");
        this.timeFrame = 0;
        let isDown: boolean = this.scroll.content.y > this.lastY;
        let offset: number = -this.spawnCount * (this.itemPrefab.data.height + this.spacing);
        // 检查每一个节点的y坐标如果超出上边界就讲该节点放到后面去替换预制体中的贴图或者标签文字
        console.log("isDown is ",isDown);
        for(let i = 0; i < this.items.length; i++) {
            // 获得每个节点的坐标
            let item: cc.Node = this.items[i];
            // item.y 是一直不变的一个值滚动的是content
            // console.log("item.parent.y is ",item.parent.y);
            let itemWorldPosition: cc.Vec2 = item.parent.convertToWorldSpaceAR(item.position);
            let itemNodePosition: cc.Vec2 = this.scroll.node.convertToNodeSpaceAR(itemWorldPosition);
            if((itemNodePosition.y > (this.scroll.node.height / 2 + item.height + this.spacing)) && isDown) {
                // 向下滑动并且该节点的坐标超出上边界就应该将该节点移动到节点队列的最末尾并更新末尾节点的相关属性
                item.y = item.y + offset;
                // 更新最后一个节点的属性
                item.getComponent("Item").setItemId(item.getComponent("Item").itemId + this.items.length);
                // item.getComponent(cc.Label).string = num.toString();
                console.log("itemId is ",item.getComponent("Item").itemId);
                item.getComponent("Item").setScore("" + item.getComponent("Item").itemId);
                if(i % 2 === 0) {
                    item.getComponent("Item").setAvatar("1.jpg");
                } else {
                    item.getComponent("Item").setAvatar("2.jpg");
                }
            } else if((itemNodePosition.y < -(this.scroll.node.height / 2 + item.height + this.spacing )) && !isDown){
                if(item.getComponent("Item").itemId - this.items.length >= 0) {
                    console.log("有节点超出了下边界",i);
                    item.y -= offset;
                    item.getComponent("Item").setItemId(item.getComponent("Item").itemId - this.items.length);
                    item.getComponent("Item").setScore("" + item.getComponent("Item").itemId);
                }
            }
        }
        this.lastY = this.scroll.content.y;
    }
}

同时预制体上绑定了一个脚本Item.ts:

const {ccclass, property} = cc._decorator;

@ccclass
export default class Item extends cc.Component {

    public itemId: number = 0;
    @property({
        type: cc.Label
    })
    scoreLabel: cc.Label = null;
    @property({
        type: cc.Label
    })
    levelLabel: cc.Label = null;
    // LIFE-CYCLE CALLBACKS:

    onLoad () {

    }
    setItemId(itemId: number): void {
        this.itemId = itemId;
    }
    setScore(scoreString: string): void {
        this.scoreLabel.string = scoreString;
    }
    setLevel(levelString: string): void {
        this.levelLabel.string = levelString;
    }
    setAvatar(url: string): void {
        let self = this;
        console.log("url is ",url);
        if(url) {
            cc.loader.loadRes(url,cc.SpriteFrame,(err,data) => {
                self.node.getChildByName("avatar").getComponent(cc.Sprite).spriteFrame = data;
            })
        }
    }
    start () {

    }

    update (dt) {

    }
}

 项目demo地址:项目源码

 

 

### 使用 FGUI 和 TypeScript 在 Cocos Creator 中实现文本滚动效果 为了在 Cocos Creator 中通过 FGUI 插件创建一个可以滚动的文本,下面提供了一个基于 TypeScript 的脚本实例来达成这一目标[^1]。 #### 创建并配置 Scroll View 组件 首先,在编辑器内新建一个 `ScrollView` 并调整其属性以适应所需的布局需求。接着将要显示的文字内容放置于该容器内部作为子对象处理。确保文字节点上挂载有 Label 或者 Text 类型组件用于呈现具体字符串数据。 #### 编写 TypeScript 脚本控制逻辑 接下来编写一段简单的 TypeScript 代码片段,这段程序会动态更新文本位置从而制造出滚屏视觉体验: ```typescript import { _decorator, Component, Node, LabelComponent } from &#39;cc&#39;; const { ccclass, property } = _decorator; @ccclass(&#39;TextScroller&#39;) export class TextScroller extends Component { @property(Node) private scrollViewContent: Node | null = null; // ScrollView 内部的内容区域 start() { this.schedule(this.scrollText.bind(this), 0.5); // 定时调用 scrollText 方法 } private scrollText(): void { if (this.scrollViewContent !== null && this.scrollViewContent.getComponent(LabelComponent)) { let labelComp = this.scrollViewContent.getComponent(LabelComponent); const textLength = labelComp.string.length; // 如果字符串长度超过一定数值则执行移位操作 if(textLength > 20){ let newText = labelComp.string.substring(1) + labelComp.string.charAt(0); labelComp.string = newText; } } } } ``` 此段代码定义了一个名为 `TextScroller` 的类继承自 `Component` ,其中包含了两个核心方法:一个是初始化阶段设置定时任务;另一个则是负责每间隔一段时间改变一次文本的位置形成循环播放的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值