首页 > 解决方案 > Unity 的 Pyshics.RaycastAll 层参数有问题

问题描述

如果我使用 layer 参数,这个光线投射总是返回一个空数组,但如果我不使用它,一切都会正常工作。我想为我的敌人(触发对撞机)制作一个分离层,以优化流程。

private RaycastHit[] GetRaycastHits(int layer = 0)
{
    return Physics.RaycastAll(partToRotate.position, partToRotate.forward, ShootRangeDistance, layer);
}

很奇怪,即使通过 LayerMask.NameToLayer("Default") 它也不起作用。我确保我的敌人现在在默认层上,并且我已经尝试传递允许施法击中触发器的参数。

标签: unity3d

解决方案


您使用的图层蒙版错误!

查看图层

Physics.Raycast 函数采用位掩码,其中每个位确定是否将忽略图层。如果 layerMask 中的所有位都打开,我们将与所有碰撞器发生碰撞。如果 layerMask = 0,我们将永远不会发现任何与射线的碰撞。

进一步了解位掩码

位掩码的工作原理基本上如下:

每个(在这种情况下)层由一个启用(1)或禁用(0)“位”表示。

请记住,int二进制后端中的一个基本上只有 4 个字节 => 32 位 => Unity 中的 32 个可用层。

假设现在只有 8 层作为示例。

所以位掩码看起来像

0000 0001

现在我将在其上添加索引,以便您了解我在说什么

//indices 7654 3210
          0000 0001

这意味着索引处的图层0已启用,其他任何内容均已禁用。这将具有int1(= 2^0)

第二个例子

// indices 7654 3210
           0000 1010

这意味着索引处的图层13已启用,int值为10. **为什么?因为它等于

0*2^7 + 0*2^6 + 0*2^5 + 0*2^4 + 1*2^3 + 0*2^2 + 1*2^1 + 0*2^0

= 0 + 0 + 0 + 0 + 8 + 0 + 2 + 0

= 10

为了更容易编写,您通常会使用位移操作,例如

var layers = 1<<3 | 1<<1;
// In bits   1000   10

这将导致最后一个掩码示例。


所以该Default层实际上是

int defaultLayer = 1<<0;

这不等于0,而是1


为了不必进行图层计算或通过字符串对其进行硬编码,您应该使用 LayerMask类似的字段

public LayerMask raycastLayers;

在您的组件中,通过 Inspector 对其进行配置,然后将其传递给

// This is possible because LayerMask has an implicit conversion from int to LayerMask
//                                                       |
//                                                       v
private RaycastHit[] GetRaycastHits(LayerMask hitLayers = 1<<0)
{
    return Physics.RaycastAll(partToRotate.position, partToRotate.forward, ShootRangeDistance, hitLayers.value);
}

var hits = GetRaycastHits(raycastLayers);

推荐阅读