Skip to main content

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 entitiesThe first matchEvery match
By namefindByName('door')find('name', 'door')
By pathfindByPath('house/door')-
By tag-findByTag('enemy')
With a componentfindComponent('light')findComponents('light')
With a scriptfindScript('health')findScripts('health')
That pass a test of your ownfindOne(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​

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');

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 initialize method 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​