> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/interatividade/raycasting.md).

# Raycasting

Raycasting é uma ferramenta fundamental no desenvolvimento de jogos. Com raycasting, você pode traçar uma linha imaginária no espaço e consultar se alguma entidade é interceptada por essa linha. Isso é útil para calcular linhas de visão, trajetórias de balas, algoritmos de pathfinding e muitas outras aplicações.

Quando um player pressiona o botão do pointer, ou o botão primário ou secundário, um ray é traçado a partir da posição do player na direção para onde ele está olhando, veja [eventos de botão](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md) para mais detalhes sobre isso. Este documento aborda como traçar um ray invisível a partir de qualquer posição e direção arbitrárias, independentemente das ações do player, o que você pode usar em muitos outros cenários.

Observe que raycasts só atingem objetos com colliders. Então, se você quiser detectar acertos de ray contra um modelo 3D, então:

* O modelo deve conter [malhas de collider](/creator/content-creator-pt/modelacao-e-animacoes-3d/colliders.md).
* O `GLTFContainer` deve ser configurado para usar a [geometria visível com máscaras de colisão](/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/colliders.md#colliders-on-3d-models).
* Adicione um [componente MeshCollider](/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/colliders.md).

Também é uma boa prática atribuir [camadas de colisão personalizadas](/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/colliders.md#collision-layers) a modelos 3D, para que os rays só precisem calcular colisões contra as entidades relevantes, em vez de contra tudo o que tenha um collider.

## Crie um ray

Todos os rays têm um ponto de origem e uma direção. O ponto de origem se baseia na posição de uma entity, usando os valores do componente Transform da entity. A direção de um ray pode ser definida de 4 maneiras diferentes:

* **local** : Uma direção relativa à direção frontal da entity, também afetada pela transformação de quaisquer entities pai. Isso é útil para detectar obstáculos à frente de veículos, respeitando sua orientação.
* **global** : Ignora a rotação da entity e aponta como se a rotação da entity fosse 0. Isso é útil, por exemplo, para apontar sempre para baixo.
* **global target** : Traça uma linha entre a posição da entity e uma posição global alvo na scene. Ele ignora a rotação da entity. Útil, por exemplo, para criar jogos de tower defense, em que a torreta de cada torre pode apontar para uma coordenada precisa no espaço.
* **target entity** : Traça uma linha entre a posição da entity e a posição de uma segunda entity-alvo. Ele ignora a rotação de ambas as entities.

O código a seguir cria um raycast com uma direção local:

```ts
const myEntity = engine.addEntity()
Transform.create(myEntity, {
  position: Vector3.create(4, 1, 4),
})

raycastSystem.registerLocalDirectionRaycast(
  {
    entity: myEntity,
    opts: { direction: Vector3.Forward() },
  },
  function (raycastResult) {
    // função de callback
  }
)
```

Use as seguintes funções para criar raycasts fornecendo a direção de diferentes maneiras:

* `raycastSystem.registerLocalDirectionRaycast()` : cria um raycast com uma **local** direção. O `campo direction espera um` Vector3 `que descreve um vetor relativo à entity e à sua rotação (por exemplo,` Vector3.Forward() `acabaria usando o vetor forward do Transform da entity)` raycastSystem.registerGlobalDirectionRaycast()
* `que descreve a direção global.` : cria um raycast com uma **global** direção. O `campo direction espera um` Vector3 `que descreve um vetor relativo à entity e à sua rotação (por exemplo,` raycastSystem.registerGlobalTargetRaycast()
* &#x20;`: cria um raycast com uma direção definida por uma`posição. O **global target** alvo. O `alvo` Vector3 `que descreve um vetor relativo à entity e à sua rotação (por exemplo,` que descreve uma posição global na scene.
* `raycastSystem.registerTargetEntityRaycast()` : cria um raycast com uma direção definida em direção a uma **target entity** alvo. O `targetEntity` campo espera uma referência a uma entity; a posição dessa entity será usada como alvo do ray.

Os seguintes campos opcionais estão disponíveis ao criar um ray com qualquer um dos métodos acima:

* `maxDistance`: *number* para definir o comprimento com que este ray será traçado. Se não for definido, o valor padrão é 16 metros.
* `queryType`: *RaycastQueryType* valor enum, para definir se o ray retornará todas as entities atingidas ou apenas a primeira. As seguintes opções estão disponíveis:
  * `RaycastQueryType.RQT_HIT_FIRST`: *(padrão)* retorna apenas a primeira entity atingida, a partir do ponto de origem.
  * `RaycastQueryType.RQT_QUERY_ALL` : retorna todas as entities atingidas, da origem até a distância máxima do ray.
* `originOffset` : Em vez de iniciar o raycast na posição de origem da entity, adicione um offset para iniciar a query a partir de uma posição relativa. Você pode, por exemplo, usar um pequeno offset para impedir que o ray colida com o próprio collider da entity. Se não for definido, o valor padrão é `Vector3.Zero()`.
* `collisionMask` : Detecte apenas colisões com certas camadas de colisão. Use isso junto com uma camada de colisão customizada, ou para detectar apenas a layer de physics ou pointer events. Veja [camadas de colisão personalizadas](/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/colliders.md#collision-layers). Se não for definido, a camada padrão usada é `ColliderLayer.CL_PHYSICS`.
* `continuous` : Se true, manterá uma query de raycast em execução a cada frame. Se false, o ray será usado apenas no frame atual. Se não for definido, o valor padrão é false.
* Ao definir a direção com uma direção local ou global, o `campo direction espera um` campo assume o valor padrão de `acabaria usando o vetor forward do Transform da entity)`.
* Ao definir a direção com um alvo global, o `globalTarget` campo assume o valor padrão de `Vector3.Zero()`.
* Ao definir a direção com um alvo de entity, o `targetEntity` campo assume por padrão a root entity da scene, localizada em `Vector3.Zero()`.

{% hint style="warning" %}
**📔 Nota** : A `continuous` propriedade deve ser usada com cautela, pois executar uma query de raycast em cada frame pode ser muito custoso para o desempenho. Quando possível, use um system (ou a `interval` função na biblioteca Utils) para executar queries de raycast em intervalos regulares mais espaçados, veja [raycasting recorrente](#recurrent-raycasting).
{% endhint %}

Abaixo estão exemplos usando cada um dos quatro métodos para determinar a direção do ray:

```ts
// RAYCAST DE DIREÇÃO LOCAL
raycastSystem.registerLocalDirectionRaycast(
  {
    entity: myEntity,
    opts: {
      queryType: RaycastQueryType.RQT_QUERY_ALL,
      direction: Vector3.Forward(),
      maxDistance: 30,
    },
  },
  function (raycastResult) {
    console.log(raycastResult.hits)
  }
)
// RAYCAST DE DIREÇÃO GLOBAL
raycastSystem.registerGlobalDirectionRaycast(
  {
    entity: myEntity,
    opts: {
      queryType: RaycastQueryType.RQT_QUERY_ALL,
      direction: Vector3.Forward(),
      maxDistance: 30,
    },
  },
  function (raycastResult) {
    console.log(raycastResult.hits)
  }
)
// RAYCAST DE POSIÇÃO ALVO GLOBAL
raycastSystem.registerGlobalTargetRaycast(
  {
    entity: myEntity,
    opts: {
      queryType: RaycastQueryType.RQT_QUERY_ALL,
      globalTarget: Vector3.Zero(),
    },
  },
  (raycastResult) => {
    console.log(raycastResult.hits)
  }
)
// RAYCAST DE ENTITY ALVO
const targetEntity = engine.addEntity()
Transform.create(targetEntity, { position: Vector3.create(8, 1, 10) })

raycastSystem.registerTargetEntityRaycast(
  {
    entity: myEntity,
    opts: {
      queryType: RaycastQueryType.RQT_QUERY_ALL,
      targetEntity: targetEntity,
    },
  },
  (raycastResult) => {
    console.log(raycastResult.hits)
  }
)
```

{% hint style="warning" %}
**📔 Nota**: `raycastSystem`, `RaycastQueryType` e `ColliderLayer` devem ser importados via

> `import { raycastSystem, RaycastQueryType, ColliderLayer } from "@dcl/sdk/ecs"`

Veja [Imports](/creator/content-creator-pt/scenes-sdk7/comecar/coding-scenes.md#imports) para saber como lidar com isso facilmente.
{% endhint %}

## Resultado do raycast

A função de callback que trata o raycast recebe um objeto contendo dados sobre o próprio ray e sobre quaisquer entities atingidas.

* `globalOrigin` : A posição de onde o ray foi originado, relativa à scene.
* `campo direction espera um` : A direção global para a qual o ray estava apontando, como um `que descreve um vetor relativo à entity e à sua rotação (por exemplo,`.
* `hits` : Um array com um objeto para cada entity que foi atingida. Se não houver entities atingidas, este array fica vazio. Se o raycast usou `RaycastQueryType.RQT_HIT_FIRST`, este array conterá apenas um objeto.

Cada objeto no `hits` array inclui:

* `entityId` : Número de identificação da entity atingida pelo ray.
* `meshName`: *String* com o nome interno da mesh específica no modelo 3D que foi atingida. Isso é útil quando um modelo 3D é composto por múltiplas meshes.
* `position`: *que descreve um vetor relativo à entity e à sua rotação (por exemplo,* para a posição onde o ray intersectou a entity atingida (relativa à scene)
* `length` : Comprimento do ray desde sua origem até a posição onde ocorreu o acerto contra a entity.
* `normalHit`: *Quaternion* para o ângulo da normal do acerto no espaço mundial.
* `globalOrigin`: *que descreve um vetor relativo à entity e à sua rotação (por exemplo,* para a posição onde o ray se origina (relativa à scene)
* `campo direction espera um` : A direção global para a qual o ray estava apontando, como um `que descreve um vetor relativo à entity e à sua rotação (por exemplo,`.

O exemplo a seguir itera sobre as entities atingidas:

```ts
const myEntity = engine.addEntity()
Transform.create(myEntity, {
  position: Vector3.create(4, 1, 4),
})

raycastSystem.registerLocalDirectionRaycast(
  {
    entity: myEntity,
    opts: {
      queryType: RaycastQueryType.RQT_QUERY_ALL,
      direction: Vector3.Forward(),
      maxDistance: 30,
    },
  },
  function (raycastResult) {
    if (raycastResult.hits.length > 0) {
      for (const hit of raycastResult.hits) {
        if (hit.entityId) {
          console.log('entity atingida ', hit.entityId)
        }
      }
    } else {
      console.log('nenhuma entity atingida')
    }
  }
)
```

{% hint style="warning" %}
**📔 Nota** : Você pode obter um resultado de raycast ao atingir uma entity em uma scene diferente.
{% endhint %}

## Tratar entities atingidas

Quando você obtém um resultado de raycast que atingiu uma entity, você pode usar o `entityId` para interagir com a entity e seus components. Uma entity é [nada mais do que um número](/creator/content-creator-pt/scenes-sdk7/arquitetura/entities-components.md#overview), então o `entityId` valor em si pode ser interpretado como um `Entity` tipo.

```ts
const hitEntity = result.entityId as Entity
const transform = Transform.get(entity)
console.log(transform.position)
```

## Camadas de colisão

É uma boa prática verificar colisões apenas contra entities relevantes, para tornar a scene mais performática. O `collisionMask` campo permite listar apenas camadas de colisão específicas — a layer physics (paredes e pisos da scene), a layer pointer (pointer events), as layers de player (avatars), ou 8 camadas customizadas que você pode atribuir livremente. Veja [camadas de colisão personalizadas](/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/colliders.md#collision-layers).

Por padrão, o `collisionMask` campo é definido como `ColliderLayer.CL_PHYSICS`. Você pode alterar este valor para listar outras layers ou combinar várias com o `|` separador.

```ts
raycastSystem.registerLocalDirectionRaycast(
  {
    entity: myEntity,
    opts: {
      queryType: RaycastQueryType.RQT_QUERY_ALL,
      direction: Vector3.Forward(),
      maxDistance: 30,
      collisionMask:
        ColliderLayer.CL_CUSTOM1 |
        ColliderLayer.CL_CUSTOM3 |
        ColliderLayer.CL_POINTER,
    },
  },
  (raycastResult) => {
    log(raycastResult.hits)
  }
)
```

## Raycasting recorrente

Ao usar as funções do `raycastSystem`, o comportamento padrão é criar um único ray, que fará uma query de colisão uma vez. Como alternativa, você pode definir o `continuous` campo *true* para executar uma query e a função de callback a cada tick do game loop.

O exemplo a seguir continuará executando a query de raycast a partir deste ponto

```ts
raycastSystem.registerLocalDirectionRaycast(
  {
    entity: myEntity,
    opts: {
      queryType: RaycastQueryType.RQT_QUERY_ALL,
      direction: Vector3.Forward(),
      maxDistance: 30,
      continuous: true,
    },
  },
  function (raycastResult) {
    log(raycastResult.hits)
  }
)
```

{% hint style="warning" %}
**📔 Nota** : A `continuous` propriedade deve ser usada com cautela, pois executar uma query de raycast em cada frame pode ser muito custoso para o desempenho.
{% endhint %}

Quando não precisar mais, remova quaisquer raycasts recorrentes. Para isso, você deve usar `raycastSystem.removeRaycasterEntity`.

```ts
raycastSystem.removeRaycasterEntity(myEntity)
```

Quando possível, use um system (ou a `interval` função na biblioteca Utils) para executar queries de raycast em intervalos regulares mais espaçados, como apenas uma vez por segundo, ou a cada quinto de segundo.

```typescript
// componentes customizados
const CubeOscilator = engine.defineComponent('CubeOscilator', {
  t: Schemas.Float,
})

const TimerComponent = engine.defineComponent('TimerComponent', {
  t: Schemas.Float,
})

const RAY_INTERVAL = 0.1

// verificar rays
engine.addSystem((dt) => {
  for (const [entity] of engine.getEntitiesWith(TimerComponent)) {
    const timer = TimerComponent.getMutable(entity)
    timer.t += dt

    if (timer.t > RAY_INTERVAL) {
      timer.t = 0
      raycastSystem.registerGlobalDirectionRaycast(
        {
          entity: myEntity,
          opts: {
            queryType: RaycastQueryType.RQT_HIT_FIRST,
            direction: Vector3.Forward(),
            maxDistance: 16,
          },
        },
        function (raycastResult) {
          log(raycastResult.hits)
        }
      )
    }
  }
})

TimerComponent.create(engine.addEntity())

// system de cubo oscilante
engine.addSystem((dt) => {
  for (const [entity, cube] of engine.getEntitiesWith(
    CubeOscilator,
    Transform
  )) {
    CubeOscilator.getMutable(entity).t += dt
    Transform.getMutable(entity).position.y = 2 + Math.cos(cube.t)
  }
})

// criar cubo
const cubeEntity = engine.addEntity()
Transform.create(cubeEntity, { position: { x: 8, y: 1, z: 8 } })
CubeOscilator.create(cubeEntity)
MeshRenderer.setBox(cubeEntity)
MeshCollider.setBox(cubeEntity)
```

O exemplo acima executa um raycast recorrente a cada 0,1 segundo. Ele usa um componente timer e a propriedade dt de um system para cronometrar isso de forma uniforme. Também inclui um cubo que oscila para cima e para baixo, controlado por outro system, para entrar e sair do caminho do ray. `dt` propriedade para cronometrar isso de forma uniforme. Também inclui um cubo que oscila para cima e para baixo, controlado por outro system, para entrar e sair do caminho do ray.

{% hint style="info" %}
**💡 Dica** : Use a `interval` função na [biblioteca SDK Utils](https://github.com/decentraland/sdk7-utils) para uma maneira mais simples de executar uma função em um intervalo fixo.
{% endhint %}

## Raycasts via um system

Outra forma de realizar raycasts recorrentes é executá-los dentro da função recorrente de um system. Isso permite que você tenha muito mais controle sobre quando e como eles funcionam. Em vez de registrar uma função de callback, você pode executar uma query de raycast com `raycastSystem.registerRaycast` e então verificar os dados retornados por essa operação, tudo dentro da função do system.

Observe que, como o raycast é executado em um system, o resultado só estará disponível no próximo tick, exigindo duas execuções do system. Uma para registrar o raycast para o próximo frame, e o próximo frame processar seu resultado.

```ts
engine.addSystem((deltaTime) => {
		const result = raycastSystem.registerRaycast(
			entity,
			localDirectionOptions({
				collisionMask: ColliderLayer.CL_CUSTOM1 | ColliderLayer.CL_CUSTOM3 | ColliderLayer.CL_POINTER,
				originOffset: Vector3.create(0, 0.4, 0),
				maxDistance: RAY_POWER,
				queryType: raycastQueryType,
				direction: Vector.forward()
				continuous: true // não use em excesso a propriedade 'continuous', pois raycasting é caro para o desempenho
			})
		)
		if (result) // faça algo
	})
```

## Colidir com o player

Você pode detectar avatars diretamente com raycasts incluindo qualquer uma das layers de colisão de avatar na máscara:

* `ColliderLayer.CL_PLAYER`: corresponde a qualquer avatar — o player local E qualquer outro player renderizado na scene.
* `ColliderLayer.CL_MAIN_PLAYER`: corresponde apenas ao player local (principal).

Ambas as layers podem ser combinadas ou usadas independentemente. O padrão `collisionMask` para um raycast é `CL_PHYSICS`, que NÃO atinge avatars — você precisa ativá-lo explicitamente.

```ts
// Atinge apenas o player local (ignore outros avatars)
raycastSystem.registerLocalDirectionRaycast(
  {
    entity: myEntity,
    opts: {
      direction: Vector3.Forward(),
      collisionMask: ColliderLayer.CL_MAIN_PLAYER,
    },
  },
  (raycastResult) => {
    if (raycastResult.hits.length > 0) {
      console.log('Atingiu o player local')
    }
  }
)

// Atinge qualquer avatar (local + remoto)
raycastSystem.registerLocalDirectionRaycast(
  {
    entity: myEntity,
    opts: {
      direction: Vector3.Forward(),
      collisionMask: ColliderLayer.CL_PLAYER,
    },
  },
  (raycastResult) => {
    // raycastResult.hits[i].entityId é 0 para acertos em avatar remoto (sem id de entity local da scene)
    console.log(raycastResult.hits)
  }
)
```

Quando um raycast atinge o player local, o `hit.entityId` é `engine.PlayerEntity`. Acertos em avatars remotos não carregam um id de entity local da scene (o campo é `0`) já que o player remoto não é uma entity no mundo da sua scene — mas o hit ainda é reportado com seu `position`, `length`, `normalHit`, e outros dados geométricos.

{% hint style="info" %}
**💡 Dica** : Para detectar apenas **outros** players (excluindo o player local), use `CL_PLAYER` e filtre `hit.entityId !== engine.PlayerEntity` na callback.
{% endhint %}

## Raycasts a partir do player

Para traçar um ray a partir da posição do player na direção para a qual a câmera está voltada, você pode traçar um ray usando a câmera ou o avatar [Entidades reservadas](/creator/content-creator-pt/scenes-sdk7/arquitetura/entities-components.md#reserved-entities).

{% hint style="info" %}
**💡 Dica** : Para a maioria dos casos, talvez seja melhor usar [Pointer events](/creator/content-creator-pt/scenes-sdk7/interatividade/eventos-de-botao/click-events.md) em vez de raycasts.
{% endhint %}

O exemplo a seguir traça um ray a partir da posição da câmera do player para frente, usando a entity `engine.CameraEntity` .

```ts
raycastSystem.registerGlobalDirectionRaycast(
  {
    entity: engine.CameraEntity,
    opts: {
      queryType: RaycastQueryType.RQT_HIT_FIRST,
      direction: Vector3.rotate(
        Vector3.Forward(),
        Transform.get(engine.CameraEntity).rotation
      ),
    },
  },
  function (raycastResult) {
    console.log(raycastResult)
  }
)
```

{% hint style="warning" %}
**📔 Nota** : Tenha em mente que, em 3rd person, o cursor no futuro pode não se comportar da mesma forma que em 1st person. Recomenda-se usar isso apenas se o player estiver em 1st person.
{% endhint %}

## Raycast a partir da posição do cursor

Você também pode traçar um ray a partir da posição do cursor do player para o mundo 3D. Isso pode ser usado para arrastar objetos, shooters, etc.

Neste exemplo, detectamos quando o player pressiona a tecla E e então traçamos um ray da posição do cursor para o mundo 3D. Em seguida, verificamos se o ray atingiu alguma entity e, em caso afirmativo, fazemos algo com ela.

```ts
import { engine, Entity, InputAction, inputSystem, PointerEventType, RaycastQueryType, raycastSystem, TextShape, Transform } from '@dcl/sdk/ecs'
import { EntityNames } from '../assets/scene/entity-names'
import { PrimaryPointerInfo } from '@dcl/sdk/ecs'

let cooldown = 1
let rayFrequency = 0.1
let mousePressed = false

export function main() {
   engine.addSystem(rayCastSystem)
}

const rayCastSystem = (t: number) => {

    if (inputSystem.isTriggered(InputAction.IA_PRIMARY, PointerEventType.PET_DOWN)) {
      mousePressed = true
    }

    if (inputSystem.isTriggered(InputAction.IA_PRIMARY, PointerEventType.PET_UP)) {
      mousePressed = false
    }

    if (!mousePressed) {
      cooldown = 0
      raycastSystem.removeRaycasterEntity(engine.CameraEntity)
      return
    }

    cooldown += t
    if (cooldown > rayFrequency) return
    cooldown = 0

    const pointerInfo = PrimaryPointerInfo.getOrCreateMutable(engine.RootEntity)
    let dir = pointerInfo.worldRayDirection

    raycastSystem.registerGlobalDirectionRaycast(
      {
        entity: engine.CameraEntity,
        opts: {
          queryType: RaycastQueryType.RQT_HIT_FIRST,
          direction: dir,
        },
      },
      function (raycastResult) {
        let result = raycastResult.hits[0]

        // faça algo na posição de impacto
        if (result && result.position) {
          console.log("x:", result.position.x, ", y:", result.position.y, ", z:", result.position.z)
        }

        // faça algo com a entidade atingida
        const entity = result.entityId as Entity
        if (entity) {
          console.log("entity: ", entity)
        }
      }
    )
}

```

{% hint style="info" %}
**💡 Dica**: Neste exemplo, usamos o botão principal (E) para disparar o Raycast. Não usamos o botão do ponteiro (clique esquerdo) porque clicar e arrastar também altera o ângulo da câmera por padrão. Se quiser impedir que a câmera gire enquanto arrasta, você pode usar um [Virtual Camera](/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/camera.md) para definir o ângulo da câmera como fixo.
{% endhint %}

## Sintaxe avançada

### Criar um componente Raycast

Um componente Raycast descreve o raio invisível usado para consultar entidades intersectadas. O raio é traçado a partir da posição da entidade, conforme definida pelo componente Transform e afetada pelo das entidades pai. A direção pode ser definida de várias maneiras,

Os raios são definidos usando os seguintes dados:

* `campo direction espera um`: Um objeto que contém um `$case` campo para selecionar o tipo de direção, e um campo adicional que dependerá desse tipo, que determina essa direção. Os seguintes são os valores aceitos para `$case`:
  * `LOCAL_DIRECTION`: Uma direção relativa à direção frontal da entidade, também afetada pela transformação de quaisquer entidades pai. Isso é útil para detectar obstáculos à frente de veículos respeitando seu rumo. A rotação é definida pelo `localDirection` campo, como um `que descreve um vetor relativo à entity e à sua rotação (por exemplo,` que descreve uma rotação.
  * `GLOBAL_DIRECTION`: Ignora a rotação da entidade e aponta para uma direção como se a rotação da entidade fosse 0. Isso é útil, por exemplo, para apontar sempre para baixo. A rotação é definida pelo `globalDirection` campo, como um `que descreve um vetor relativo à entity e à sua rotação (por exemplo,` que descreve uma rotação.
  * `GLOBAL_TARGET`: Traça uma linha entre a posição da entidade e uma posição global alvo na scene. Ignora a rotação da entidade. Útil para criar jogos de tower defense, em que a torreta de cada torre pode apontar para uma coordenada exata no espaço. O alvo é definido pelo `globalTarget` campo, como um `que descreve um vetor relativo à entity e à sua rotação (por exemplo,` que descreve a posição global.
  * `TARGET_ENTITY`: Traça uma linha entre a posição da entidade e a posição de uma segunda entidade alvo. Ignora a rotação de ambas as entidades. O alvo é definido pelo `targetEntity` campo, que contém uma referência à entidade.
* `maxDistance`: *number* para definir o comprimento com que este raio será traçado.
* `queryType`: *RaycastQueryType* valor enum, para definir se o ray retornará todas as entities atingidas ou apenas a primeira. As seguintes opções estão disponíveis:
  * `RaycastQueryType.RQT_QUERY_ALL`: retorna apenas a primeira entidade atingida, a partir do ponto de origem.
  * `RaycastQueryType.RQT_HIT_FIRST` : retorna todas as entities atingidas, da origem até a distância máxima do ray.
* `collisionMask` : Detecte apenas colisões com certas camadas de colisão. Use isso junto com uma camada de colisão customizada, ou para detectar apenas a layer de physics ou pointer events. Veja [camadas de colisão personalizadas](/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/colliders.md#collision-layers). Por padrão, todas as layers são detectadas.
* `originOffset`: Em vez de iniciar o Raycast a partir da posição de origem da entidade, adicione um offset para iniciar a consulta a partir de uma posição relativa. Por exemplo, você pode usar um pequeno offset para impedir que o raio colida com o próprio modelo 3D da entidade.
* `continuous`: Se true, continuará executando uma consulta de Raycast em cada frame. Se false, o raio será usado apenas no frame atual. Por padrão, esse valor é false.

{% hint style="warning" %}
**📔 Nota** : A `continuous` propriedade deve ser usada com cautela, pois executar uma query de raycast em cada frame pode ser muito custoso para o desempenho. Quando possível, use um system (ou a `interval` função na biblioteca Utils) para executar queries de raycast em intervalos regulares mais espaçados, veja [raycasting recorrente](#recurrent-raycasting).
{% endhint %}

O exemplo a seguir usa uma rotação global para determinar a direção e retorna apenas a primeira entidade atingida no frame em que o raio é enviado.

```typescript
const entity1 = engine.addEntity()

Transform.create(entity1, {
  position: Vector3.create(8, 1, 0)
})

Raycast.createOrReplace(entity1, {
  direction: {
    $case: "globalDirection",
    globalDirection: Vector3.create(0, 0, 1)
  }
  maxDistance: 16,
  queryType: RaycastQueryType.RQT_HIT_FIRST
})
```

O exemplo abaixo lança um raio na direção frontal da entidade, retornando apenas o primeiro item atingido. Ele faz isso continuamente. Também inclui um pequeno offset de 0,5 para impedir que o raio atinja o próprio collider da entidade.

```typescript
const entity1 = engine.addEntity()

Transform.create(entity1, {
  position: Vector3.create(8, 1, 0)
})

Raycast.createOrReplace(entity1, {
  direction: {
    $case: "localDirection",
    localDirection: Vector3.Forward()
  }
  maxDistance: 16,
  queryType: RaycastQueryType.RQT_HIT_FIRST,
  originOffset: Vector3.create(0.5, 0, 0),
  continuous: true
})
```

Este exemplo traça um raio entre duas entidades. Ele retorna todas as entidades atingidas no trajeto.

```ts
const entity1 = engine.addEntity()

Transform.create(entity1, {
  position: Vector3.create(8, 1, 0)
})

const entity2 = engine.addEntity()

Transform.create(entity2, {
  position: Vector3.create(0, 1, 8)
})

Raycast.createOrReplace(entity1, {
  direction: {
    $case: "targetEntity",
    targetEntity: entity2
  }
  maxDistance: 16,
  queryType: RaycastQueryType.RQT_QUERY_ALL
})
```

### Componente de resultados do Raycast

{% hint style="warning" %}
**📔 Nota**: A maneira mais fácil de lidar com os resultados do Raycast é usar `raycastEventSystem`, e registrar uma função de callback como parte da mesma instrução que cria o raio. O`RaycastResult` componente é usado internamente por essa interface, mas também é exposto para permitir uma lógica personalizada mais avançada.
{% endhint %}

Depois de criar um componente Raycast, a entidade à qual esse componente é adicionado terá um `RaycastResult` componente. Esse componente inclui informações sobre quaisquer acertos do raio. Configure um System para verificar esses dados.

O `RaycastResult` componente contém os seguintes dados:

* `globalOrigin` : A posição de onde o ray foi originado, relativa à scene.
* `campo direction espera um` : A direção global para a qual o ray estava apontando, como um `que descreve um vetor relativo à entity e à sua rotação (por exemplo,`.
* `hits` : Um array com um objeto para cada entity que foi atingida. Se não houver entities atingidas, este array fica vazio. Se o raycast usou `RaycastQueryType.RQT_HIT_FIRST`, este array conterá apenas um objeto.

Cada objeto no `hits` array inclui:

* `entityId` : Número de identificação da entity atingida pelo ray.
* `meshName`: *String* com o nome interno da mesh específica no modelo 3D que foi atingida. Isso é útil quando um modelo 3D é composto por múltiplas meshes.
* `position`: *que descreve um vetor relativo à entity e à sua rotação (por exemplo,* para a posição onde o ray intersectou a entity atingida (relativa à scene)
* `length` : Comprimento do ray desde sua origem até a posição onde ocorreu o acerto contra a entity.
* `normalHit`: *Quaternion* para o ângulo da normal do acerto no espaço mundial.
* `globalOrigin`: *que descreve um vetor relativo à entity e à sua rotação (por exemplo,* para a posição onde o ray se origina (relativa à scene)
* `campo direction espera um` : A direção global para a qual o ray estava apontando, como um `que descreve um vetor relativo à entity e à sua rotação (por exemplo,`.

O exemplo abaixo mostra como você pode acessar resultados de uma entidade individual usando um System:

```typescript

const rayEntity = engine.addEntity()

Transform.create(rayEntity, {
  position: Vector3.create(8, 1, 0)
})

// retornar todas as entidades
Raycast.createOrReplace(rayEntity, {
  direction: {
    $case: "globalDirection",
    globalDirection: Vector3.create(0, 0, 1)
  }
  maxDistance: 16,
  queryType: RaycastQueryType.RQT_QUERY_ALL
})

engine.addSystem(() => {
  const rayResult = RaycastResult.get(rayEntity)
  console.log(rayResult.hits)
})
```

O próximo exemplo mostra como você pode acessar `RaycastResult` components de todas as entidades na cena, usando uma [consulta por component](/creator/content-creator-pt/scenes-sdk7/arquitetura/querying-components.md).

```typescript
engine.addSystem(() => {
  for (const [_, result] of engine.getEntitiesWith(RaycastResult)) {
    console.log(result.hits)
  }
})
```

{% hint style="warning" %}
**📔 Nota**: Os resultados de um Raycast não chegam no mesmo tick do loop do jogo em que você criou o Raycast. Os resultados podem levar um ou vários ticks para chegar.
{% endhint %}

Em uma scene em que você usa vários tipos de raios para finalidades diferentes (como para path finding, verificação de line-of-sight, rastreamento de projéteis etc.), talvez você queira usar diferentes [camadas de colisão personalizadas](/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/colliders.md#collision-layers), para evitar calcular colisões irrelevantes.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/interatividade/raycasting.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
