/// <summary> /// Performs a raycast according to the supplied configuration. /// </summary> /// <returns><c>true</c> if a collider was hit, otherwise <c>false</c>.</returns> public static bool TryCast(this Ray ray, out RaycastHit hit, RaycastConfig config) { // Raise ray origin to avoid missing hits in close proximity. if (config.raiseRaycast > 0f) { ray.origin += -ray.direction * config.raiseRaycast; } switch (config.mode) { case RaycastMode.Ray: if (Physics.Raycast(ray, out hit, config.maxDistance, config.layerMask)) { return(true); } break; case RaycastMode.Sphere: if (Physics.SphereCast(ray, config.radius, out hit, config.maxDistance, config.layerMask)) { return(true); } break; default: throw new ArgumentOutOfRangeException("config", config.mode, "Unknown RaycastMode"); } return(false); }
/// <summary> /// Sets the Transform's position so that it is at the intersection with a layer directly below the Transform's downwards vector. /// </summary> /// <remarks> /// This is useful for snapping an object down onto a terrain (provided that it is correctly oriented with the terrain). /// </remarks> /// <param name="tx">The Transform to reposition.</param> /// <param name="config">The raycast configuration.</param> /// <param name="raiseRaycast">The distance above the transform to use as the origin of the raycast.</param> /// <param name="raiseSnap">The distance above the raycast hit point to move the snapped position.</param> public static void SnapDown(this Transform tx, RaycastConfig config, float raiseRaycast = 0f, float raiseSnapped = 0f) { var p = tx.position + tx.up * raiseRaycast; var snapped = p.SnapToLayer(-tx.up, config) + tx.up * raiseSnapped; tx.position = snapped; }
/// <summary> /// Snaps the vector <paramref name="pos"/> to the intersection with a collider in the specified direction. /// </summary> /// <returns>The new position.</returns> /// <param name="pos">The position to snap to the layer.</param> /// <param name="dir">The direction in which to snap.</param> /// <param name="config">Configuration of the physics casting to perform.</param> public static Vector3 SnapToLayer(this Vector3 pos, Vector3 dir, RaycastConfig config) { var ray = new Ray(pos, dir); RaycastHit hit; if (ray.TryCast(out hit, config)) { return(hit.point); } // We didn't hit anything, so return original position. return(pos); }
/// <summary> /// Sets the Transform's position so that it is at the intersection with a layer directly below the Transform's downwards vector. /// </summary> /// <remarks> /// This is useful for snapping an object down onto a terrain (provided that it is correctly oriented with the terrain). /// </remarks> /// <param name="tx">The Transform to reposition.</param> /// <param name="layerMask">The layer mask being snapped to.</param> /// <param name="raiseRaycast">The distance above the transform to use as the origin of the raycast.</param> /// <param name="raiseSnap">The distance above the raycast hit point to move the snapped position.</param> public static void SnapDown(this Transform tx, int layerMask, float raiseRaycast = 0f, float raiseSnapped = 0f) { var config = RaycastConfig.Ray(layerMask: layerMask); tx.SnapDown(config, raiseRaycast, raiseSnapped); }