- Home /
Layer Mask Detection
I have a two spesific layer mask. When I click the blocks if the block has destructable mask i am firing a rocket but in second section when i click to block that has core mask Unity still returning 0 and firing rockets.
Where I did wrong I define the rays for specific layers but it gives the same results only returnin 0 when I click the any block ?
Thanks In Advance !
if( Physics.Raycast(out var hit) )
if( hit.collider )
This if( hit.collider )
is redundant as Physics.Raycast()==true
guarantees a collider been hit.
Answer by Pangamini · May 14, 2021 at 10:37 AM
Mask filtering means that the raycast will pass through colliders that don't match your mask. This means, that if there's an object that matches destructableMask behind the object that matches the coreMask, you will always hit the destructibleMask object in the first raycast. I am just guessing what you are trying to do. But most likely, a better solution would be to have a single raycast, whose mask matches everything you want to hit potentially, then determine what kind of object you've clicked. Also paste your code as text, not as a screenshot, it makes it easier for people to copy and modify it.
if(Physics.Raycast(ray, out hit, mergedMask))
{
int objectLayer = hit.collider.gameObject.layer;
if (1<<objectLayer & destructableMask)
return 0;
// ...........etc
}
If something goes wrong in the future, you can be sure that I will paste the code :)
Thanks a lot !
+1
Also, to better understand what is happening here I suggest you add these debug lines there:
if( Physics.Raycast( ray , out var hit , mask ) )
{
Debug.Log( $"mask 1, collider hit: {hit.collider.name}" , hit.collider.gameObject );
Debug.DrawLine( ray.origin , ray.origin+ray.direction*hit.distance );
}
It will draw it as a ray in scene view and also clicking on these console logs should select a gameObjects that was hit.
That's why I have to write shorter, more compact answers. I know that you are out there somewhere answering at the same time :D
Answer by Bunny83 · May 14, 2021 at 10:49 AM
Well, I think you have the wrong idea about the layermask. The layermask does not only filter the results of the raycast, but also only casts against those objects. So your ray becomes an "x-ray" for all objects that do not match the layermask. So for example, if your player object is in a layer player and you cast a ray just against the player layer, you can still hit the player even if there's some other geometry in between. Only things that are included in the layermask will participate in the raycast-
That means if you want the raycast to be "blockable" by default geometry, you have to include the default layer as well, otherwise they will be ignored. The layermask is not for filtering the endresult.
Now it depends on what you want to achieve. In most raycast scenarios you usually want to include blocking geometry. So you have to include all layers that should participate in the raycast. That means you essentially need one layermask and only one raycast. Of course in order to determine what was hit, you have to analyse the hit object. The gameObject of the collider has a layer property which you can use to further filter your results. For this you can use your two layermasks. So the code would look something like this:
if (Physics.Raycast(ray, out hit, allRelevantLayers))
{
int goLayerMask = 1 << hit.collider.gameObject.layer;
if ((goLayerMask & destructableBlocks.value) != 0)
{
return 0;
}
if ((goLayerMask & coreMask.value) != 0)
{
return 1;
}
}
return 0;
Note I've simplified the code since you did not post the code as code so we can't copy it for the answer. However the overall idea here is that "allRelevantLayers" is a layermask that contains all layers that you want to be able to "hit". So the layers you're interested in as well as blocking geometry (usually the default layer). You could create that layermask by combining your two layermask and add the blocking geometry layers as well by doing
int allRelevantLayers = destructableBlocks.value | coreMask.value | blockingLayers.value;
Now our raycast will only consider those layers. When we hit "something" from those layers, we determine what we hit based on your two layermasks.
Note I would highly recommend that you avoid magic numbers like 0, 1 and 2. If you want to communicate a certain outcome, use an enum and give the 3 cases meaningful names.
Really thank you for explaining in great detail!
At the same time, as you said enum logic, the more useful the project grows, the harder it is to understand the integer values: D
Good answer !
Your answer
Follow this Question
Related Questions
Ignore one layermask question 1 Answer
Help Can't find the Correct Parameters 1 Answer
Help with Layermasks 1 Answer
Raycast works perfectly, but only in editor 0 Answers
Boxcast vs Raycast Oddities 1 Answer