【包教包会】节点扩展(支持原生,附引擎源码查询教程、skew翻页教程)

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

一、需求整理

相信很多从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
二、分析引擎源码

右键点VsCode图标,选择Visual Studio Code
image
在打开的新VsCode中,选择Open Folder
image
找到C:\ProgramData\cocos\editors\Creator\3.8.7,点“选择文件夹”打开引擎工程


点击顶部搜索框,输入node.ts

搜索set position
image
可以看到,位移属性保存在私有属性_lpos中,进一步点开setPosition
image
整个setPosition方法做了3件事:
修改_lpos值、使修改生效(标记dirty)、emit位移事件

该说不说,3.8.7引擎代码比以前的版本工整了很多 :+1:

三、自定义属性

照葫芦画瓢,给节点增加一个“x”属性
image
照抄get方法,只返回x分量
照抄set方法,只修改x分量
去掉emit事件,主要考虑2点:
1、大部分修改坐标的操作不需要抛出事件,去掉emit可以提升性能
2、如果需要监听事件,可以调用setPosition,选择权交给用户

测试一下

image
BearMove
符合预期!
其他属性也如法炮制,这里要说明一下:
image
1、引擎组在3.8.7已经新增了x,y,z属性,因此这里没有报错,但添加其他属性会报错
因此借助declare补充声明所有自定义属性
这样调用自定义属性就不会报错,而且有代码提示

2、自定义属性width、height、anchorX、anchorY会报错,因为底层做了废弃声明
为了避免每次看到warn闹心,在属性后面加个U来规避

3、color属性在3.8.7中支持tween渐变,但在之前版本不支持(会闪烁)
因此老版本可以参考3.8.7官方的做法修改

4、新增scaleXY属性,方便实现等比缩放
新增radian弧度属性,方便直接参与三角函数运算

5、虽然h5运行良好,但是原生环境运行无效,这里做个兼容处理:
原生端沿用setPosition,h5用新版提升性能
image

image
四、扩展方法

新增了4个强大的扩展方法:

1、get 获取节点或组件
let node = this.node.get(‘AA/BB/CC’); //获取路径为"AA/BB/CC"的子节点
let spt = this.node.get(‘AA/BB’, Sprite); //获取路径为"AA/BB"的子节点的Sprite组件
let spt1 = this.node.get(‘AA/BB’, ‘Sprite’); //同上,支持填写类型名称
未找到返回null

2、find 获取子节点
let arr0 = this.node.find(‘Title’); //获取所有名称为’Title’的子节点
let arr1 = this.node.find(‘Ti’, true); //获取所有名称以’Ti’开头的子节点
返回子节点数组,未找到返回空数组[]

3、setColor 渐变色
this.node.setColor(3, new Color(255,0,0)); //节点颜色3秒内渐变到255,0,0
this.node.setColor(2); //节点颜色2秒内复原
setColor
所有子节点也会跟着一起变色
支持同步调用,也可以在异步方法中使用

4、setShake节点震动
this.node.setShake(7, new Vec2(100, 0), 0.1); //节点振动7次,水平振幅100,频率0.1秒
this.node.setShake(-1, new Vec2(0, -50), 0.5); //节点振动无限次,垂直振幅-50,频率0.5秒
this.node.setShake(0); //节点立即停止振动
shake
所有子节点也会跟着一起振动
支持同步调用,也可以在异步方法中使用

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

Q:如何导入自己项目
step1. 将Demo中NodeEx.ts复制到自己项目assets目录下,具体层级不限
step2. 任意Node对象,按 . 就可以出现语法提示,可以像2.x一样调用
image
Q:3.8.7的UISkew怎么用
A: 扩展了skewX和skewY属性
在Demo的HelloWorld.ts中演示了如何通过 tween + skewY + scaleX 实现翻页


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

EMail地址:27185709@qq.com

推荐链接:
1、【包教包会】CocosCreator3.x——重写Sprite

2、【包教包会】3分钟学会贝塞尔曲线

3、【包教包会】130行代码实现多语言,i18n扔了扔了

4、【包教包会】CocosCreator3.x全局单例最优解

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

mi

8赞

大佬666

大佬,牛的:call_me_hand:

大佬收小弟不,自带学费的那种 :crazy_face:

可以啊私信

国庆不出去玩吗?感觉今年不是很热闹,还是我没去对地方,感受不到人挤人

大佬,牛的:call_me_hand:

10月19日修改:
get方法返回的组件类型优化,例如:
let a = this.node.get(‘AA/BB’, Label);
旧版返回typeof Label
新版返回Label,会有正确的代码提示
下载地址不变,请使用最新版

战略性mark

这种API不应该用泛型吗?

新版用的就是泛型

包吃住不 :grinning:

可以的,顿顿西贝

之前用(白P)了你的好几个组件代码了,这次支持你的GiSprite一波,感谢

另:
新版本的ts脚本是能在3.8.2用的吧?
270行的 get<T = Node>(hierarchy: string, typeOrClassName?: __private.__types_globals__Constructor | string): T | null; 提示报错
cc".__private”没有导出的成员“__types_globals__Constructor”。你是否指的是“_types_globals__Constructor”。多了一个下划线了
以及原来的heightUT为什么又改成heightU了啊?

3.8.2可以用,引擎底层有些差异自己适配一下
heightU纯粹就是短一点
感谢支持GiSprite,这个组件最新版本可以加我售后群获取 :grinning:

10月31日更新:
1、新增convert方法

/** 返回当前节点坐标系下的点pos,在target节点坐标系的坐标,target缺省则返回世界坐标下的坐标 */
function convert(pos: Vec3, target?: Node): Vec3;

2、优化opacity
修复了特殊渲染节点(例如:Graphics等)使用opacity报错的bug