Tag Archives: Cocos

Hello World

sp.Skeleton动画Listener汇总

简单总结一下cocos骨骼动画的各种几个回调监听,可以进行更精确的控制特效,免得到时只会this.schedule

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    //整体开始是调用一次
    this.roleAnimation.setStartListener((trackEntry)=>{
        console.log('---->> HeroAI roleAnimation, setStartListener:', trackEntry.trackIndex, trackEntry.animation.name);
    });
    //动画关闭时调用,在setEndListener之后
    this.roleAnimation.setDisposeListener((trackEntry)=>{
        console.log('---->> HeroAI roleAnimation, setDisposeListener:', trackEntry.trackIndex, trackEntry.animation.name);
    });
    //整体结束时调用
    this.roleAnimation.setEndListener((trackEntry)=>{
        console.log('---->> HeroAI roleAnimation, setEndListener:', trackEntry.trackIndex, trackEntry.animation.name);
    });
    //中断时调用,在setEndListener之前
    this.roleAnimation.setInterruptListener((trackEntry)=>{
        console.log('---->> HeroAI roleAnimation, setInterruptListener:', trackEntry.trackIndex, trackEntry.animation.name);
    });
    //每次循环结束时调用
    this.roleAnimation.setCompleteListener((trackEntry)=>{{
        console.log('---->> HeroAI roleAnimation, setCompleteListener:', trackEntry.trackIndex, trackEntry.animation.name);
    });

——
over
转载请注明出处:http://www.jiangkl.com/2025/04/cocos-skeleton-listener

Hello World

cocos.tween动画,时间线控制汇总

本文主要简绍cc.tween与sequence、delay、parallel、repeat和call的各种搭配、混合使用,实现事件序列的串并行控制
1. 简单串行

1
2
3
4
5
6
7
8
// 示例代码,先执行动作1、再执行动作2、然后执行回调
cc.tween(node)
    .to(time1, { position: newPosition }) // 动作1
    .to(time2, { angle: newAngle }) // 动作2
    .call(() => {
        // console.log('>> cc.tween end')
    })
    .start();

2. 并行parallel、延迟delay

1
2
3
4
5
6
7
8
9
// 示例代码,先同步执行动作1和动作2、然后延迟0.5秒、然后执行动作3
cc.tween(node)
    .parallel(
        cc.tween().to(time1, { position: newPosition1 }),// 动作1
        cc.tween().to(time2, { angle: newAngle }),// 动作2
    )
    .delay(0.5)
    .to(time2, { position: newPosition2 }) // 动作3
    .start();

3. 并行parallel、串行sequence、重复repeat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 示例代码 串并行混排、重复
cc.tween(node)
    .repeat(3,  // 让整个 sequence 重复 3 次
        cc.tween().sequence( //先执行第一个parallel,然后等待0.5秒、然后执行第二个parallel
            cc.tween().parallel( //先动作1与动作2串行
                cc.tween().to(1, { position: cc.v2(200, 200) }),  // 动作1
                cc.tween().to(1, { angle: 180 }) //动作2
            ),
            cc.tween().delay(0.5),
            cc.tween().parallel( //后动作3与动作4
                cc.tween().to(1, { position: cc.v2(-200, -200) }).to(1, { position: cc.v2(0, -200) }), //动作3,包含两个串行的子动作
                cc.tween().to(1, { color: cc.Color.RED }) //动作4
            )
        ).call(()=>{
               console.log('>> repeat once'); //每次repeat可以单独定义回调
        }),
 
    ).call(()=>{
        console.log('>> repeat end');} //整体完成的回调
    ).start();

——
over
转载请注明出处:http://www.jiangkl.com/2025/02/cocos-tween_timeline

Hello World

cocos.tween动画,移动曲线参数汇总

1. 缓动曲线:

1
2
3
4
5
6
7
8
9
10
11
// 示例代码
cc.tween(node)
    .to(time, { position: newPosition }, { easing: "sineInOut" }) // 先慢后快
    .start();
// 常用 easing 类型
// "sineIn"	开始慢,后面加速
// "sineOut"	开始快,后面减速
// "sineInOut"	先慢-加速-再慢
// "quadIn"	二次方曲线加速
// "quadOut"	二次方曲线减速
// "quadInOut"	二次方曲线平滑过渡

2. 贝塞尔曲线(Bezier Curve):

1
2
3
4
5
6
7
//示例代码
cc.tween(node)
    .bezierTo(time, cc.v2(100, 200), cc.v2(200, 300), cc.v2(300, 100)) // 1秒内按贝塞尔曲线移动
    .start();
// bezierTo(time, control1, control2, endPos)
// control1 和 control2 是控制点,决定曲线形状。
// endPos 是终点,节点沿着曲线到达该点。

3. 分步依次移动,使用 sequence() 组合多个 to():

1
2
3
4
5
6
7
//示例代码
cc.tween(node)
    .sequence(
        cc.tween().to(time1, { position: cc.v2(100, 200) }, { easing: "sineOut" }),
        cc.tween().to(time2, { position: cc.v2(200, 100) }, { easing: "sineIn" })
    )
    .start();

——
over
转载请注明出处:http://www.jiangkl.com/2025/02/cocos_tween_positin_easing

Hello World

Label对Drawcall的影响测试

众所周知,drawcall的数量是影响CocosCreator流畅度的一个重要指标,本文主要测试Label与Sprite混排时对性能的影响,主要有下面几个对照量:
1. 运行环境,共三种:
    a. mac端chrome浏览器(开启开发者工具、尺寸模拟iphon12pro)
    b. iphone(8plus)自带浏览器
    c. android(其实是鸿蒙、麒麟820/6G运存)自带浏览器
2. Label属性CacheMode,这里节选一下官方文档:
    a. None: 默认值,Label 中的整段文本将生成一张位图
    b. BitMap: 选择后,Label 中的整段文本仍将生成一张位图,但是会尽量参与 动态合图。只要满足动态合图的要求,就会和动态合图中的其它 Sprite 或者 Label 合并 Draw Call。由于动态合图会占用更多内存,该模式只能用于文本不常更新的 Label
    c. Char: 原理类似 BMFont,Label 将以“字”为单位将文本缓存到全局共享的位图中,相同字体样式和字号的每个字符将在全局共享一份缓存。能支持文本的频繁修改,对性能和内存最友好……不能参与动态合图(同样启用 CHAR 模式的多个 Label 在渲染顺序不被打断的情况下仍然能合并 Draw Call)
3. 节点形态:每一个精灵节点下,加一个Label子节点;精灵节点简单转动或摆动;Label仅显示数字,使用系统字体;测试过程共分三种情况:50/200/1000个节点
4. Label节点除了会修改CacheMode,还会尝试两种情况:不修改文案内容、每秒修改一次文案内容
基本的测试要素就是上面这些,下面来看测试结果

简单总结几个结论:
1. 就像文档里说的,对于固定内容的Label,BitMap确实对性能有巨大帮助,可以通过合批最大程度减少Drawcall
2. 对于Label和Sprite混排的情况,文本如果还要频繁更新,性能必然会受影响,如果预期这类节点数量很多,一定不能这么做
3. 虽然测试用的chrome浏览器已经开启了硬件加速,但或许是对m1mac的适配不好,这次测试chrome浏览器的表现完败,甚至不如六年前的iphone手机。(试了一下mac自带的safar浏览器,表现和iphone手机浏览器差不多)
那么,针对上面提到的第二条,如果确实需要大量、频繁更新的文本,应该怎么办?看文档大概有下面两种解决方案:
1. 使用艺术字图集代替系统字体
2. 将Label节点提出来,不要和Sprite混编
后续有时间试试这两种方案的效果 o(* ̄︶ ̄*)o
————
转载请注明出处:http://www.jiangkl.com/2023/04/cocos_label_drawcall
————
补充:
继续上面的话题,按照第2个解决方案对项目做了“优化”,也就是将所有的Label提取出来,单独放在一个节点了,和Sprite区隔开,测试结果:
1000个节点的情况下,三个端都能轻松运行,FPS 60,Drawcall 5,成功将1000个Label合批到一个Drawcall!

Hello World

浅析schedule与update的关系

schedule是cocos自带的定时器,这里简单试试这玩意的执行情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    onLoad () {
        this.schedule(()=>{
            let now = new Date().getTime();
            console.log('schedule-test, schedule 0.001', now);
        }, 0.001);
        this.schedule(()=>{
            let now = new Date().getTime();
            console.log('schedule-test, schedule  0.01', now);
        }, 0.01);
        this.schedule(()=>{
            let now = new Date().getTime();
            console.log('schedule-test, schedule   0.1', now);
        }, 0.1);
    }
 
    update (dt) {
        let now = new Date().getTime();
        console.log('schedule-test,         update', now);
    }

输出如下:
————
schedule-test, update 1658395521046
schedule-test, schedule 0.001 1658395521047
schedule-test, schedule 0.01 1658395521048
schedule-test, update 1658395521063
schedule-test, schedule 0.001 1658395521064
schedule-test, schedule 0.01 1658395521065
schedule-test, update 1658395521080
schedule-test, schedule 0.001 1658395521081
schedule-test, schedule 0.01 1658395521082
schedule-test, update 1658395521097
schedule-test, schedule 0.001 1658395521098
schedule-test, schedule 0.01 1658395521099
schedule-test, schedule 0.1 1658395521100
schedule-test, update 1658395521113
schedule-test, schedule 0.001 1658395521114
schedule-test, schedule 0.01 1658395521115
。。。。
————
简单总结一下,可以得到下面几个结论:
1. 在cocos的世界里,一“帧”,就是它的最小计时单位,也是schedule的最小调用周期,比帧间隔再小的时间单位,对schedule无效
2. schedule(可能)会在每一帧的update以后,调起定时逻辑
3. 即使定时间隔大于帧间隔,schedule也不能按毫秒级的时间精确调起回调函数(这一点从定时“0.1s”的回调里可以看出,不过上面没贴出出这么多)
嗯,简单来说看,可以把schedule当成低配版setInterval,既然cocos提供了自己的定时器,就尽量少用setInterval和setTimeout吧
————
转载请注明出处:http://www.jiangkl.com/2022/07/cocos_schedule_update