Some salient facts here: Problem with raycasting using a layer mask - Questions & Answers - Unity Discussions
And also some answers, which seem to be flat out wrong. So far the only conclusion i can come to is that unity is broken. But that can’t be so, can it? I must be missing something.
I’m attempting to do a raycast which hits most layers, but ignored my player’s layer and also the layer ghostChunks.
My entire masks class which contains the layermask, is this:
using UnityEngine;
using System.Collections;
public class masks : MonoBehaviour
{
public const int VisibilityCastMask = 65535;//Does not hit ghost chunks, players
}
65535 equates to 1111111111111111 in binary. That’s sixteen ones
which when used as a layer mask should cause the raycast to hit layers 0-15, and ignore all following layers
Is this statement correct?
A layermask of 1111111111111111 is functionally equivilant to a layermask of 00000000000000001111111111111111
Is this statement correct?
I believe it is, i fed 65535 into a public layermask variable and checked it in the inspector, it showed this:
My player is on layer 17, named Players.
Here is my entire list of layers, to prove that Players is indeed layer 17
Now, what i’m doing is raycasting to hundreds of small objects in the scene, from the camera, to check if they’re visible or not. (don’t offer alternative approaches please, just make this work)
The player is BLOCKING these raycasts. Whenever it is between the camera and the target, the cast fails to hit the target, consistently.
The entire, unedited raycasting function can be found at the bottom of this post, just to be sure. I call one raycast to the centre, and then several more raycasts to random vertexes on the object, if that fails.
Pay special attention to line 44. A debug message, which can only be reached if the first object we collide with is not the target.
It outputs the name of the collider’s object, the layermask we’re currently using, and the layer the collider’s object is on. I use this debug message to dispel the faint possibility that i’m using an incorrect mask, or that the mask somehow changed just before casting, or that the player is not actually on the layer i think he is.
Here is a common output of that debug message:
Unified Character is the name of my player object. It clearly shows he is on layer 17, and that the mask is still 65535.
By everything i know, a raycast with a mask of 65535 cannot possibly detect objects on layer 17
Is this statement true?
Process of elimination. When you’ve eliminated all other possibilities, whatever remains, however improbable, must be the truth. Right now as far as i can tell, I have eliminated all possibilities except these:
- One of the bolded statements i’ve made is untrue, and i’m working on false assumptions
- There is a bug in unity
Are there any other possibilities? What the hell is going on here?
public static bool VisibilityCastChunk(GameObject origin, FracturedChunk target)
{
//This function performs a complex raycast using multiple rays. The exact number of rays used scales up as required, based on the volume of the target object
float minVolume = 0.1f;//Objects below this volume will use only a single ray
float maxVolume = 3.0f;//Objects at or above this volume will use the most possible rays.
int maxCasts = 7;
int raycasts = 0;
Vector3 targetPos = target.gameObject.transform.position;
Vector3 castPos;
Vector3 originPos = origin.gameObject.transform.position;
RaycastHit hit = new RaycastHit();
Vector3[] chunkVerts = target.GetComponent<MeshFilter>().sharedMesh.vertices;
if (target.Volume <= minVolume)
{
raycasts = 1;
}
else if (target.Volume >= maxVolume)
{
raycasts = maxCasts;
}
else
{
//maxcasts -1 = how many pieces to cut
//maxvolume - minvolume = what to cut
//cut what into num pieces to get the threshold.
//divide (volume - minVolume) by threshold, and ceiltoint
raycasts = Mathf.CeilToInt((target.Volume - minVolume) / ((maxVolume - minVolume) / (maxCasts - 1)));
}
if (target.gameObject.collider is MeshCollider)
{
for (i = raycasts - 1; i >= 0;i-- )
{
if (i == raycasts - 1)//if this is the first cast
{
Physics.Raycast(originPos, (targetPos - originPos), out hit, masks.VisibilityCastMask);
if (hit.collider == target.gameObject.collider)
{
//Visibility.SetColor(target.gameObject, Color.green);
return true;
}
print("First Scan: "+hit.collider.gameObject.name+" mask "+masks.VisibilityCastMask+" Layer:"+hit.collider.gameObject.layer);
}
else
{
castPos = chunkVerts[Random.Range(0, chunkVerts.Length-1)] + targetPos;//Beware optimize here
Physics.Raycast(originPos, (castPos - originPos), out hit, masks.VisibilityCastMask);
if (hit.collider == target.gameObject.collider)
{
//Visibility.SetColor(target.gameObject, Color.green);
return true;
}
}
}
}
//Visibility.SetColor(target.gameObject, Color.red);
return false;
}