- Home /
RaycastHit.triangleIndex always returning -1
So I've been looking into how to get the material of a certain triangle on a certain mesh by raycasting and then attempting to get the triangle index and search through the object's submeshes to find the triangle that was hit and thus, it's index which should be used to get the material BUT for some reason I am always getting a "-1" for the triangle index return when raycasting onto my mesh. I looked around and didn't see anyone else with "unity raycast.triangleIndex returning -1" issues so I came here.
Sorry if I missed something someone posted before but thought I'd ask to see if anyone knew what my issue might be. Below is the code I currently have.
Vector3 HitCoords(){
//Returns Vector3 of the mouse's click location
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
//Raycast to mouse point
Physics.Raycast (ray, out hit, 100);
//set burstMaterial to hit triangle's material
FindTriangleMaterial (hit);
return hit.point;
}
void FindTriangleMaterial(RaycastHit hit){
triIndex = hit.triangleIndex; //<-- this is always -1
mesh = GetComponent<MeshFilter>().sharedMesh;
subMeshCount = mesh.subMeshCount;
matIndex = -1;
for (int i = 0; i < subMeshCount; i++) {
int[] curTris = mesh.GetTriangles(i);
for(int j = 0; j < curTris.Length; j++){
if(curTris[j] == triIndex){
matIndex = i;
break;
}
}
}
if (matIndex == -1) {
burstMat = null;
} else {
burstMat = GetComponent<Renderer>().materials[matIndex];
}
}
Thanks for anyone who can help.
EDIT: So in looking around, I have found that convex mesh colliders wont allow triangleIndex to ever work? I saw nothing on this anywhere else but if this is the case, that's a real bummer. Verification would be much appreciated.
Answer by Bunny83 · Jun 29, 2015 at 01:32 AM
Of course it doesn't work with a convex mesh collider since a convex mesh represents the convex hull of your actual mesh. So it's triangles have no relation to the actual mesh at all. A convex mesh collider also works way different from a normal mesh collider. A convex mesh collider represents a volume while a normal mesh collider just represents a surface.
Keep in mind that you can use two meshcolliders if you want, one convex and one non-convex. Just setup the layers accordingly to define which one can collider with what.
However if your mesh contains submeshes the triangleIndex won't help much i think. The MeshCollider of course doesn't use submeshes. So the triangle index won't tell you to which submesh the triangle belongs.
Your code also makes no sense since you compare the triangle index to a vertex index. The triangle index is simply the position of a triangle within the triangles array divided by 3 (since a triangle is made by 3 vertices)
What you can do is doing something like this (This might even work):
use the world space position of your raycast hit point and transform it into local space of your mesh (Transform.InverseTransformPoint).
Iterate through all submeshes and through all triangles (take 3 indices at a time)
use the vertices array with the 3 indices to get the actual positions of the corners.
use the 3 points to calculate the face normal (cross product)
use the face normal and one corner of the triangle to project our hit point onto the triangle.
Check if the distance between the projected point and the actual hitpoint is very small (so the point actually lays in the plane of the triangle).
Calculate the barycentric coordinate of the projected hit point for each triangle. See this post over here
With the barycentric coordinate you can easily check if the hitpoint is within the triangle
Well thanks for clarifying. It seemed like that was the case about convex colliders as being more of just "volumes" but I didn't know for sure so thank you for clarifying. (Rather new to 3D development :D )
Any who, I have decided to not go through with this method because my game involves using non-kinematic rigidbodies and as far as I know, you can't have a non-kinematic, non-convex object in Unity so I'll just make some $$anonymous$$aterial variable that is passed in ins$$anonymous$$d of trying to find the material on a specific triangle of the object. Thanks for the clarification!
PS- To comment on your instructions that seem to be in mush detail and well thought out, thank you as well but that seems to be much too detailed for the simple effect I had in $$anonymous$$d. It seems like it would work but for what I was going to use the triangle-material-lookup for, it's just not worth it from a mobile development standpoint.
Just took my 5-10 $$anonymous$$utes to log in (Coz I don't have access to my registered phone number blah blah) Just to Thank you... You saved me
Answer by SirLogray · Jul 19, 2017 at 09:38 PM
Just replace your primitive Collider with a MeshCollider. RaycastHit.triangleIndex only works with those.
He didn't use a primitive collider. He used a $$anonymous$$eshCollider. However the $$anonymous$$eshCollider must not be marked as "convex". It should be obvious that you need to use a $$anonymous$$eshCollider in the first place..
Answer by DiegoSLTS · Jun 28, 2015 at 02:15 PM
Physics.Raycast returns true when the raycast actually hits something. You're not checking this, are you sure there was a hit? Maybe you're using the "hit" variable without any hit happening. Check that return value and maybe add a Debug.Log line to make sure it's hitting what you think it's hitting:
Debug.Log(hit.rigidbody.name);
So it returns the rigidbody's name as it should. Something I should probably say is that this script is on the actual object being raycast on. I use an On$$anonymous$$ouseDOwn event that calls the HitCoords() function to find where on this object I just clicked. This might be the issue but I was attempting to keep raycasting confined to each game object as it is clicked.
Answer by Saravanan_unity · Mar 26, 2019 at 11:13 AM
@Escapade Just Update MeshCollider for each hit. Assign the updated mesh to MeshCollider component. This issue may be solved. but if any others finding for solution my suggestion may be helpful.
Answer by Es_ · Sep 13, 2020 at 08:44 PM
If there is a rigidbody attached to the transform of the hit meshCollider (non-convex), the meshCollider will not return triangle indexes. Set the rigidbody to isKinematic before raycasting and then back to whatever it was.