在 Unity 中将图层和位掩码与 Raycast 结合使用 [英] Using Layers and Bitmask with Raycast in Unity

查看:40
本文介绍了在 Unity 中将图层和位掩码与 Raycast 结合使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Unity 的 Raycast 函数有一个参数,您可以使用它来将光线投射到特定的 GameObject.您还可以使用该参数来忽略特定的游戏对象.

以光线投射函数为例:

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

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

<小时>

1.如何将光线投射到位于名为cube"的层中的特定 GameObject?

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

假设那些对象的层是立方体"和球体".

3.如果您想将光线投射到所有游戏对象但忽略 1,该怎么办.

假设要忽略的游戏对象位于立方体"层.

4.如果您想将光线投射到所有游戏对象但忽略 2 个(多个)游戏对象,该怎么办.

同样,要忽略的层是立方体"和球体"层.

解决方案

我看到的大多数 Raycast 问题都错误地使用了 Layermask.虽然这对他们来说很幸运,但当他们真的想从 Raycast 中排除游戏对象时,他们通常会遇到问题.

这个答案是为了涵盖一个人在执行光线投射时想要使用层来过滤游戏对象的所有场景.

<块引用>

1.如何将光线投射到位于名为cube"的层中的特定 GameObject?

首先使用 LayerMask.NameToLayer("cube") 将图层名称转换为图层编号.LayerMask.NameToLayer 函数返回 -1 如果图层不存在.在进行任何图层按位运算之前,您必须检查这一点.

光线投射到特定层(仅限立方体"):

//将图层名称转换为图层编号int cubeLayerIndex = LayerMask.NameToLayer("cube");//检查图层是否有效if (cubeLayerIndex == -1){Debug.LogError("图层不存在");}别的{//计算layermask to Raycast to.(仅限 Raycast 到立方体"层)int layerMask = (1 <

上面例子中最重要的部分是int layerMask = (1 <.

为了使这个答案简短,我不会检查其余答案的错误.

<小时><块引用>

2.如果您在场景中有 10 个游戏对象,但您只想将光线投射到 2 个游戏对象而忽略其余游戏对象,该怎么办?你好吗那个?

假设那些对象的层是立方体"和球体".

光线投射到立方体"和球体"层而忽略其余的:

//将图层名称转换为图层编号int cubeLayerIndex = LayerMask.NameToLayer("cube");int sphereLayerIndex = LayerMask.NameToLayer("sphere");//计算layermask to Raycast to.(仅限于立方体"和球体"层的光线投射)int layerMask = (1 <

<小时><块引用>

3.如果您想将光线投射到所有游戏对象但忽略 1,该怎么办.

假设要忽略的游戏对象位于立方体"层.

光线投射到所有但忽略立方体"层:

//将图层名称转换为图层编号int cubeLayerIndex = LayerMask.NameToLayer("cube");//计算layermask to Raycast to.(忽略立方体"层)int layerMask = (1 <

<小时><块引用>

4.如果您想将光线投射到所有游戏对象但忽略 2 个(多个)游戏对象,该怎么办.

同样,要忽略的层是立方体"和球体"层.

光线投射到所有但忽略立方体"和球体"层:

//将图层名称转换为图层编号int cubeLayerIndex = LayerMask.NameToLayer("cube");int sphereLayerIndex = LayerMask.NameToLayer("sphere");//计算layermask to Raycast to.(忽略立方体"和球体"层)int layerMask = ~((1 <

OR

//将图层名称转换为图层编号int cubeLayerIndex = LayerMask.NameToLayer("cube");int sphereLayerIndex = LayerMask.NameToLayer("sphere");//计算layermask to Raycast to.(忽略立方体"和球体"层)int layerMask = (1 <

<小时>

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

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

Unity's Raycast functions has a parameter you could use to raycast to a particular GameObject. You can also use that parameter to ignore particular GameObject.

For exmple the Raycast function:

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

The layerMask parameter is used to specified which Objects should/should not receive the raycast.


1.How do you raycast to a particular GameObject which is in a layer called "cube"?

2.What if you have 10 GameObjects in the scene but you only want to raycast to just 2 GameObjects and ignore the rest? How do you do that?

Let's say that those Object's layers are "cube" and "sphere".

3.What if you want to raycast to all GameObjects but ignore 1.

Let's say that the GameObject to ignore is in the "cube" layer.

4.What if you want to raycast to all GameObjects but ignore 2(multiple) GameObjects.

Again, the layers to ignore are the "cube" and "sphere" layers.

解决方案

Most Raycast questions I see use the Layermask incorrectly. Although it works for them by luck but they usually run into issues when they actually want to exclude a GameObject from Raycast.

This answer is made to cover all those scenarios that a person would want to use the Layer to filter GameObjects when performing raycast.

1.How do you raycast to a particular GameObject which is in a layer called "cube"?

First you use LayerMask.NameToLayer("cube") to convert the layer name to layer number. The LayerMask.NameToLayer function returns -1 if the layer does not exist. You must check this before doing any layer bitwise operation.

Raycast to a particular layer ("cube" only):

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

    }
}

The most important part of the example above is int layerMask = (1 << cubeLayerIndex);.

To make this answer short, I won't be checking for errors for the rest of the answer.


2.What if you have 10 GameObjects in the scene but you only want to raycast to just 2 GameObjects and ignore the rest? How do you do that?

Let's say that those Object's layers are "cube" and "sphere".

Raycast to the "cube" and "sphere" layers and ignore the rest:

//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.What if you want to raycast to all GameObjects but ignore 1.

Let's say that the GameObject to ignore is in the "cube" layer.

Raycast to all but ignore the "cube" layer:

//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.What if you want to raycast to all GameObjects but ignore 2(multiple) GameObjects.

Again, the layers to ignore are the "cube" and "sphere" layers.

Raycast to all but ignore the "cube" and "sphere" layers:

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


Finally, if you know the layer index/number, there is no need to use the LayerMask.NameToLayer function. Just insert that layer index there. For example, let's raycast to the "cube" layer which is in index #9. You could just do int layerMask = (1 << 9);.

See the Layers manual to read more about this subjct.

这篇关于在 Unity 中将图层和位掩码与 Raycast 结合使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆