CocosCreator3.8 Research Notes (8) Use of CocosCreator Nodes and Components


We know that there are two ways to modify nodes and components in CocosCreator:

  • Settings in the Property Inspector
  • Dynamic modification in script

Dynamic modification in the script can realize various game logic, such as responding to player input, deleting, modifying, and destroying nodes or components.

However, in order to implement these game logic, you need to access these components or nodes in the script.


1. Access nodes


1. Get the node where the component is located


Just access the this.node variable in the component method.

onLoad() {
        
   let node = this.node;
   node.setPosition(0.0,0.0,0.0);
}

2. Get other components on the same node


Use getComponentto find the required components and pass in the type, for example:

  this.sprite = this.getComponent(Sprite);

It can also be obtained by passing in the class name. For custom components, the class name is the file name of the script and is case-sensitive :

  this.testSprite = this.getComponent("TestSprite");

There is also a getComponentmethod on the node, which has the same effect:

 console.log( this.node.getComponent(Label) === this.getComponent(Label) );  // true

If the component is not found on the node, getComponentnull will be returned, accessing a null value will throw a "TypeError" error at runtime,

If you are not sure whether the component exists, you need to check:

 this.label = this.getComponent(Label);
 if (this.label) {
 		this.label.string = "test";
 } else {
 		console.error("this.label is null");
 }

3. Set nodes and use them in the attribute inspector


Here is the Node node as an example:

(1) Add a Node node to the hierarchy manager named Body.

Insert image description here


(2) Declare an Nodeattribute of type

For example:

@property({type:Node})
private Body = null;

At this time, the body node in the attribute inspector is as follows:

Insert image description here


(3). Drag the Body node in the hierarchy manager into the corresponding Node in the property inspector on the right.


After dragging in, the display is as follows:

Insert image description here


After doing this, the Body property will be set successfully and we can access the Body in the script.


(4) Access the Body node in the script

log('Body==' + this.Body.name);

Insert image description here


4. Set components and use them in the property inspector


Here is the player component as an example:


(1). Add a main node in the hierarchy manager and the main.ts script in the resource manager.

And in the property inspector, drag the main.ts script in and bind it to the main node.


As shown in the picture:

Insert image description here


(2) Add an attribute of type playercontrol to main.ts

    @property({type:PlayerControl})
    private PlayerControl = null;

(3) Drag the Player node in the hierarchy manager into the PlayerControl corresponding to the property inspector on the right


Insert image description here


After passing the above settings, we can access PlayerControl in the script.


(4) Access PlayerControl in the script

​ This way you don't need to call it yourself getComponentto get the PlayerControl.

Insert image description here


5. Find child nodes

Sometimes there are many components in a scene, and a script is needed to manage them uniformly, as shown in the main.ts function above.


If you use the property inspector to associate them to this script one by one, the workload will be very large.


In order to better manage these objects in a unified manner, we can put them under a parent node, and then obtain all child nodes through the parent node:


let cannons = this.node.children;

You can also get it by the name of the child node:

this.node.getChildByName("child name");

If the level of child nodes is deeper, you can also use findthe passed-in path to perform a level-by-level search:

find("a/b/c", this.node);

2. Access the value in an existing variable


You can use importto implement cross-file operations in scripts.

Each script can use import{ } from+ file name (without path) to obtain the object of the other party's exports.


For example: there is a utils.ts script

// , now the filename matters
import { _decorator, Component, Node } from 'cc';
const { ccclass, property } = _decorator;

@ccclass("utils")
export class utils extends Component {

    public static utilsNode: any = null;
    public static utilsLabel: any = null;
}

Use utils.ts in user.ts, access utils.utilsNode \utils.utilsNode bi

 
import { _decorator, Component, Node, Label } from 'cc';
const { ccclass, property } = _decorator;
// this feels more safe since you know where the object comes from
import{utils}from "./utils";

@ccclass("user")
export class user extends Component {
    onLoad() {
        utils.utilsNode = this.node;
        utils.utilsLabel = this.getComponent(Label);
    }
}


3. Node common interface


1. Create a new node

let node =new Node('a');
node.setPosition(0,0,-10);

2. Node activation and shutdown

this.nodeAccess the node where the current script is located.

this.node.activeIndicates the activation status of the node itself . Whether this node can currently be activated depends on its parent node.


Determine whether the node is currently activated:

activeInHierarchy 

Activate node

this.node.active = true; 

If the node is originally in a state that can be activated , changing it activeto true will immediately trigger the activation operation:

  • Reactivate the node and all active child nodes under the node in the scene.
  • All components on this node and all child nodes will be enabled, and their updatemethods will be executed every frame thereafter.
  • If there are onEnablemethods on these components, these methods will be executed.

When a node is closed, all its components will be disabled, and all its child nodes, as well as the components on the child nodes, will also be disabled.


3. Index child nodes

  • this.node.children: Returns an array of all child nodes of the node.
  • this.node.children.length: Returns the number of child nodes of the node.

Note : The above two APIs will only return the direct child nodes of the node, not the child nodes of the child node.


4. Change node location

There are two methods:

  • How to use setPosition:

    this.node.setPosition(1, 1, 0);
    this.node.setPosition(new Vec3(1, 1, 0))
    
  • Set positionvariables:

    this.node.position = new Vec3(1, 1, 0);
    

5. Change node rotation

this.node.setRotation(90, 90, 0);

Set local rotation via Euler angles:

this.node.setRotationFromEuler(90, 90, 0);

6. Change node scaling

this.node.setScale(1, 1, 0);

7. Change the parent node of a node

Assume that the parent node is parentNodeand the child node is this.node.

It can be adjusted in the following two ways:

this.node.parent = parentNode;
this.node.removeFromParent();
parentNode.addChild(this.node);

8. Clone node

Cloning nodes is done via instantiate.

import { _decorator, Component, Node,instantiate, director } from 'cc';
const { ccclass, property } = _decorator;

@ccclass("testClone")
export class testClone extends Component {

    @property({type:Node})
    private target: Node = null;

    start(){
        let scene = director.getScene();
        let node = instantiate(this.target);

        scene.addChild(node);
        node.setPosition(0, 0,-10);
    }
}

9. Destroy nodes

Destroying nodes can be done using node.destroy()and node.removeFromParent().

The difference between the two:

  • By calling node.destroy()the function, the destroyed node will not be removed immediately, it will be executed after the logic update of the current frame is completed.

    When a node is destroyed, the node is in an invalid state, and it can be isValidjudged whether the current node has been destroyed by .

  • By calling the `node.removeFromParent() function, the node is not released from memory because its data is still held internally by the engine.


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

@ccclass("testDestroy")
export class testDestroy extends Component {

    @property({type:Node})
    private target: Node = null;

    private positionz: number = -20;

    start(){
        // 10秒后销毁节点
        setTimeout(function () {
            this.target.destroy();
          }.bind(this), 10000);
    }
    update(deltaTime: number){
        console.info(this.target.isValid);
        this.positionz += 1*deltaTime;
        if (this.target.isValid) {
            this.target.setPosition(0.0,0.0,this.positionz);
          }
    }
}

Summarize:

If a node is no longer used, call its destroyinstead directly removeFromParent, and there is no need to set it parentto null, otherwise it will cause a memory leak.


4. Common interfaces of components

ComponentIt is the base class of all components. Any component includes the following common interfaces:

  • this.node: The node instance to which this component belongs
  • this.enabled: Whether to execute updatethe method of this component every frame, and also used to control whether the rendering component is displayed
  • update(deltaTime: number): As a member method of the component, when the component's enabledproperty is true, the code in it will be executed every frame.
  • onLoad(): Executed when the node where the component is located is initialized.
  • start()update: Will be executed before the first time of this component , usually used for onLoadlogic that needs to be executed after the initialization of all components.

Guess you like

Origin blog.csdn.net/lizhong2008/article/details/132699419