Help With Ignoring Collider With Raycast!?

Hello,

I am using the FPS tutorial from Unity. I am using the machine gun script and I want to ignore a specific collider (Element 7 tag - want to ignore).

Here is the machine gun script, I've added the layerMask, but its still not ignoring the 7th tag which is on the collider I want to ignore?!? Any ideas?

function FireOneShot () {
    var direction = transform.TransformDirection(Vector3.forward);
    var hit : RaycastHit;
    var localOffset = transform.position + transform.up * 2;
    var layerMask = 1 << 7;
    layerMask = ~layerMask;

    // Did we hit anything?
    //transform.position + transform.up * 10
    if (Physics.Raycast (localOffset, direction, hit, range, layerMask) && MachineGun == true) {
         Debug.DrawLine (localOffset, hit.point, Color.yellow);
        // Apply a force to the rigidbody we hit
        if (hit.rigidbody)
            hit.rigidbody.AddForceAtPosition(force * direction, hit.point);

        // Place the particle system for spawing out of place where we hit the surface!
        // And spawn a couple of particles
        if (hitParticles) {
            hitParticles.transform.position = hit.point;
            hitParticles.transform.rotation = Quaternion.FromToRotation(Vector3.up, hit.normal);
            hitParticles.Emit();
        }

        // Send a damage message to the hit object          
        hit.collider.SendMessageUpwards("ApplyDamage", damage, SendMessageOptions.DontRequireReceiver);
    }

    bulletsLeft--;

    // Register that we shot this frame,
    // so that the LateUpdate function enabled the muzzleflash renderer for one frame
    m_LastFrameShot = Time.frameCount;
    enabled = true;

    // Reload gun in reload Time        
    if (bulletsLeft == 0)
        Reload();           
}

I recently had this problem. It was a pain to figure out, yet it is a simple fix.

I found that if you go to Edit → Project Settings → Physics2d and Uncheck the box that says “Raycasts Start In Colliders” it solves this issue.

This makes it so that you do not have to deal with layers (I find layers to be a very impractical way of selectively raycasting). It just ignores the collider on the gameobject casting the ray, so you can have multiple prefabs of players/enemies casting rays and hitting each other, but not themselves.

Just put the collider you'd like to ignore on the "IgnoreRaycast" layer.

If you want power over raycasting different layers you can selectively choose which layers are affected by the raycast. If you are only wanting to exclude one object then move that object to the ignore raycast layer such as the bottom of this post. Sometimes this may or may not work so knowing the proper technique WILL come in handy eventually.

link text

Casting Rays Selectively Using layers you can cast rays and ignore colliders in specific layers. For example you might want to cast a ray only against the player layer and ignore all other colliders.

The Physics.Raycast function takes a bitmask, where each bit determines if a layer will be ignored or not. If all bits in the layerMask are on, we will collide against all colliders. If the layerMask = 0, we will never find any collisions with the ray.

// bit shift the index of the layer to get a bit mask var layerMask = 1 << 8; // Does the ray intersect any objects which are in the player layer. if (Physics.Raycast (transform.position, Vector3.forward, Mathf.Infinity, layerMask)) print ("The ray hit the player"); In the real world you want to do the inverse of that however. We want to cast a ray against all colliders except those in the Player layer.

function Update () { // Bit shift the index of the layer (8) to get a bit mask var layerMask = 1 << 8; // This would cast rays only against colliders in layer 8. // But instead we want to collide against everything except layer 8. The ~ operator does this, it inverts a bitmask. layerMask = ~layerMask;

var hit : RaycastHit; // Does the ray intersect any objects excluding the player layer if (Physics.Raycast (transform.position, transform.TransformDirection (Vector3.forward), hit, Mathf.Infinity, layerMask)) { Debug.DrawRay (transform.position, transform.TransformDirection (Vector3.forward) * hit.distance, Color.yellow); print ("Did Hit"); } else { Debug.DrawRay (transform.position, transform.TransformDirection (Vector3.forward) *1000, Color.white); print ("Did not Hit"); } } strong text When you don't pass a layerMask to the Raycast function, it will only ignore colliders that use the IgnoreRaycast layer. This is the easiest way to ignore some colliders when casting a ray.

I hope this helps someone. Here’s my code to detect if the enemy can see the player (C#). Here’s the settings - where the test object is the GameObject I’m looking for, and the Mask Layers String is an array of layers I want to ignore. If you want to add more layers to ignore increase the size of the array (i.e. to add another change 1 to 2 and there will be a space to add the name of another layer you want to ignore)

25464-checkviz_settings.jpg

Make sure you add another C# script called LayerMaskExtensions to your found here too…
link text
using UnityEngine;
using System.Collections;

public class CheckViz : MonoBehaviour {

	public GameObject testObject;
	public string[] maskLayersString;

	LayerMask maskLayer; 
	// Use this for initialization
	void Start () {
		maskLayer = LayerMaskExtensions.Create("Ignore Raycast");
		foreach(string mask in maskLayersString)
		{
			maskLayer = maskLayer.AddToMask(mask);
		}
		Debug.Log(maskLayer.MaskToString());
		maskLayer = maskLayer.Inverse();
		Debug.Log(maskLayer.MaskToString());
	}
	
	// Update is called once per frame
	void Update () {
		// cast a ray to player
		// does the ray hit them first?
		Vector3 direction = testObject.transform.position - transform.position;
		RaycastHit2D hitInfo = Physics2D.Raycast(transform.position,direction,100,maskLayer);
		if(hitInfo.collider.gameObject == testObject)
		{
			Debug.Log( "I can see you!!!!" );
		}
		
	}
	void OnGUI()
	{
		Debug.DrawLine(transform.position, testObject.transform.position);
	}
}

Short:

Raycast only 1 kind of object and ignore all others:
Setup a new Layer e.g. User Layer 8.

//Only raycast for layer 8
LayerMask layerMask = 1 << 8;

RayCast hit;

//transform.position - the world koords where the raycast starts
//transform.TransformDirection - the direction where the raycast should goto
// out hit - the hit object
// 2f - a float value equals the length of the raycast
// layerMask - the layerMask, here ignoring all layers but 8

Physics.Raycast(transform.position, transform.TransformDirection(Vector3.right), out hit, 2f,layerMask)

if you want to ignore only layer 8, it’s the same code
use

LayerMask = ~1 << 8

instead

I know this thread is a bit old, but it seems to be a common issue so thought I’d throw in my $0.05 cent solution.

  • This solution works best with capsule or sphere colliders at the origin point.
  • This solution does not use layers (layers are clunky but also it’s often not practical to change them at run time because other processes need to use them).

The trick I use is to simply start my cast a short distance from the origin. The function below handles that for us;

///<summary>
/// Returns a vector at a location between two points at a given distance from source.
///</summary>    
public static Vector3 Get3DPointBetweenVectors(Vector3 _Source, Vector3 _Target, float _DistanceFromSource)
{
     Vector3 P = _DistanceFromSource * Vector3.Normalize(_Target - _Source) + _Source;
     return P;
}

For the cast, use LineCast, not RayCast. It’s the better option for detecting collisions between two objects.

RaycastHit hit;
Vector3 StartPoint = Util.Get3DPointBetweenVectors(SourceObj.transform.position, DestObj.transform.position, (1.1f));
    
if (Physics.Linecast(StartPoint, DestObj.transform.position, out hit))
{
      GameObject HitObject = hit.collider.transform.root.gameObject;
      (....do something with the hit object here....)
}

So this will allow you to cast a line from ObjectA to ObjectB but start outside of ObjectA’s collider. Again, this assumes that you’re simply trying to cast outside of a simple capsule collider surounding a character or something similar.

thanks

What are we going to do if our game is multiplayer ? You cant ignore player in layermask but then you will going to ignore all players which means players cant hit each other…