检查光线投射是否命中,是否命中LayerMask中的层



标题称之为

最初我使用的是:

hit.transform.gameObject.layer == LayerMask.NameToLayer("Floor")

但最终我发现不同的地板需要不同的层,我想我应该使用LayerMask,如果我错了,但不能让它发挥作用,请纠正我。

在文件的顶部,我有:

public LayerMask floorLayers;

在空白更新我有:

int floorMask = ~floorLayers.value;

在if语句中,我有:

if (playerHasWetFeet == true && wetSteps < maxWetSteps && controller.isGrounded && hit.transform.gameObject.layer == floorMask)

然而,这不起作用。

有人能指出我做错了什么吗?

编辑:

这在我的更新功能范围内:

int floorMask = ~floorLayers.value;
currentFrameFootstepLeft = anim.GetFloat("FootstepLeft");
if (currentFrameFootstepLeft > 0 && lastFrameFootstepLeft < 0)
{
if (Physics.Raycast(transform.position, dirDown, out hit, 10f, floorMask))
{
if (playerHasWetFeet == true && wetSteps < maxWetSteps && controller.isGrounded && (1 << hit.transform.gameObject.layer & floorMask) != 0)
{
LeftWetStepSpawner();
Debug.Log("Hit");
}

使用此:

if(hit.transform.gameObject.layer == floorMask)

您只是在比较RaycastHit结果中的层命中率。如果这确实是您想要的,并且您只想检查光线投射按层命中的内容,则不要对层执行任何位掩码操作。

删除此

int floorMask = ~floorLayers.value;

获取层索引:

int floor1 = LayerMask.NameToLayer("Floor1");
int floor2 = LayerMask.NameToLayer("Floor2");
int floor3 = LayerMask.NameToLayer("Floor2");

然后直接比较图层索引:

if (hit.transform.gameObject.layer == floor1)
{
}
if (hit.transform.gameObject.layer == floor2)
{
}
if (hit.transform.gameObject.layer == floor3)
{
}

虽然这应该可以解决您的问题,但使用图层掩码的主要原因是过滤光线投射。当使用layermask时,您可以使用它来决定光线投射应该命中或忽略哪些对象,如果这是您真正想要做的,请不要像在代码中那样比较层。只需找到遮罩,然后将遮罩传递给光线投射函数。我不确定这是否是您想要做的,但这两个例子都应该让您了解图层遮罩的用途。

例如,您希望只对"地板"层上的对象进行光线投射,而不希望光线投射击中另一层上的任何其他对象:

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

你可以在这篇文章中找到许多其他的例子。

由于您希望光线投射忽略任何不是地板的东西,因此可以在光线投射中使用遮罩,使其只触及地板。要做到这一点,您需要有您的LayerMask floorLayers,以便只检查楼层,然后在Raycast:中

Physics.Raycast(transform.position, dirDown, out hit, 10f, ~floorLayers.value)

如果你这样做,任何命中都将是地板命中,你不需要做下面的任何数学运算。

如果您后来决定不能使用相同的遮罩进行光线投射(也许您真的需要光线投射能够与许多可能的目标碰撞,然后如果击中的对象恰好是地板,请参见(,请阅读以下内容。


首先,您想要比较一个掩码值,该值的位仅针对楼层设置为true,它似乎是floorLayers.value

如果要将GameObject.layerLayerMask.value进行比较,首先需要按GameObject.layer移位一位。

此外,如果您想检查gameObject.layerfloorMask之间是否至少有一个匹配,您需要使用二进制and(&(并查看它是否不是0(!= 0是不必要的,但它有助于提高可读性(:

... && (1 << hit.transform.gameObject.layer & floorLayers.value) != 0

这是因为GameObject.layer是该单层的索引,但FloorMask.value是基于各种位的真/假值的位掩码。直接比较它们是没有意义的,而不首先进行转换。

最新更新