在Unity中使用层和位掩码与Raycast

时间:2017-04-22 13:20:27

标签: c# unity3d raycasting bitmask

Unity的Raycast函数有一个参数可用于光线投射到特定的GameObject。您也可以使用该参数来忽略特定的GameObject。

例如,Raycast功能:

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

layerMask参数用于指定哪些对象应该/不应该接收光线投射。

1 。如何光线投射到名为“立方体”的图层中的特定 GameObject?

2 。如果你在场景中有 10 GameObjects,但你只想光线投射到 2 GameObjects并忽略其余的话?你是怎么做到的?

假设那些对象的图层是“立方体”和“球体”。

3 。如果你想光线投射到所有 GameObjects但忽略1,那该怎么办。

假设要忽略的GameObject位于“立方体”层中。

4 。如果你想光线投射到所有 GameObjects但忽略2个(多个)GameObjects,那该怎么办。

同样,要忽略的图层是“立方体”和“球体”图层。

2 个答案:

答案 0 :(得分:17)

我看到的大多数Raycast个问题都错误地使用了Layermask。虽然它很幸运,但是当他们真正想要从Raycast中排除GameObject时,它们通常会遇到问题。

这个答案是为了涵盖一个人在执行光线投射时想要使用Layer过滤GameObjects的所有场景。

  

1 。您如何光线投射到名为“立方体”的图层中的特定 GameObject?

首先使用LayerMask.NameToLayer("cube")将图层名称转换为图层编号。如果图层不存在,LayerMask.NameToLayer函数将返回-1。您必须在执行任何图层按位操作之前检查此项。

投射到特定图层(仅限“立方体”):

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

    }
}

上述示例中最重要的部分是int layerMask = (1 << cubeLayerIndex);

为了简化这个答案,我不会检查其余答案的错误。

  

2 。如果你在场景中有 10 GameObjects,但你只想光线投射到 2 GameObjects并忽略其余的话?你好吗   是什么?

     

假设那些对象的图层是“立方体”和“球体”。

Raycast到“立方体”和“球体”图层并忽略其余部分:

//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 。如果你想光线投射到所有 GameObjects但忽略1,那该怎么办。

     

假设要忽略的GameObject位于“立方体”层中。

Raycast给所有人但忽略了“立方体”图层:

//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 。如果你想光线投射到所有 GameObjects但忽略2个(多个)GameObjects,那该怎么办。

     

同样,要忽略的图层是“立方体”和“球体”图层。

Raycast向所有人忽略了“立方体”和“球体”图层:

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

OR

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

最后,如果您知道图层索引/编号,则无需使用LayerMask.NameToLayer函数。只需在那里插入那个图层索引。例如,让我们将光线投射到索引#9 的“立方体”图层。你可以int layerMask = (1 << 9);

请参阅Layers手册以了解有关此主题的更多信息。

答案 1 :(得分:1)

要添加到@Programmer的综合答案中...

  

1。。如何将光线投射到位于“多维数据集”图层中的特定GameObject?

如果您想new_str查看是否仅 命中了特定于对象,请调用File.write(fname, new_str) collider.Raycast(。 ..)。

Raycast可以是object或您的object派生脚本(GameObject)。