Access Nodes and Components

You can modify Nodes and Components in the Inspector panel, and also dynamically using scripts. The advantage of dynamic modification is that it can continuously modify attributes and transition attributes within a period of time to achieve gradual effects. Scripts can also respond to player input, modify, create and destroy Nodes or Components, and implement various game logic. To achieve these effects, developers need to obtain the Node or Component that needs to be modified in the script.

Document topics

  • Obtain the node where the component is located.
  • Obtain other components.
  • Use Inspector panel to set up nodes and components.
  • Find child nodes.
  • Global node search.
  • Access values in existing variables.

Obtain the node where the component is located

It’s easy to get the node where the component is. Just access the this.node variable in the component method:

  1. start(){
  2. let node = this.node;
  3. node.setPosition(0.0,0.0,0.0);
  4. }

Obtaining other components

It will often be need to get other components on the same node. Use the getComponent API, which will help to find the component that is needed.

  1. import { _decorator, Component, LabelComponent } from 'cc';
  2. const { ccclass, property } = _decorator;
  3. @ccclass("test")
  4. export class test extends Component {
  5. private label: any = null
  6. start(){
  7. this.label = this.getComponent(LabelComponent);
  8. let text = this.name + 'started';
  9. // Change the text in Label Component
  10. this.label.string = text;
  11. }
  12. }

It is also possible to pass in a class name for getComponent. For user-defined components, the class name is the file name of the script and is case sensitive. For example, the component declared in SinRotate.ts, the class name is SinRotate.

  1. let rotate = this.getComponent("SinRotate");

There is also ther getComponent method on the node, and their functions are the same:

  1. start() {
  2. console.log( this.node.getComponent(LabelComponent) === this.getComponent(LabelComponent) ); // true
  3. }

If the component that is needed is not found on the node, getComponent will return null. If you try to access the value of null, a TypeError error will be thrown at runtime. If you are not sure whether the component exists, please remember to check:

  1. import { _decorator, Component, LabelComponent } from 'cc';
  2. const { ccclass, property } = _decorator;
  3. @ccclass("test")
  4. export class test extends Component {
  5. private label: any =null;
  6. start() {
  7. this.label = this.getComponent(LabelComponent);
  8. if (this.label) {
  9. this.label.string = "Hello";
  10. } else {
  11. console.error("Something wrong?");
  12. }
  13. }
  14. }

Get other nodes and their components

It is usually not enough to only have access to the node’s own components, and scripts usually require interaction between multiple nodes. For example, a cannon that automatically aims at the player needs to constantly obtain the latest position of the player. Cocos Creator provides some different methods to obtain other nodes or components.

Use the Inspector panel to set the node

The most straightforward way is to set the objects you need in the Inspector panel. Take node as an example, this only needs to declare an attribute with type Node in the script:

  1. // Cannon.ts
  2. import { _decorator, Component, Node } from 'cc';
  3. const { ccclass, property } = _decorator;
  4. @ccclass("Cannon")
  5. export class Cannon extends Component {
  6. // Declare Player properties
  7. @property({type:Node})
  8. private player = null;
  9. }

This code declares a player property in properties, the default value is null, and its object type is specified as Node. This is equivalent to declaring public Node player = null; in other languages. After the script is compiled, this component looks like this in the Inspector panel:

player-in-inspector-null

Then you can drag any node on the Hierarchy panel to the Player control:

player-in-inspector

The Player property will be set successfully, and can be accessed directly in a script. Example:

  1. // Cannon.ts
  2. import { _decorator, Component, Node } from 'cc';
  3. const { ccclass, property } = _decorator;
  4. @ccclass("Cannon")
  5. export class Cannon extends Component {
  6. @property({type:Node})
  7. private player = null;
  8. start() {
  9. console.log('The player is ' + this.player.name);
  10. }
  11. }

Use the Inspector panel to set up components

In the above example, if the type of the attribute is declared as a Player component, when the Player node is dragged to the Inspector panel, the Player attribute will be set to the Player component in this node. This way developers don’t need to call getComponent() themselves.

  1. // Cannon.ts
  2. import { _decorator, Component } from 'cc';
  3. const { ccclass, property } = _decorator;
  4. import { Player } from "Player";
  5. @ccclass("Cannon")
  6. export class Cannon extends Component {
  7. @property({type:Player})
  8. private player = null;
  9. start(){
  10. let PlayerComp = this.player;
  11. }
  12. }

The default value of the property can be changed from null to array [], so that multiple objects in the Inspector panel can be set at the same time. However, if dynamically obtaining other objects at runtime is needed, it is also necessary to use the search method described below.

Find child nodes

Sometimes, there are many objects of the same type in the game scene, such as turrets, enemies, and special effects, and they usually have a global script to manage them uniformly. Using the Inspector panel to associate them with this script one by one, the work will be very tedious. In-order to better manage these objects uniformly, they can be put under a unified parent object, and then obtain all the child objects through the parent object:

  1. // CannonManager.ts
  2. import { _decorator, Component, Node } from 'cc';
  3. const { ccclass, property } = _decorator;
  4. @ccclass("CannonManager")
  5. export class CannonManager extends Component {
  6. start() {
  7. let cannons = this.node.children;
  8. //...
  9. }
  10. }

Using getChildByName:

  1. this.node.getChildByName("Cannon 01");

If the child node has a deeper level, find can be used, and will search step by step according to the path passed in:

  1. find("Cannon 01/Barrel/SFX", this.node);

Global name lookup

When find only passes in the first parameter, it will be searched step by step from the scene root node:

  1. this.backNode = find("Canvas/Menu/Back");

Accessing values in existing variables

If you have saved references to nodes or components in one place, you can also access them directly.

Accessing via module

Use import to implement script cross-file operations. Example:

  1. // Global.ts, now the filename matters
  2. import { _decorator, Component, Node } from 'cc';
  3. const { ccclass, property } = _decorator;
  4. @ccclass("Global")
  5. export class Global extends Component {
  6. public static backNode:any=null;
  7. public static backLabel:any=null;
  8. }

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

  1. // Back.ts
  2. import { _decorator, Component, Node, LabelComponent } from 'cc';
  3. const { ccclass, property } = _decorator;
  4. // this feels more safe since you know where the object comes from
  5. import{Global}from "./Global";
  6. @ccclass("Back")
  7. export class Back extends Component {
  8. onLoad(){
  9. Global.backNode=this.node;
  10. Global.backLabel=this.getComponent(LabelComponent);
  11. }
  12. }
  1. // AnyScript.ts
  2. import { _decorator, Component, Node } from 'cc';
  3. const { ccclass, property } = _decorator;
  4. // this feels more safe since you know where the object comes from
  5. import{Global}from "./Global";
  6. @ccclass("AnyScript")
  7. export class AnyScript extends Component {
  8. start () {
  9. const text = "Back";
  10. Global.backLabel.string=text;
  11. }
  12. }