public override void SolverUpdate() { // Pass-through by default this.GoalPosition = WorkingPos; this.GoalRotation = WorkingRot; // Determine raycast params Ray ray = new Ray(GetRaycastOrigin(), GetRaycastDirection()); // Skip if there's no valid direction if (ray.direction == Vector3.zero) { return; } float ScaleOverride = GetScaleOverride(); float len; bool bHit; RaycastResultHelper result; Vector3 hitDelta; switch (raycastMode) { case RaycastModeEnum.Simple: default: // Do the cast! bHit = DefaultRaycast(ray.origin, ray.direction, MaxDistance, MagneticSurface, out result); OnSurface = bHit; if (UseTexCoordNormals) { result.OverrideNormalFromTextureCoord(); } // Enforce CloseDistance hitDelta = result.Point - ray.origin; len = hitDelta.magnitude; if (len < CloseDistance) { result.OverridePoint(ray.origin + ray.direction * CloseDistance); } // Apply results if (bHit) { GoalPosition = result.Point + SurfaceNormalOffset * result.Normal + SurfaceRayOffset * ray.direction; GoalRotation = CalculateMagnetismOrientation(ray.direction, result.Normal); } break; case RaycastModeEnum.Box: Vector3 scale = transform.lossyScale; if (ScaleOverride > 0) { scale = scale.normalized * ScaleOverride; } Quaternion orientation = orientationMode == OrientModeEnum.None ? Quaternion.LookRotation(ray.direction, Vector3.up) : CalculateMagnetismOrientation(ray.direction, Vector3.up); Matrix4x4 targetMatrix = Matrix4x4.TRS(Vector3.zero, orientation, scale); if (m_BoxCollider == null) { m_BoxCollider = this.GetComponent <BoxCollider>(); } Vector3 extents = m_BoxCollider.size; Vector3[] positions; Vector3[] normals; bool[] hits; if (RaycastHelper.CastBoxExtents(extents, transform.position, targetMatrix, ray, MaxDistance, MagneticSurface, DefaultRaycast, BoxRaysPerEdge, OrthoBoxCast, out positions, out normals, out hits)) { Plane plane; float distance; // place an unconstrained plane down the ray. Never use vertical constrain. FindPlacementPlane(ray.origin, ray.direction, positions, normals, hits, m_BoxCollider.size.x, MaximumNormalVariance, false, orientationMode == OrientModeEnum.None, out plane, out distance); // If placing on a horzizontal surface, need to adjust the calculated distance by half the app height float verticalCorrectionOffset = 0; if (IsNormalVertical(plane.normal) && !Mathf.Approximately(ray.direction.y, 0)) { float boxSurfaceOffsetVert = targetMatrix.MultiplyVector(new Vector3(0, extents.y / 2f, 0)).magnitude; Vector3 correctionVec = boxSurfaceOffsetVert * (ray.direction / ray.direction.y); verticalCorrectionOffset = -correctionVec.magnitude; } float boxSurfaceOffset = targetMatrix.MultiplyVector(new Vector3(0, 0, extents.z / 2f)).magnitude; // Apply boxSurfaceOffset to rayDir and not surfaceNormalDir to reduce sliding GoalPosition = ray.origin + ray.direction * Mathf.Max(CloseDistance, distance + SurfaceRayOffset + boxSurfaceOffset + verticalCorrectionOffset) + plane.normal * (0 * boxSurfaceOffset + SurfaceNormalOffset); GoalRotation = CalculateMagnetismOrientation(ray.direction, plane.normal); OnSurface = true; } else { OnSurface = false; } break; case RaycastModeEnum.Sphere: // Do the cast! float size = ScaleOverride > 0 ? ScaleOverride : transform.lossyScale.x * SphereSize; bHit = DefaultSpherecast(ray.origin, ray.direction, size, MaxDistance, MagneticSurface, out result); OnSurface = bHit; // Enforce CloseDistance hitDelta = result.Point - ray.origin; len = hitDelta.magnitude; if (len < CloseDistance) { result.OverridePoint(ray.origin + ray.direction * CloseDistance); } // Apply results if (bHit) { GoalPosition = result.Point + SurfaceNormalOffset * result.Normal + SurfaceRayOffset * ray.direction; GoalRotation = CalculateMagnetismOrientation(ray.direction, result.Normal); } break; } // Do frame to frame updates of transform, smoothly toward the goal, if desired UpdateWorkingPosToGoal(); UpdateWorkingRotToGoal(); }