public Hit Test(Ray ray, float rayLength = 500.0f) { LastHit = Hit.Invalid; if (Target == null) { return(Hit.Invalid); } Hit hit = new Hit(); Collide.Shape shape = Target.GetComponent <Collide.Shape>(); if (shape != null) { if (shape is Collide.Mesh) { hit.Triangle = MeshUtils.FindClosestTriangle((shape as Collide.Mesh).SourceObjects, shape.gameObject, ray, rayLength); } else if (shape is Collide.HeightField) { hit.Triangle = TriangleHit.Invalid; } else { GameObject tmp = PrefabLoader.Instantiate <GameObject>(Rendering.DebugRenderData.GetPrefabName(shape.GetType().Name)); if (tmp != null) { tmp.hideFlags = HideFlags.HideAndDontSave; tmp.transform.position = shape.transform.position; tmp.transform.rotation = shape.transform.rotation; tmp.transform.localScale = shape.GetScale(); hit.Triangle = MeshUtils.FindClosestTriangle(tmp, ray, rayLength); hit.Triangle.Target = shape.gameObject; GameObject.DestroyImmediate(tmp); } } } else { MeshFilter filter = Target.GetComponent <MeshFilter>(); hit.Triangle = filter != null?MeshUtils.FindClosestTriangle(filter.sharedMesh, Target, ray, rayLength) : TriangleHit.Invalid; } if (hit.Triangle.Valid) { hit.Triangle.ClosestEdge = ShapeUtils.FindClosestEdgeToSegment(ray.GetPoint(0), ray.GetPoint(rayLength), hit.Triangle.Edges).Edge; } List <MeshUtils.Edge> allEdges = FindPrincipalEdges(shape, 10.0f).ToList(); if (hit.Triangle.Valid) { allEdges.Add(hit.Triangle.ClosestEdge); } var closestEdgeToSegmentResult = ShapeUtils.FindClosestEdgeToSegment(ray.GetPoint(0), ray.GetPoint(rayLength), allEdges.ToArray()); hit.ClosestEdge.Target = Target; hit.ClosestEdge.Edge = closestEdgeToSegmentResult.Edge; hit.ClosestEdge.Distance = closestEdgeToSegmentResult.Distance; return(LastHit = hit); }