using System.Collections; using UnityEngine; namespace XRMultiplayer.MiniGames { /// /// Updates the visual elements of the slingshot in the gameplay. /// [ExecuteInEditMode] public class SlingshotVisualUpdater : MonoBehaviour { /// /// The line renderer displaying the current trajectory. /// public LineRenderer trajectoryLineRenderer; [SerializeField] Rigidbody m_Rigidbody; /// /// The transform of the bucket. /// [SerializeField] Rigidbody m_BucketRigibody; /// /// The transform of the shot center. /// [SerializeField] Transform m_ShotCenterTransform; /// /// The line renderers of the slingshot. /// [SerializeField] LineRenderer[] m_LineRenderers; /// /// The transform of the line end. /// [SerializeField] Transform[] m_LineEndTransforms; /// /// The minimum and maximum distance of the slingshot. /// [SerializeField] Vector2 m_MinMaxDistance = new Vector2(0.0f, 1.0f); /// /// The minimum and maximum size of the line. /// [SerializeField] Vector2 m_MinMaxLineSize = new Vector2(.05f, .01f); /// /// The minimum and maximum shot force. /// [SerializeField] Vector2 m_MinMaxShotForce = new Vector2(5.0f, 20.0f); /// /// The force multiplier of the shot. /// [SerializeField] float m_ForceMultiplier = 2.0f; /// /// The maximum distance to display the debug line. /// [SerializeField] float m_MaxDebugShowDistance = 2.0f; /// /// The time to reset the bucket position. /// [SerializeField] float m_BucketResetTime = .35f; /// /// The color divisor of the debug line. /// [SerializeField] float m_ColorDivisor = 5.0f; /// /// The line display distance. /// [SerializeField] float m_LineDisplayDistance = 2.0f; [SerializeField] bool m_LockBucketRotation = true; /// /// The shot force of the slingshot. /// float m_ShotForce; /// /// The aim direction of the slingshot. /// Vector3 m_AimDirection; /// /// The reset position of the bucket. /// // Vector3 m_ResetPosition; Pose m_ResetPose; /// void Awake() { trajectoryLineRenderer.enabled = false; m_ResetPose = new Pose(m_BucketRigibody.transform.localPosition, m_BucketRigibody.transform.localRotation); // m_ResetPosition = m_BucketTransform.localPosition; } /// void LateUpdate() { for (int i = 0; i < m_LineRenderers.Length; i++) { m_LineRenderers[i].SetPosition(0, m_LineRenderers[i].transform.position); m_LineRenderers[i].SetPosition(1, m_LineEndTransforms[i].position); float distance = Vector3.Distance(m_LineRenderers[i].transform.position, m_LineEndTransforms[i].position); float perc = Utils.GetPercentOfValueBetweenTwoValues(m_MinMaxDistance.x, m_MinMaxDistance.y, distance); float size = Mathf.Lerp(m_MinMaxLineSize.x, m_MinMaxLineSize.y, perc); m_LineRenderers[i].startWidth = size; m_LineRenderers[i].endWidth = size; } float lineDistance = Vector3.Distance(m_ShotCenterTransform.position, m_BucketRigibody.position); m_ShotForce = Mathf.Clamp(lineDistance * m_ForceMultiplier, m_MinMaxShotForce.x, m_MinMaxShotForce.y); m_AimDirection = (m_ShotCenterTransform.position - m_BucketRigibody.position).normalized; Vector3 lineEndPos = m_BucketRigibody.position + (m_AimDirection * Mathf.Clamp(lineDistance * m_LineDisplayDistance, 0.0f, m_MaxDebugShowDistance)); Color forceColor = Color.Lerp(Color.yellow, Color.red, Mathf.Clamp01(m_ShotForce / m_MaxDebugShowDistance / m_ColorDivisor)); Color transparentForceColor = new Color(forceColor.r, forceColor.g, forceColor.b, 0.0f); trajectoryLineRenderer.startColor = forceColor; trajectoryLineRenderer.endColor = transparentForceColor; trajectoryLineRenderer.SetPosition(0, m_BucketRigibody.position); trajectoryLineRenderer.SetPosition(1, lineEndPos); if (m_LockBucketRotation) m_BucketRigibody.transform.forward = m_AimDirection; } /// /// Gets the force of the shot. /// /// The force of the shot. public Vector3 GetShotForce() { return m_AimDirection * m_ShotForce; } public void ResetSlingshot(float height) { StartCoroutine(ResetSlingshotHeightRoutine(height)); ResetBucketPosition(); } IEnumerator ResetSlingshotHeightRoutine(float height) { bool wasKinematic = m_Rigidbody.isKinematic; m_Rigidbody.isKinematic = true; transform.localPosition = new Vector3(transform.localPosition.x, height, transform.localPosition.z); yield return new WaitForSeconds(.15f); m_Rigidbody.isKinematic = wasKinematic; } /// /// Resets the position of the bucket. /// public void ResetBucketPosition() { StartCoroutine(ResetBucketPositionRoutine()); } /// /// Coroutine to reset the position of the bucket over time. /// /// An IEnumerator used for the coroutine. IEnumerator ResetBucketPositionRoutine() { bool wasKinematic = m_BucketRigibody.isKinematic; m_BucketRigibody.isKinematic = true; for (float i = 0; i < m_BucketResetTime; i += Time.deltaTime) { m_BucketRigibody.transform.localPosition = Vector3.Lerp(m_BucketRigibody.transform.localPosition, m_ResetPose.position, i / m_BucketResetTime); yield return null; } m_BucketRigibody.transform.SetLocalPositionAndRotation(m_ResetPose.position, m_ResetPose.rotation); m_BucketRigibody.isKinematic = wasKinematic; } } }