跳到主要内容

查找实体

代码经常需要访问并非由它创建的实体,例如玩家、钥匙对应的门或关卡中的所有敌人。每个实体都可以搜索自身及后代,因此既可从 app.root 搜索整个场景,也可从任意下级实体搜索更小范围。

查找方法​

查找条件首个匹配项所有匹配项
名称findByName('door')find('name', 'door')
路径findByPath('house/door')-
标签-findByTag('enemy')
包含指定组件findComponent('light')findComponents('light')
包含指定脚本findScript('health')findScripts('health')
满足自定义条件findOne(entity => ...)find(entity => ...)

查找采用深度优先顺序:先访问第一个子实体及其全部后代,再访问第二个子实体。除 findByTag() 只搜索后代外,其余方法都会包含调用方法的实体自身。查找首个匹配项的方法在未找到时返回 null,但 findScript() 返回 undefined;查找全部匹配项的方法则返回空数组。

findComponent() 和 findComponents() 返回组件而非实体,findScript() 和 findScripts() 返回脚本实例。它们都具有 entity 属性,指向所属实体。

按名称查找​

const door = app.root.findByName('door');

名称不必唯一,因此 findByName() 返回首先遇到的匹配实体。要获得全部同名实体,使用 find('name', 'door')。若使用唯一名称,findByName() 就是最简单的查找方式。

按路径查找​

路径从被搜索实体的下级开始,按从上到下的实体名称排列,以斜杠分隔。即使场景其他位置存在同名实体,也能定位到具体对象:

const door = house.findByPath('ground-floor/door');

实体的 path 属性表示从层级根开始的完整路径。编辑器创建的场景中,所有实体都位于名为 Root 的场景根实体下,因此从 app.root 开始的路径也要以它开头:

const door = app.root.findByPath('Root/house/ground-floor/door');
console.log(door.path); // 'Root/house/ground-floor/door'

按标签查找​

标签用于标记实体分组,findByTag() 返回带有指定标签的所有后代。传入多个标签,匹配具有其中任意标签的实体;传入标签数组,则匹配同时具有数组中所有标签的实体:

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

检查单个实体时,entity.tags.has() 使用相同的参数规则,因此哥布林只要具有任一标签,goblin.tags.has('enemy', 'boss') 就为 true。

按组件或脚本查找​

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

使用自定义条件​

find() 和 findOne() 接受一个函数,该函数对每个实体执行,对符合要求的实体返回 true:

const coins = level.find(entity => entity.name.startsWith('coin') && entity.enabled);

要遍历子树中的所有实体而不收集结果,使用 forEach():

level.forEach(entity => console.log(entity.path));

各种开发方式中的用法​

对 app.root 调用方法可搜索整个场景,对任意实体调用则搜索其下方内容。在脚本中,this.app.root 是根节点,this.entity 是脚本自身附加的实体:

const wheels = this.entity.findByTag('wheel');

高效查找​

一次查找会访问覆盖范围内的所有实体,因此开销随下方场景规模增加。

  • **只查找一次。**在脚本的 initialize 中找到所需实体并保留引用,避免每帧查找。
  • **缩小范围。**从已知的最近实体开始,比从 app.root 开始访问的实体更少。
  • **优先使用引用。**实体属性、ref 或保留的元素引用都比搜索更快,也不会因名称变化而失效。

要浏览运行中应用的层级,并查看实体及组件的当前设置,使用 Inspector 调试面板。

另请参阅​