Bootstrap

CocosCreator开发系列教程(三):Cocos Creator场景树与节点

本章内容

了解Cocos Creator场景树与节点的相关知识

一、场景树与cc.Node

Cocos Creator 中的场景树是其核心功能之一,它通过节点(Node)和节点组件(Component)的结合,实现了灵活的场景结构管理。

节点(Node)

节点是场景中最基本的逻辑单元,场景树中的每个元素,我们叫做节点,每个节点都可以包含其他节点,并通过父子关系(Parent Relationship)与其它节点连接。节点不仅能够管理自身的属性,还能携带多个组件(Component),以扩展功能。

  父子关系(Hierarchy)

  每个节点都有且只有一个父节点,可以拥有一个或多个子节点,除了场景根节点外。父子关系允许节点在场景中建立层级结构,例如:parent->child1->child2,移动父节点,那么子节点也会跟着移动。
在这里插入图片描述

这种结构使得开发者能够轻松地组织和管理场景中的实体。

每个节点上都有其相对应的节点信息(Posiiton、Rotation、Scale等),以及所携带的对应的组件,例如这里parent节点携带了Sprite组件
在这里插入图片描述
编辑器上,每个节点也会有一个添加组件实例的按钮。

  cc.Node

  1.cc.Node维持了这个节点的位置(Position)、大小(Size)、旋转(Rotation)、缩放(Scale)等节点信息
  2.同时也维持了场景的关系域:父亲节点的相关信息
  3.节点是事件的载体,可以进行事件的监听
  4.节点的一些其他的接口方法

二、场景树中寻找节点

在这里插入图片描述
如果想要查找child2节点,需要怎么做呢?
在这里插入图片描述

cc.find()

通过creator.d.ts文件,我们看到一个cc.find接口,这个接口函数通过传入path路径来获取一个节点,具体含义是:
按层次结构路径查找节点,路径区分大小写。它将通过使用“/”字符分割路径来遍历层次结构。即使节点处于非活动状态,此函数仍将返回节点。建议不要在每一帧都使用此功能,而是在启动时缓存结果。

这里新建一个脚本组件,挂载到parent节点下,在onLoad函数中编写代码

cc.Class({
    extends: cc.Component,

    properties: {

    },

    onLoad () {
        let node = cc.find('Canvas/parent/child1/child2')
        console.log(node)
    },

});

由于child2所在路径是 Canvas -> parent - > child1 - > child2
那么通过cc.find(‘Canvas/parent/child1/child2’) 就可以查询到child2节点,用一个临时变量node来接收它,并将它进行打印。

如果同一个父节点下面有两个名字相同的节点,那么会查询到谁呢?
在这里插入图片描述
当这个接口第一次找到所包含名称的节点时,就会立即返回这个节点,所以这里查询到第一个child2(数字1对应的)就返回了,不会继续向下查询了。

node具有的一些常见属性(通过node.获取)含义
name节点名称
parent节点的父亲
children子节点(数组)
   let node = cc.find('Canvas/parent/child1/child2')
   console.log("节点的名称:" + node.name)
   console.log("节点的父亲:" + node.parent)
   console.log("节点的子节点:" + node.children)

在这里插入图片描述
在这里插入图片描述

getChildByName()

还有一种在当前节点查找子节点的方式
在这里插入图片描述

let node = this.node.getChildByName("child1").getChildByName("child2");

通过当前组件所在节点(parent)调用getChildByName(“下一级子节点名称”)的方式,也可以一层一层的向下查询子节点。
注意:这个方式不能查找当前节点的父节点

在这里插入图片描述

addChild()

通过addChild()方法可以将节点添加到其他节点下,后续章节会详细讲到。

在这里插入图片描述

removeFromParent()

通过removeFromParent() 方法将当前节点删除。

 

通过便历当前节点的children数组,可以获取当前节点的下一级所有子节点

        for (let i = 0; i < this.node.children.length; i++) {
            console.log(this.node.children[i])
        }

三、节点中找组件实例

getComponent()

目标:查找当前组件所在节点的(Sprite)组件,那么应该怎么做呢?
在这里插入图片描述
(1)找到当前节点----> this.node
(2)找当前节点的Sprite组件实例,用getComponent函数获取

cocosAPI是这样解释的:

	Returns the component of supplied type if the node has one attached, null if it doesn't.<br/>
	You can also get component in the node by passing in the name of the script.
	!#zh
	获取节点上指定类型的组件,如果节点有附加指定类型的组件,则返回,如果没有则为空。<br/>
	传入参数也可以是脚本的名称。
	@param typeOrClassName typeOrClassName
	
	@example 
	```js
	// get sprite component
	var sprite = node.getComponent(cc.Sprite);
	// get custom test class
	var test = node.getComponent("Test");
	```
	*/
	getComponent<T extends Component>(type: {prototype: T}): T;
	getComponent(className: string): any;		
let sprite = this.node.getComponent(cc.Sprite)

这样就获取到了当前节点的Sprite实例

 

getComponents()

一个节点可以有多个组件实例,那么如果想一次性都把他们查询出来呢

	@example 
	```js
	var sprites = node.getComponents(cc.Sprite);
	var tests = node.getComponents("Test");
	```
	*/
	getComponents<T extends Component>(type: {prototype: T}): T[];
	getComponents(className: string): any[];		
	/**
	!#en Returns the component of supplied type in any of its children using depth first search.
	!#zh 递归查找所有子节点中第一个匹配指定类型的组件。
	@param typeOrClassName typeOrClassName

通过getComponents()接口可以获取到所有的组件实例

 

addComponent()

如果想往一个节点上添加一个组件实例要怎么做呢?

	/**
	!#en Adds a component class to the node. You can also add component to node by passing in the name of the script.
	!#zh 向节点添加一个指定类型的组件类,你还可以通过传入脚本的名称来添加组件。
	@param typeOrClassName The constructor or the class name of the component to add
	
	@example 
	```js
	var sprite = node.addComponent(cc.Sprite);
	var test = node.addComponent("Test");
	```
	*/
	addComponent<T extends Component>(type: {new(): T}): T;
	addComponent(className: string): any;		
	/**

通过addComponent()函数可以将组件实例添加到节点中
例如:

this.node.addComponent(cc.Sprite)

这样就将Sprite组件实例添加到当前节点中了

;