Usando Camadas e Bitmask com Raycast no Unity

As funções do Raycast da Unity têm um parâmetro que você pode usar para transmitir um determinado GameObject. Você também pode usar esse parâmetro para ignorar GameObject específico.

Por exemplo, a function Raycast:

public static bool Raycast(Vector3 origin, Vector3 direction, float maxDistance = Mathf.Infinity, int layerMask = DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.UseGlobal); 

O parâmetro layerMask é usado para especificar quais Objetos devem / não devem receber o raycast.


1. Como você raycast para um determinado GameObject que está em uma camada chamada “cubo”?

2. E se você tem 10 GameObjects na cena mas você só quer raycast para apenas 2 GameObjects e ignorar o resto? Como você faz isso?

Digamos que as camadas desses objects sejam “cubo” e “esfera”.

3. E se você quiser raycast para todos os GameObjects, mas ignorar 1.

Digamos que o GameObject a ser ignorado esteja na camada “cubo”.

4. E se você quiser raycast para todos os GameObjects mas ignorar 2 (vários) GameObjects.

Novamente, as camadas a serem ignoradas são as camadas “cubo” e “esfera”.

A maioria Raycast perguntas do Raycast que vejo usam a Layermask incorretamente. Embora funcione para eles por sorte, mas eles geralmente se deparam com problemas quando eles realmente querem excluir um Raycast da Raycast .

Essa resposta é feita para cobrir todos os cenários em que uma pessoa gostaria de usar a Camada para filtrar GameObjects ao executar o raycast.

1. Como você raycast para um determinado GameObject que está em uma camada chamada “cubo”?

Primeiro você usa LayerMask.NameToLayer("cube") para converter o nome da camada para o número da camada. A function LayerMask.NameToLayer retorna -1 se a camada não existir. Você deve verificar isso antes de fazer qualquer operação bit a bit de camada.

Raycast para uma camada específica (“cubo” apenas):

 //Convert Layer Name to Layer Number int cubeLayerIndex = LayerMask.NameToLayer("cube"); //Check if layer is valid if (cubeLayerIndex == -1) { Debug.LogError("Layer Does not exist"); } else { //Calculate layermask to Raycast to. (Raycast to "cube" layer only) int layerMask = (1 << cubeLayerIndex); Vector3 fwd = transform.TransformDirection(Vector3.forward); //Raycast with that layer mask if (Physics.Raycast(transform.position, fwd, 10, layerMask)) { } } 

A parte mais importante do exemplo acima é int layerMask = (1 << cubeLayerIndex); .

Para tornar essa resposta curta, não verificarei erros no restante da resposta.


2. E se você tem 10 GameObjects na cena mas você só quer raycast para apenas 2 GameObjects e ignorar o resto? Como você faz isso?

Digamos que as camadas desses objects sejam "cubo" e "esfera".

Raycast para as camadas "cubo" e "esfera" e ignorar o resto:

 //Convert Layer Name to Layer Number int cubeLayerIndex = LayerMask.NameToLayer("cube"); int sphereLayerIndex = LayerMask.NameToLayer("sphere"); //Calculate layermask to Raycast to. (Raycast to "cube" && "sphere" layers only) int layerMask = (1 << cubeLayerIndex) | (1 << sphereLayerIndex); 

3. E se você quiser raycast para todos os GameObjects, mas ignorar 1.

Digamos que o GameObject a ser ignorado esteja na camada "cubo".

Raycast para todos, mas ignorar a camada "cubo":

 //Convert Layer Name to Layer Number int cubeLayerIndex = LayerMask.NameToLayer("cube"); //Calculate layermask to Raycast to. (Ignore "cube" layer) int layerMask = (1 << cubeLayerIndex); //Invert to ignore it layerMask = ~layerMask; 

4. E se você quiser raycast para todos os GameObjects mas ignorar 2 (vários) GameObjects.

Novamente, as camadas a serem ignoradas são as camadas "cubo" e "esfera".

Raycast para todos, mas ignorar as camadas "cubo" e "esfera":

 //Convert Layer Name to Layer Number int cubeLayerIndex = LayerMask.NameToLayer("cube"); int sphereLayerIndex = LayerMask.NameToLayer("sphere"); //Calculate layermask to Raycast to. (Ignore "cube" && "sphere" layers) int layerMask = ~((1 << cubeLayerIndex) | (1 << sphereLayerIndex)); 

OU

 //Convert Layer Name to Layer Number int cubeLayerIndex = LayerMask.NameToLayer("cube"); int sphereLayerIndex = LayerMask.NameToLayer("sphere"); //Calculate layermask to Raycast to. (Ignore "cube" && "sphere" layers) int layerMask = (1 << cubeLayerIndex); layerMask |= (1 << sphereLayerIndex); layerMask |= (1 << otherLayerToIgnore1); layerMask |= (1 << otherLayerToIgnore2); layerMask |= (1 << otherLayerToIgnore3); //Invert to ignore it layerMask = ~layerMask; 

Finalmente, se você conhece o índice / número da camada, não há necessidade de usar a function LayerMask.NameToLayer . Apenas insira o índice dessa camada lá. Por exemplo, vamos raycast para a camada "cubo" que está no índice # 9 . Você poderia fazer int layerMask = (1 << 9); .

Veja o manual Layers para ler mais sobre este subjct.

Para adicionar à resposta abrangente do @Programador …

1. Como você raycast para um determinado GameObject que está em uma camada chamada “cubo”?

Se você quiser Raycast para ver se você acertar apenas um object específico , chamar object . collider.Raycast (…).

object pode ser o GameObject ou seu script derivado de MonoBehaviour ( this ).