V7投稿 | 手把手教你搭框架——节点扩展,用2.x代码写3.x项目

对CocosCreator3.x节点Node进行扩展,简化书写,提升性能。

演示Demo:https://gitee.com/szrpf/NodeEx

image
一、需求整理
相信很多从2.x转过来的同学对3.x的节点属性调整会比较别扭,例如:

2.x可以直接写:
this.node.x++;
this.node.width = 100;
this.node.anchorX = 1;
tween(this.node).to(1,{x:100,scaleX:3}).start();

3.x必须这么写:
this.node.setPosition(this.node.position.x+1,this.node.position.y);
let uiTrans = this.node.getComponent(UITransform);
uiTrans.width = 100;
uiTrans.anchorX = 1;
tween(this.node).to(1,{position:cc.v3(this.node.position.x+100,this.node.position.y)}).start();
tween(uiTrans).to(1,{width:100,anchor:cc.v2(1,uiTrans.anchorY)}).start();
image
二、构思方案
分析引擎源码,我猜官方是想合并事件消息才这么处理的

拿setPosition举例:
2.x
this.node.x = 3;this.node.y = 10;this.node.z = 0;
这样会emit3个位置变更事件
3.x
直接一句setPosition就设置3个坐标,只emit一个事件
但问题是,如果只设置x或y,那么setPosition也要象征性的把另一个捎带上,属实有点der~

优化思路
如果this.node.x只变更位置,不emit事件是不是就不存在以上问题了?
不但写起来省事,效率还更高(少了emit事件)
再扩展一下把2.x的scaleX、scaleY、width、height、anchorX,anchorY统统按照以上思路重写
那么UITransform的属性和node的属性可以在一个tween处理了

三、验证可行性
Object.defineProperties重定义属性
image
照抄引擎setPosition相关的源码,去掉emit事件发送的代码
image
发现".x"报错,说明底层并没有给Node设置x这个属性,运行一下看看。
BearMove
节点确实移动了,符合预期。
image
至于报错问题,编写一个.d.ts文件声明一下就可以了。
至此,报错问题也顺利解决,而且在任何脚本里,节点对象按.都能出现x的语法提示

其余方法如法炮制,是不是2.x熟悉的感觉又回来了。
image
这里有2个坑:
1、扩展width、height、anchorX、anchorY的时候提示重定义
image
应该是引擎已经将这4个属性声明为废弃了
退而求其次,只能在后面加个后缀UT(代表UITransform)
希望官方能解除这个废弃声明

2、扩展color的时候,发现虽然直接node.color = cc.color(xxxx)有效
但是tween里面渐变color属性会闪,这是因为:
3.x的tween直接将color作为_val进行数值渐变,而非对r、g、b、a分别渐变
这个要重写tween来解决,不属于今天的讨论范围。

四、其他扩展函数
既然扩展了Node,顺便把以前写的节点函数也丢进来,分别是:
1、返回所有名称为name的子节点
findChildren(name: string, isStartWith: boolean = false): cc.Node[]
例如:this.node.findChildren(‘Title’); //返回所有名称为’Title’的子节点
this.node.findChildren(‘Tit’,true); //返回所有名称以’Tit’开头的子节点

2、在不改变世界坐标的前提下,设置锚点
setAnchor: (point: Vec2 | number, y?: number);

3、节点颜色time秒内渐变到color色值
setColor: (time: number, color?: Color);
例如:this.node.setColor(3,cc.color(255,0,0)); //节点颜色3秒内渐变到255,0,0
this.node.setColor(2); //节点颜色2秒内复原
setColor
注意:所有子节点也会跟着一起变色

4、节点震动repeat次,振幅amplitude,频率frequency
shake: (repeat: number, amplitude?: Vec3, frequency?: number);
例如:
this.node.shake(7,cc.v3(100,0,0),0.1); //节点振动7次,水平振幅100逐次递减,频率0.1秒
this.node.shake(-1,cc.v3(0,-50,0),0.5); //节点振动无限次,垂直振幅-50逐次递减,频率0.5秒
this.node.shake(0); //节点立即停止振动
shake

5、实时销毁
this.node.destroyRealtime(); //销毁节点,并立即从层级树中移除
this.node.destroyChildrenRealtime(); //销毁所有子节点,并立即从层级树中移除子节点

五、结束语
NodeEx扩展的优势:
1、简化了书写
对于大量做项目的实战选手来说,这个很重要

2、提高了性能
大部分节点属性的emit事件是没必要的,NodeEx直接移除了emit,提高性能
如果需要监听事件,再用setPosition、setScale这些函数就行了

3、降低了2.x转型3.x的难度
很多代码都不用改了

演示Demo:https://gitee.com/szrpf/NodeEx

如何导入自己项目:
1、将Demo中NodeEx.ts复制到自己项目assets目录下

2、将Demo中NodeEx.d.ts复制到自己项目根目录下(与assets同级)

3、任意Node对象,按 . 就可以出现语法提示,可以像2.x一样调用
image
技术基本功决定下限
设计架构能力决定上限
不想面临35岁裁员危机
就多多锻炼框架设计能力吧
加油:sunglasses::sunglasses::sunglasses::sunglasses::sunglasses::sunglasses::sunglasses:

Gitee地址:https://gitee.com/szrpf

EMail地址:27185709@qq.com

推荐链接:

1、【包教包会】CocosCreator3.x框架——资源管理(秒Loading、大厅子游戏、同步加载、极简对象池、多语言)

2、【包教包会】CocosCreator Assembler经典案例第一期——2D实现3D透视翻转(附Demo源码)

3、【包教包会】对CocosCreator富文本RichText进行全面优化

4、【包教包会】对CocosCreator拖尾组件MotionStreak做了全面优化

5、权重随机算法,解决游戏中一切可控随机(刷怪、掉宝、转盘、抽卡等等)

mi

1赞

不要扩展 Node.prototype,之前 panda 大佬说过,自行扩展会影响节点内存,可能导致性能降低很多,我的框架里都改成了 N(node).xxx

https://gitee.com/muzzik/MKFramework/blob/main/assets/extends/@node/nodes.ts

https://forum.cocos.org/t/topic/151848/20?u=1226085293

你测过性能么?

我没测过,但是引擎组的人测试过并且修改过因为这个导致的性能问题

随便改变原型链就不是正道,老老实实写个util 方法不就行了

使用方便,性能高效就是正道,当然每个人理解不同