/// <summary> /// SORT ORDER IS NOT GUARANTEED BY PHYSICS /// Use : RaycastHelper.SortByDistance(rhd); /// /// https://docs.unity3d.com/ScriptReference/Physics.BoxCastNonAlloc.html /// </summary> /// <param name="rhd">The returned hit data will be stored here</param> /// <param name="center"></param> /// <param name="halfExtents"></param> /// <param name="direction"></param> /// <param name="orientation"></param> /// <param name="maxDistance"></param> /// <returns>Returns true if cast hits something</returns> public static bool BoxCast (RaycastHitData rhd, Vector3 center, Vector3 halfExtents, Vector3 direction, Quaternion orientation, float maxDistance = Mathf.Infinity) { CheckRHDInit(rhd); for (; ;) { rhd.numHits = Physics.BoxCastNonAlloc (center, halfExtents, direction, rhd.hitResults, orientation, maxDistance, rhd.layerMask, rhd.triggerInteraction); if (CheckCastResultsRHD(rhd)) { break; } } return(rhd.numHits > 0); }
/// <summary> /// Sort using static temporary variables to avoid memory allocations /// at runtime. NOT THREAD SAFE! USE ONLY ON MAIN THREAD! /// </summary> /// <param name="rhd"></param> public static void CombSort(ref RaycastHitData rhd) { gap = rhd.numHits; swaps = false; i = 0; while (gap > 1 || swaps) { gap /= 1.247330950103979f; if (gap < 1) { gap = 1; } i = 0; swaps = false; while (i + gap < rhd.numHits) { int igap = i + (int)gap; if (rhd.hitResults[i].distance > rhd.hitResults[igap].distance) { // Swap tempRaycastHit = rhd.hitResults[i]; rhd.hitResults[i] = rhd.hitResults[igap]; rhd.hitResults[igap] = tempRaycastHit; swaps = true; } ++i; } } }
/// <summary> /// SORT ORDER IS NOT GUARANTEED BY PHYSICS /// Use : RaycastHelper.SortByDistance(rhd); /// /// https://docs.unity3d.com/ScriptReference/Physics.CapsuleCastNonAlloc.html /// </summary> /// <param name="rhd"></param> /// <param name="point1"></param> /// <param name="point2"></param> /// <param name="radius"></param> /// <param name="direction"></param> /// <param name="maxDistance"></param> /// <returns></returns> public static bool CapsuleCast (RaycastHitData rhd, Vector3 point1, Vector3 point2, float radius, Vector3 direction, float maxDistance = Mathf.Infinity) { CheckRHDInit(rhd); for (; ;) { rhd.numHits = Physics.CapsuleCastNonAlloc (point1, point2, radius, direction, rhd.hitResults, maxDistance, rhd.layerMask, rhd.triggerInteraction); if (CheckCastResultsRHD(rhd)) { break; } } return(rhd.numHits > 0); }
/// <summary> /// SORT ORDER IS NOT GUARANTEED BY PHYSICS /// Use : RaycastHelper.SortByDistance(rhd); /// /// Like a raycast with thickness, or a capsule. /// /// https://docs.unity3d.com/ScriptReference/Physics.SphereCastNonAlloc.html /// /// From Physics.SphereCastNonAlloc : /// It will only compute as many hits as fit into the buffer, /// and store them in no particular order. It's not /// guaranteed that it will store only the closest hits. /// </summary> /// <param name="rhd">The returned hit data will be stored here</param> /// <param name="origin"></param> /// <param name="radius">The radius of the sphere</param> /// <param name="direction"></param> /// <returns>Returns true if cast hits something</returns> public static bool SphereCast (RaycastHitData rhd, Vector3 origin, float radius, Vector3 direction, float maxDistance = Mathf.Infinity) { if (radius == 0) { Debug.LogError("No radius, unpredicatble results"); return(false); } CheckRHDInit(rhd); for (; ;) { rhd.numHits = Physics.SphereCastNonAlloc (origin, radius, direction, rhd.hitResults, maxDistance, rhd.layerMask, rhd.triggerInteraction); if (CheckCastResultsRHD(rhd)) { break; } } return(rhd.numHits > 0); }
/// <summary> /// SORT ORDER IS NOT GUARANTEED BY PHYSICS /// Use : RaycastHelper.SortByDistance(rhd); /// /// https://docs.unity3d.com/ScriptReference/Physics.RaycastNonAlloc.html /// </summary> /// <param name="rhd"></param> /// <param name="ray"></param> /// <param name="maxDistance"></param> /// <returns>True if hits returned something</returns> public static bool Raycast (RaycastHitData rhd, Ray ray, float maxDistance) { CheckRHDInit(rhd); // For debugging //Debug.DrawRay(ray.origin, ray.direction, Color.red); for (; ;) { rhd.numHits = Physics.RaycastNonAlloc (ray, rhd.hitResults, maxDistance, rhd.layerMask, rhd.triggerInteraction); if (CheckCastResultsRHD(rhd)) { break; } } return(rhd.numHits > 0); }
/// <summary> /// SORT ORDER IS NOT GUARANTEED BY PHYSICS /// Use : RaycastHelper.SortByDistance(rhd); /// /// https://docs.unity3d.com/ScriptReference/Physics.RaycastNonAlloc.html /// </summary> /// <param name="rhd"></param> /// <param name="origin"></param> /// <param name="direction"></param> /// <param name="maxDistance"></param> /// <returns>True if hits returned something</returns> public static bool Raycast (RaycastHitData rhd, Vector3 origin, Vector3 direction, float maxDistance) { CheckRHDInit(rhd); for (; ;) { rhd.numHits = Physics.RaycastNonAlloc (origin, direction, rhd.hitResults, maxDistance, rhd.layerMask, rhd.triggerInteraction); if (CheckCastResultsRHD(rhd)) { break; } } return(rhd.numHits > 0); }
/// <summary> /// Check data for basic initialization /// </summary> /// <param name="rhd"></param> static void CheckRHDInit(RaycastHitData rhd) { if (rhd.hitResults == null || rhd.hitResults.Length == 0) { rhd.Init(rhd.sizeAtInit); } }
/// <summary> /// Function will cannot be called with a null 'results' /// parameter to determine how many results are REALLY /// available. So, if the number of hits is exactly /// the length of the array I resize the array and /// call again to be sure. /// </summary> /// <param name="rhd"></param> /// <returns>True if Cast needs to be called again</returns> static bool CheckCastResultsRHD(RaycastHitData rhd) { if (rhd.autoResize && rhd.numHits == rhd.hitResults.Length) { System.Array.Resize <RaycastHit>(ref rhd.hitResults, rhd.hitResults.Length * 2); return(false); } return(true); }
/// <summary> /// Sorts RaycastHitData by RaycastHit distance, in reverse /// Furthest is index 0, closest is rhd.numHits /// /// No memory allocations! Yay! /// </summary> /// <param name="rhd"></param> public static void SortByDistanceRev(RaycastHitData rhd) { // Array.Sort() can allocate memory! GC.Alloc will appear in the Profiler // //Array.Sort(rhd.hitResults, // 0, // rhd.numHits, // _distRevComparer); if (rhd.numHits == 0) { return; } CombSortRev(ref rhd); }