/// <summary> /// Retrieve the list of interactables that this interactor could possibly interact with this frame. /// This list is sorted by priority (in this case distance). /// </summary> /// <param name="validTargets">Populated List of interactables that are valid for selection or hover.</param> public override void GetValidTargets(List <XRBaseInteractable> validTargets) { // pointers used to sample the curve and check colliders between points Vector3 m_PreviousPoint; Vector3 m_NextPoint; validTargets.Clear(); // we havent init'd cleanly. bail out. if (m_SamplePoints == null || m_SamplePoints.Length < 2) { return; } m_NoSamplePoints = 1; m_SamplePoints[0] = m_StartTransform.position; m_PreviousPoint = m_StartTransform.position; m_HitCount = 0; m_HitPositionInLine = 0; int accumulatedHits = 0; int maxSamplePoints; switch (m_LineType) { case LineType.StraightLine: m_NextPoint = m_PreviousPoint + m_StartTransform.forward * maxRaycastDistance; m_HitCount = CheckCollidersBetweenPoints(m_PreviousPoint, m_NextPoint); if (m_HitCount != 0) { m_HitPositionInLine = 1; // hit position is between point 0 and point 1 } // save the "virtual" end point of the line m_SamplePoints[m_NoSamplePoints] = m_NextPoint; m_NoSamplePoints++; break; case LineType.ProjectileCurve: float flightTime = 2.0f * m_Velocity * Mathf.Sin(Mathf.Abs(Angle) * Mathf.Deg2Rad) / m_Acceleration + m_AdditionalFlightTime; Vector3 velocityVector = m_StartTransform.forward * m_Velocity; Vector3 accelerationVector = m_ReferenceFrame.up * -1.0f * m_Acceleration; maxSamplePoints = m_SamplePoints.Length; accumulatedHits = 0; for (int i = 1; i < m_SampleFrequency && m_NoSamplePoints < maxSamplePoints; i++) { float t = (float)i / (float)(m_SampleFrequency - 1) * flightTime; m_NextPoint = CalculateProjectilePoint(t, m_StartTransform.position, velocityVector, accelerationVector); // check collider only when there has not been a hit point if (accumulatedHits == 0) { accumulatedHits += CheckCollidersBetweenPoints(m_PreviousPoint, m_NextPoint); if (accumulatedHits != 0) { m_HitPositionInLine = i; } } // keep sampling m_SamplePoints[m_NoSamplePoints] = m_NextPoint; m_NoSamplePoints++; m_PreviousPoint = m_NextPoint; } m_HitCount = accumulatedHits; break; case LineType.BezierCurve: // update control points for bezier curve UpdateControlPoints(); maxSamplePoints = m_SamplePoints.Length; for (int i = 1; i < m_SampleFrequency && m_NoSamplePoints < maxSamplePoints; i++) { float t = (float)i / (float)(m_SampleFrequency - 1); m_NextPoint = CalculateBezierPoint(t, m_ControlPoints[0], m_ControlPoints[1], m_ControlPoints[2]); // check collider only when there has not been a hit point if (accumulatedHits == 0) { accumulatedHits += CheckCollidersBetweenPoints(m_PreviousPoint, m_NextPoint); if (accumulatedHits != 0) { m_HitPositionInLine = i; } } // keep sampling m_SamplePoints[m_NoSamplePoints] = m_NextPoint; m_NoSamplePoints++; m_PreviousPoint = m_NextPoint; } m_HitCount = accumulatedHits; break; } // sort all the hits by distance to the controller if (m_HitCount > 0) { SortingHelpers.Sort(m_RaycastHits, m_RaycastHitComparer); for (var i = 0; i < Math.Min(m_HitCount, kMaxRaycastHits); ++i) { var interactable = interactionManager.TryGetInteractableForCollider(m_RaycastHits[i].collider); if (interactable && !validTargets.Contains(interactable)) { validTargets.Add(interactable); } else { break; // blocker } } } }
/// <inheritdoc /> public override void GetValidTargets(List <XRBaseInteractable> targets) { SortingHelpers.SortByDistanceToInteractor(this, m_ValidTargets, targets); }