cocosCreator版本: v3.7.1

脚本: TypeScript

简介

在cocosCreator中,脚本如果继承于 Component 就可作为组件挂载在不同的节点上。

创建脚本后,编译器会根据脚本的文件名生成对应的className文件。

// cc 历史原因保留下的标识符,在2.x版本中没有, 在3.x版本中出现,相当于对API模块的一次嵌套封装
// Component 附加到节点的基类,脚本不继承它无法作为组件嵌套到节点上
import { _decorator, Component, Node } from 'cc';
const { ccclass, property } = _decorator;

// ccclase 它主要用于将脚本作为组件添加到节点上,其类名是不可重复的。
@ccclass('mainScene')
export class mainScene extends Component {
  	// 生命周期的回调接口
  	start () {
      	// 
    }
}

ccclass

在引擎中被称为装饰器,用于修饰Componet的子类,表示为组件脚本。其他常用的还有:

@ccclass('Example')
// 允许当前组件在编译模式下运行,默认为false 
@executeInEditMode(true)
// 制定当前组件的依赖组件,默认为null, 如果依赖组件不存在,引擎自动降依赖组件添加到节点中,避免脚本报错
@requireComponent(Sprite)
// 用来指定脚本生命周期回调的执行优先级。小于 0 的脚本将优先执行,大于 0 的脚本将最后执行
@executionOrder(3)
// 同一节点上只允许添加一个同类型(含子类)的组件,防止逻辑发生冲突,默认值为 false
@disallowMultiple(true)
// 用来将当前组件添加到组件菜单中,方便用户查找
@menu('foo/bar')
// 指定当前组件的帮助文档的 URL。设置完成后,属性检查器就会显示一个帮助图标,点击即可打开指定的网页。
@help('https://docs.cocos.com/creator/3.4/manual/zh/scripting/decorator.html')

Component

所有组件的基类,在脚本中使用this表示本组件,脚本中获取组件所在节点的对象,可以这样:

export class mainScene extends Component {
  	start () {
      	let node = this.node;
      	node.active = false;			// 设置节点atvie为false
    }
}

property

被称为属性装饰器,可以用来控制编译器对属性的序列化,以及属性检查器对属性的显示。比如:

@ccclass('mainScene')
export class mainScene extends Component {
    @property({type: Button, tooltip: "这是一个按钮"})
    public backBtn: Button = null!;	  //等价 backBtn: Button | null = null;
}

部落冲突iOS脚本_初始化

其常用写法有:

// 可以用来修饰CCInteger, CCFloat, CCBoolean, CCString等基础属性类型
@property({type: CCInteger})
num = 0;

// 属性参数只有type时,可以忽略;等价@property({type: CCInteger})
@property(CCInteger)
num = 0;

// 修饰Node数组相关
@property({type: [Node]})
children: Node[] = [];

// 
@property(Node) 
targetNode: Node | null = null; // 等价于 targetNode: Node = null!;

// 属性参数不可带有'_', 否则只会序列化,不会在属性面板显示
@property(Label)
_title = null;

如果是基础数据类型,注意:

  • 不要使用number, boolean, string等,要使用封装的CCInteger等,否则编译器无法识别
  • 也可以忽略掉,直接编写类似代码
@property() maxValue = 0;

生命周期

继承于Component的脚本,都会有着对应的生命周期,其主要回调方法接口有:

  • onLoad :组件脚本的初始化阶段,在组件被加载后立即调用
  • onEnable:组件的enable属性或节点的active属性由false变为true时,会被调用。
  • start :在onLoad之后调用,通常用于初始化一些中间状态的数据,比如定时器等
  • update:主要用于每一帧渲染钱更新物体的行为,状态和方位。
  • lateUpdate:主要用于组件在执行update之后执行的其他操作。
  • onDisable : 组件的enable属性或者节点的active属性由true变为false时,会被调用。
  • onDestory : 组件或节点调用了destroy(),则被调用,并在当前帧结束时统一回收组件。

从左到右执行顺序:

部落冲突iOS脚本_部落冲突iOS脚本_02

他们的方法属性均被protected修饰,示例代码:

import { _decorator, Component, Button} from 'cc';
const { ccclass, property, executeInEditMode } = _decorator;

@ccclass('mainScene')
// 设置当前组件在编译模式下运行,默认为false 
@executeInEditMode(true)
export class mainScene extends Component {
    private _init = false;
	
    onLoad() {
        console.log("onLoad");
    }
    onEnable() {
        console.log("onEnable");
    }
    start () {
        console.log("start");
    }
    update() {
    	if (this._init == false) {
    		console.log("update");
    	}
    }
    lateUpdate() {
    	if (this._init == false) {
    		console.log("lateUpdate");
    		this._init = true;
    	}
    }
    onDisable() {
        console.log("onDisable");
        this._init = false;
    }
    onDestroy() {
        console.log("onDestroy");
    }
}

当组件脚本被添加到节点中,生命周期执行顺序:

// 如果未激活节点,不会执行;节点激活会执行
onLoad
onEnable
start
update
lateUpdate
// 节点或组件脚本的`active`属性由true变为false
onDisable
// 节点或组件脚本的`active`属性由false变为true
onEnable
update
lateUpdate
// 将组建脚本从节点中删除
onDisable
onDestory

注意事项

这里稍微的说明下关于生命周期回调的注意事项相关:

  • onLoad 可以理解为对组件属性的初始化,比如通过对预制体的克隆instantiate成功后,首先会调用该回调。
    千万注意:无论组件启用或禁用,它只会被调用一次。
  • start 这里可以用来设置启动定时器,一些临时变量的初始化等,当然针对于临时变量的初始化也可以放在onLoad中。
  • onEnable/onDisable 可以放置组件或节点的事件回调, 甚至自定义事件回调,定时器的关闭等,比如:
protected onEnable(): void {
  this.node.on(Node.EventType.TOUCH_START, this.touchStartEvent, this);
	this.node.on(Node.EventType.TOUCH_MOVE, this.touchMoveEvent, this);
}

protected onDisable(): void {
  this.node.off(Node.EventType.TOUCH_START, this.touchStartEvent, this);
	this.node.off(Node.EventType.TOUCH_MOVE, this.touchMoveEvent, this);
}

这里放置触摸事件或自定义事件,一般都是配对使用,这样有利于代码的安全性。

但要注意: 如果项目需要物理的支持,其回调一定要放在onLoad中,否则在在物体发生碰撞时无法检测到回调事件发生

  • onDestory 主要在于组件销毁的时候调用,编写方式:
onDestory() {
  // 虽然说组件的删除在下一帧的时候执行删除
  // 但可能因为逻辑处理较为复杂,在物理碰撞以及射击游戏,或者切水果游戏当中,会使用setTimeout
  // 人为的延迟下,再调用删除接口,这样避免出现错误
  setTimeout(() => {
    // 如果是更有效的判定,就增加个if处理,比如if (this.node && this.node.isValid)
    // 这种方式常用于定时器或者异步编程中
    this.node.destroy();
  }, 1000);
}