- Home /
Looking for advice to get around issues with CapsuleCast
Consider the following scenario:
I have a meshcollider that is a wavy plane, with a bit of thickness. Imagine a blanket on a badly made bed. I need to trace the edge of this plane to get a list of points, which will later be used.
What I came up with (and works most of the time) is to run a set of consecutive capsule casts (since I do not know the elevation of the side I am casting against yet)), using the normal from the last hit to perform the next cast, until I have traced the desired area. Imagine tapping the edge of the blanket with a broomstick (longways, such that the side of the stick hits the edge of the blanket).
The issue I have with this approach is that occasionally, I hit the TOP of the plane, and not the side (remember, it DOES have thickness, so there is a side to hit for sure). This causes the normal to be facing the wrong direction, and messes up the rest of the trace.
The normal returned from RaycastHit for this is not correct due to the nature of capsulecast and spherecast. UI already account for and correct this by taking the face that was hit, and manually calculating the normal (this is confirmed correct), via this method:
/// <summary>
/// Calculates the surface normal of the collider that was HIT.
/// This is to be used for sphere and capsule casts, where the
/// hit normal is actually based on the caster shape, and not the
/// collider hit
/// </summary>
/// <returns>Calculated Normal</returns>
public static Vector3 ColliderNormal(this RaycastHit hit, LayerMask mask = default(LayerMask)) {
Vector3 normal = Vector3.zero;
if(hit.collider is MeshCollider) {
Mesh mesh = ((MeshCollider)hit.collider).sharedMesh;
int[] tris = mesh.triangles;
Vector3[] verts = mesh.vertices;
Vector3 v0 = verts[tris[hit.triangleIndex * 3 + 0]];
Vector3 v1 = verts[tris[hit.triangleIndex * 3 + 1]];
Vector3 v2 = verts[tris[hit.triangleIndex * 3 + 2]];
normal = Vector3.Cross(v1 - v0, v2 - v1).normalized;
//return hit.transform.TransformDirection(n);
} else {
Vector3 p = hit.point + hit.normal * 0.01f;
Physics.Raycast(p, -hit.normal, out hit, 0.011f, mask);
normal = hit.normal;
}
return normal;
}
This has nothing to do with the issue, I just wanted to post it in case people started suspecting it.
I need to always get the SIDE of the plane, but capsulecast is unreliable. I have tried a few things to derive the side further (like raycasting against the bottom, lerping a new point to raycast against that is between both points), but that is turning out to be unreliable.
So what I wonder is, how would you handle this? What approach would you go about to get hits along the edge? I'm welcome to any and all suggestions. It is worth noting that I am rarely ever tracing the entire edge; I need subsets of the edge (a constraint I enforce with two planes).
I hope this makes sense. If needed, I can try to draw a shitty bmp to illustrate it further.