- Home /
Raycast Limiting and Layers
I have a scene with several objects called panels. A raycast from the camera determines if the camera is 'looking' at a panel or not. There may be, at times, objects between the camera and the panels. So I have a raycast filter for only the 'Panels'. There is a plane between the camera and the panels which is in layer 'Ground' (9), all of the panels are in layer 'Panels' (10).
If I remove the plane, the code executes perfectly. If the plane is present between the camera and the panels, the raycast suddenly doesn't hit or doesn't register hitting the panels. A debug draw line goes through both the panels and the plane.
What do I need to do to get the raycast to ignore the plane, but register the panel objects?
public LayerMask blockLayers;
void Awake() {
blockLayers = LayerMask.GetMask("Panels");
}
void Update() {
Camera camera;
camera = oCam.GetComponent<Camera>();
RaycastHit hit;
Ray ray = camera.ScreenPointToRay(new Vector3((camera.pixelWidth / 2), (camera.pixelHeight / 2), 0));
Debug.DrawRay(ray.origin, ray.direction * 10, Color.red);
if (Physics.Raycast(ray, out hit, blockLayers))
{
if (hit.collider != null && hit.collider.gameObject.layer == 10)
{
hPanel(hit.collider.gameObject);
}
}
}
ins$$anonymous$$d of your layermask plz try an integer:
int mask = 1 << 10
So I've tried this solution, and unfortunately am hitting the same problem, namely that an object in layer 9 is preventing the raycast from hitting objects behind it which are in layer 10. If I remove the 2D plane, this solution works equally as well.
i posted an answer some time ago, but it seems moderators are busy, i dont want to let you wait for it: blocklayers is interpreted as float, and as maximum range.
Answer by TdragonR1386 · Dec 15, 2015 at 08:56 AM
As @Soraphis points out, the method I had of utilizing physics.raycast was incorrect. blockLayers was being interpreted as an int for the distance of the raycast and not the layermask. I have re-written the line as follows using identifying practices provided by @wibble82, and it appears to work as needed:
if (Physics.Raycast(ray, out hit, 10f, blockLayers))
{
Debug.Log(hit.collider.name + " was hit.");
if (hit.collider != null && hit.collider.gameObject.layer == LayerMask.NameToLayer("Panels"))
{
hPanel(hit.collider.gameObject);
}
}
Moral of the story: Verify method overloads
Answer by wibble82 · Dec 14, 2015 at 02:18 PM
Hi there.
I think your ray cast filtering is correct - you've used the layer mask system exactly how you should, so presuming you're correct about what is in what layer, most of the code is correct. However on Line 15, you're simply checking the layer index - that seems a bit suspicious to me, and you should never be referencing layers purely by integer, as it can change depending on scene and stuff. Instead try this:
if (hit.collider != null && hit.collider.gameObject.layer == LayerMask.NameToLayer("Panels"))
If that doesn't work, try using Debug.Log to print out what is actually being found. i.e. inside the if statement:
Debug.Log(out.hit.collider.name)
-Chris
tell me how can the layers change from scene to scene if they are per Project. You'll have them at one point Hardcoded. either as string, where typos are possible or as integer where you have to remember the name.
I for my self have bad expierience with layermask i dont remember correctly but i think there was some (for me) unexpected behaviour, thats why i mention testing it with an integer - just testing.
So that didn't seem to change anything, but I get what you're saying in that it's less prone to being interfered with should I change something later.
The debug line didn't report hitting anything when put within the second if statement. If I place it in the first one, but outside the second if, it says the 2D plane is being 'hit'. So despite being in a different layer, it is preventing the raycast from moving forward and hitting the panels behind it.
The debug ray is moving through both objects, however.
Answer by Soraphis · Dec 15, 2015 at 08:53 AM
if (Physics.Raycast(ray, out hit, blockLayers))
blockLayers is interpreted as float (because the implicit casting from int to float) for maximum range. for a layermask 1 << 10, your ray will return the first object hit in a 1024 distance, with the default layermask. So you'll hit the first object which is the plane.
You got the method signature wrong. Use either: Raycast(Ray, out hit, float range, int layermask)
or
Raycast(Ray, float range, int layermask)