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

Unity的Raycastfunction有一个参数可以用来对特定的GameObject进行光线投射。 您也可以使用该参数来忽略特定的GameObject。

例如Raycastfunction:

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

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


1 ,你如何对一个名为“cube”的图层进行光线投射?

2,如果你在场景中有10个 GameObjects,但是你只想对2个 GameObjects进行光线投射而忽略其余部分? 你如何做到这一点?

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

3,如果你想对所有 GameObjects进行光线投射,但忽略1。

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

4,如果您想对所有 GameObjects进行光线投射,但忽略2(多个)GameObjects。

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

我看到的大多数Raycast问题Layermask错误地使用了Layermask 。 虽然它运气好,但他们通常遇到的问题,当他们真的想从Raycast排除游戏对象。

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

1 ,你如何对一个名为“cube”的图层进行光线投射?

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

Raycast到特定图层(仅“立方体”):

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

要么

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

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