Is it possible to allow a raycast to pass through a collider to hit things behind it?

I have a scenario in which sometimes there’s an invisible collider in front of objects that need to be clicked on. It is necessary that this invisible object has a collider. However even using a layermask the invisible object still blocks rays. The layer mask simply stops it from returning true for a collision.

It is not an option to turn on and off the collider of the invisible object at appropriate times as 1 or more objects respond to an OnTriggerExit with the invisible object.

What I need to know is, can I make a ray pass through a collider ignoring it completely until it either hits an intended collider or hits max distance?

Any help is much appreciated : ]

I just ran a quick check – rayCasting through a custom layer (one you create) works just fine. Made four cubes lined up on z, added custom layers 8 and 9 (skip and skip2, but the names don’t matter,) lined them up on z and added a raycast script to the start cube:

Cubes:    start->   wall1    wall2     target
Layer:    default  skip(8)  skip2(9)   default

if(Input.GetKey("space")) {
  RaycastHit H;

  // goes through wall1 (layer 8,) hits wall2:
  if(Physics.Raycast(transform.position, transform.forward, out H, 100, ~1<<8))
  Debug.Log(H.transform.name);

  // goes through both walls (layer 8 and 9) and hits target:
  int skip1n2 = ~((1<<8)|(1<<9));
  if(Physics.Raycast(transform.position, transform.forward, out H, 100, skip1n2))
  Debug.Log(H.transform.name);

  // The previous hits ignoreRaycast. This skips 8,9 and ignoreRC(layer 2):
  int skip = ~((1<<8)|(1<<9)|(1<<2));
  if(Physics.Raycast(transform.position, transform.forward, out H, 100, skip))
}

http://unity3d.com/support/documentation/Components/Layers.html has the official example.

I can think of a few solutions for this problem:

1- Disable the “forbidden” object’s collider, do the raycast and enable the collider. If you do this in the same function, nobody else will be affected. This may be a solution when you have only one forbidden object, but can be awkward if there are several of them.

2- Use RaycastAll: it returns an array with all hits, and you can ignore the forbidden objects until you find a valid one. This is more time expensive, specially if the raycast is infinite or too long:

var hit: RaycastHit; // the hit info (if any) will be returned here
var nonoTag: String; // define the forbidden tag here

// specify the ray and the max distance 
function XRaycast(ray: Ray, dist: float): boolean {
    var hits = Physics.RaycastAll(ray, dist); // get all hits
    for (hit in hits){ // check hits until a valid one is found
        if (hit.collider.tag != nonoTag) return true;
    }
    // if no valid hit found, return false
    return false;
}

3- Do a Raycast and check the object hit: if it’s a forbidden one, change the origin to the hit.point plus a little offset in the ray.direction, and repeat the process. This can be done recursively until a valid object is found or the ray hits nothing.

The function below can do this: it does successive Raycasts while finding forbidden objects. If some valid object is found, it returns true; if there are no valid objects, returns false.

var hit: RaycastHit; // the hit info (if any) will be returned here
var nonoTag: String; // define the forbidden tag here

// specify the ray and the max distance 
static function XRaycast(ray: Ray, dist: float): boolean {
    if (!Physics.Raycast(ray, hit, dist)) return false; // return false if nothing found
    if (hit.collider.tag != nonoTag) return true; // return true if valid obj found
    var end = ray.GetPoint(dist);             // if invalid object hit, set a new
    ray.origin = hit.point+0.1*ray.direction; // ray origin 0.1 ahead of the hit.point
    dist = Vector3.Distance(end, ray.origin); // update the max distance...
    return XRaycast(ray, dist);               // and call itself
}

Yeah sure just give it a layerMask

Something like this

        if (Physics.Raycast(ray, out hit, Mathf.Infinity, myLayerMask))

HI,

I struggled with this for a long time. And I finally found how to do it so it works every time. but first for your solution you can set the layer of the object to be ignored to “IgnoreRaycast”, however, you do not always want this. So here is the correct way

// Create Ray
Ray ray = new Ray( transform.position, transform.forward);

// Hit info
RaycastHit hit;

// Layer to hit / Layer to ignore
string nameOfLayer = "InvisObjectLayer";

/**
* Note that we use ` ~ ` sign if we want the opposite. 
* So we want all the layers accept that particular one. 
* If we only want to cast to one layer just remove the ` ~ ` sign
*/
LayerMask layer =  ~(1 << LayerMask.NameToLayer(nameOfLayer )); 

// Do the raycast - Use if Statement to automatically check if there was a hit

/** IMPORTANT
*  We must use the Mathf.Infinty statement. Unity does not have a
* function that accepts only a ray, hitInfo and layer!
*/
if (Physics.Raycast (ray, out hit, Mathf.infinity, layer)) {
     if (hit.transform.tag == "Player")...
}

Another solution is to raycasts from initial raycast collistion spot.

Hi! I’m fighting with the same problem. Anyone found a solution yet?

For C-Sharp:

Ray ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width/2,Screen.height/2,0));

RaycastHit hit;

int layerMask = 1 << 4;//setting the layer mask to layer 4 (water in my case)

layerMask = ~layerMask;//setting the layer mask to “ignore” layer (~)

if (Physics.Raycast(ray, out hit, maxInteractionRange, layerMask))//adding in the layer mask to the raycast and it WILL ignore the 4th layer!

{

//your code here…
}