Finding Entities
Your code often needs an entity that it did not create: the player, the door that a key opens, every enemy in the level. Every entity can search itself and its descendants for others, so you can search the whole scene from app.root, or a smaller part of it from any entity below.
Search Methods
| To find entities | The first match | Every match |
|---|---|---|
| By name | findByName('door') | find('name', 'door') |
| By path | findByPath('house/door') | - |
| By tag | - | findByTag('enemy') |
| With a component | findComponent('light') | findComponents('light') |
| With a script | findScript('health') | findScripts('health') |
| That pass a test of your own | findOne(entity => ...) | find(entity => ...) |
The searches are depth-first: they visit an entity's first child and all of its descendants before its second child. They cover the entity you call them on as well as its descendants, except findByTag(), which only searches the descendants. The methods that look for the first match return null when there is none, apart from findScript(), which returns undefined. The ones that look for every match return an empty array.
findComponent() and findComponents() return components rather than entities, and findScript() and findScripts() return script instances. Each of these has an entity property for the entity it belongs to.
By Name
const door = app.root.findByName('door');
Names do not have to be unique, so findByName() returns whichever matching entity it reaches first. To get all the entities with a name, use find('name', 'door'). If you give entities unique names, findByName() is the simplest way to find them.
By Path
A path names the entities on the way down to the one you want, separated by slashes, starting below the entity you search from. It picks out one entity even when names repeat elsewhere in the scene:
const door = house.findByPath('ground-floor/door');
An entity's path property is its path from the root of the hierarchy. In a scene made in the Editor, every entity is below the scene's root entity, called Root, so paths from app.root start with it:
const door = app.root.findByPath('Root/house/ground-floor/door');
console.log(door.path); // 'Root/house/ground-floor/door'
By Tag
Tags label groups of entities, and findByTag() returns every descendant with a tag. Pass several tags to find entities with any of them, and an array of tags to find entities with all of them:
const enemies = app.root.findByTag('enemy');
// entities tagged 'enemy' OR 'boss'
const hostile = app.root.findByTag('enemy', 'boss');
// entities tagged both 'enemy' AND 'flying'
const flyers = app.root.findByTag(['enemy', 'flying']);
To test a single entity, entity.tags.has() takes its arguments in the same way, so goblin.tags.has('enemy', 'boss') is true if the goblin has either tag.
By Component or Script
// every light in the scene
const lights = app.root.findComponents('light');
lights.forEach(light => light.enabled = false);
// the first instance of the Health script below the player, by class or by name
const health = player.findScript(Health);
With a Test of Your Own
find() and findOne() take a function, which is called for each entity and returns true for the ones you want:
const coins = level.find(entity => entity.name.startsWith('coin') && entity.enabled);
To visit every entity in a subtree without collecting them, use forEach():
level.forEach(entity => console.log(entity.path));
On Each Surface
- Engine
- Editor
- React
- Web Components
Call the methods on app.root to search the whole scene, or on any entity to search the entities below it. In a script, this.app.root is the root and this.entity is the script's own entity:
const wheels = this.entity.findByTag('wheel');
To find entities while you edit, type in the search box at the top of the Hierarchy. Click the magnifying glass to choose what it matches: Name, Component Type, Script Name or Tags, the same things the search methods look for. Smart Search also matches names that are close to what you type.

In scripts, you rarely need to search. Give the script an entity attribute and drag the entity onto it in the Inspector. The reference then survives renaming and moving the entity, which a search by name or path does not:
import { Entity, Script } from 'playcanvas';
export class Key extends Script {
static scriptName = 'key';
/**
* The door that this key opens.
*
* @attribute
* @type {Entity}
*/
door;
open() {
this.door.enabled = false;
}
}
You rarely need to search, because you rendered the entities yourself. Keep a ref to the ones your code needs:
const door = useRef(null);
<Entity ref={door} name="door" />
To search the scene, start from the root of the application, in an effect so that the entities you rendered exist:
import { useEffect } from 'react';
import { useApp } from '@playcanvas/react/hooks';
const app = useApp();
useEffect(() => {
const enemies = app.root.findByTag('enemy');
}, [app]);
The document mirrors the hierarchy, so you can select an entity's element with a CSS selector. Its entity is null until the element is ready, so wait for it with whenReady(), which takes the same selector:
import { whenReady } from '@playcanvas/web-components';
const door = await whenReady('pc-entity[name="door"]');
console.log(door.entity.getPosition().toString());
The DOM sees the markup, not the engine's state. For entities created from code, and for tags added at runtime, search the engine instead:
import { whenReady } from '@playcanvas/web-components';
const { app } = await whenReady('pc-app');
const enemies = app.root.findByTag('enemy');
Searching Efficiently
A search visits every entity it covers, so its cost grows with the size of the scene below it.
- Search once. Find the entities a script needs in its
initializemethod and keep them, rather than searching every frame. - Search close by. Searching from the nearest entity that you know of visits fewer entities than searching from
app.root. - Prefer references. An entity attribute, a ref or an element you keep is faster than any search, and does not break when names change.
To browse the hierarchy of a running application, and to see what its entities and components are set to right now, use the Inspector debug panel.
See Also
- Entities - Naming and tagging entities
- Script Attributes - Passing entity references to scripts
- Hierarchy Panel - Searching the hierarchy in the Editor
- GraphNode, Entity and Tags - The engine API reference