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 getComponent
to 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 getComponent
method 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, getComponent
null 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.
(2) Declare an Node
attribute of type
For example:
@property({type:Node})
private Body = null;
At this time, the body node in the attribute inspector is as follows:
(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:
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);
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:
(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
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 getComponent
to get the PlayerControl.
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 find
the 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 import
to 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.node
Access the node where the current script is located.
this.node.active
Indicates 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 active
to 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
update
methods will be executed every frame thereafter. - If there are
onEnable
methods 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
position
variables: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 parentNode
and 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
isValid
judged 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 destroy
instead directly removeFromParent
, and there is no need to set it parent
to null
, otherwise it will cause a memory leak.
4. Common interfaces of components
Component
It is the base class of all components. Any component includes the following common interfaces:
this.node
: The node instance to which this component belongsthis.enabled
: Whether to executeupdate
the method of this component every frame, and also used to control whether the rendering component is displayedupdate(deltaTime: number)
: As a member method of the component, when the component'senabled
property istrue
, 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 foronLoad
logic that needs to be executed after the initialization of all components.