CreatorPrimer|预制件嵌套
1. LoadPrefab组件
预制件嵌套可以将复杂UI界面模块化,让每一个界面模块可以独立运行,也可以组合使用,开篇之前先看个视频演示:
不知道大家是否还记得之前的一篇教程《CreatorPrimer|加载预制件》,我们在这篇教程中提供的LoadPrefab组件中增加一行特殊代码就能实现预制件的嵌套,先看下代码:
前面说的特殊代码就是:
node._objFlags |= cc.Object.Flags.DontSave;
在每一个node节点上都有一个_objFlags变量,它是一个位标记,变量参数定义在cc.Object.Flags中,请看下图:
cc.Object.Flags.DontSave中“DontSave”故名思意,该节点不保存,不保存到那儿呢?该节点不会保存到场景文件.fire或者是预制件文件.prefab中。
2. 激活编辑器中的组件脚本
不保存到场景或预制文件中有意义呢?这个功能需要组件的executeInEditMode配合,它可以实现一个很有意思的功能:
“在编辑器状态执行组件生命周期函数”
看下面代码:
cc.Class({
extends: cc.Component,
editor: {
executeInEditMode: true, //注意这里
},
onLoad () {
Editor.log(`${this.node.name}: onLoad`);
},
onEnable() {
Editor.log(`${this.node.name}: onEnable`);
},
start () {
Editor.log(`${this.node.name}: start`);
},
});
组件开启executeInEditMode为true,所有组件生命周期函数都可以在编辑器状态被执行,不用等到在打开浏览器就能运行预览,请看下图:
在编辑器状态下,组件生命周期函数被执行,在此实例化出一个预制节点,同样会显示在场景编辑器中。
3. DontSave的作用
在开发过程中,每当打开场景或修改代码,都会触发编辑器中的组件生命周期函数被执行。
如果此时你按个ctrl+s或cmd+s保存当前界面,实例化出的预制节点也会保存当前场景中,如此反复操作,节点就会越来越多,但这是并不是我们想要的,因此下面这段代码就是关键了:
node._objFlags |= cc.Object.Flags.DontSave;
使用了上面这段代码,就不会担心节点被持久化到界面配置文件中了,每次实例化出的都是最新的预制节点。
4. 注意事项
隐藏API的使用
引擎提供的API中,以下划线开头的变量和方法其实是不建议随便使用的。
node._objFlags变量在官方文档中并没有介绍,Shawn从1.x用到了2.x暂时没有什么变化,请在使用前自己评估风险,这个需要说在前面。
注意节点不会被保存
使用LoadPrefab实例化出的预制节点是临时的,不会被持久化到编辑器配置文件中。
因此修改实例化出的预制节点的属性、组件属性是不起作用的,需要回到原始预制节中去修改,但修改预制节点下绑定的脚本代码是有效的。
executeInEditMode
注意开启了组件的executeInEditMode属性后,update函数也会在编辑器中被每帧执行,一它会让你的编辑器变慢,二此时可能还会有未初始化的操作,这应该不是你想要的,需要特别处理一下:
update() {
//编辑器环境退出
if (CC_EDITOR) {
return;
}
...
}
CC_EDITOR是引擎内置的全局变量,用于检查当前是否在编辑器状态,类似的变量还有不少,下面列举几个常用的:
变量 | 说明 |
---|---|
CC_EDITOR | 是否为编辑器环境 |
CC_PREVIEW | 是否为预览环境 |
CC_JSB | 是否为JSB环境 |
CC_DEBUG | 是否为调试环境 |
CC_WECHATGAME | 是否为微信小游戏环境 |
CCWECHATGAMESUB | 是否为微信小游戏子域环境 |
以上变量可以用于帮助大家判断代码当前执行环境,为不同环境、平台上做条件执行。
注意代码控制时机
如果需要用代码控制实例化出的预制节点,要特别注意控制时机,等待节点被创建成功后才能被正常访问。
5. 小结
本篇通过在编辑器中执行代码,动态实例化出临时预制节点,可实现多层的预制嵌套。
预制件的嵌套并不是目的,目的是利用预制件的嵌套组合,可以将一个复杂的UI界面拆分成多个子模块,从而实现多人分工协作,最后通过LoadPrefab组件将各个小模块(预制件)整合起来。
如果觉得公众号的文章对您或您身边的朋友有帮助,感谢分享给他们,愿我们一起成长!