一尘不染

在Unity中将图层和位掩码与Raycast一起使用

c#

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。 如何将广播到 特定的 游戏对象,该对象位于称为“多维数据集”的图层中?

2。 如果场景中有 10个 游戏对象,但您只想射线投射到 2个 游戏对象,而忽略其余部分该怎么办?你是怎样做的?

假设这些对象的图层是“多维数据集”和“球形”。

3。 如果您想向 所有 GameObjects进行广播,而忽略1。

假设要忽略的GameObject位于“多维数据集”层中。

4。 如果要向 所有 GameObjects进行广播,而忽略2个(多个)GameObjects,该怎么办。

同样,要忽略的层是“多维数据集”和“球形”层。


阅读 564

收藏
2020-05-19

共1个答案

一尘不染

Raycast我看到的大多数问题都使用Layermask不正确。虽然运气对他们有用,但是当他们实际上想从中排除GameObject时,他们通常会遇到问题Raycast

做出此回答的目的是涵盖人们在执行光线投射时想要使用图层来过滤游戏对象的所有那些情况。

1。 如何将广播到 特定的 游戏对象,该对象位于称为“多维数据集”的图层中?

首先,您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个 游戏对象,但您只想射线投射到 2个 游戏对象,而忽略其余部分该怎么办?你是怎样做的?

假设这些对象的图层是“多维数据集”和“球形”。

广播到“多维数据集”和“球形”层,忽略其余部分:

//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位于“多维数据集”层中。

向所有人进行光线广播,但忽略“多维数据集”层:

//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,该怎么办。

同样,要忽略的层是“多维数据集”和“球形”层。

向所有人进行光线广播,但忽略“多维数据集”和“球形”层:

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

要么

//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中
的“多维数据集”层进行raycast广播。你可以做int layerMask = (1 << 9);

请参阅“ 图层”手册以了解有关此主题的更多信息。

2020-05-19