using UnityEngine; public class WindVisualizer : MonoBehaviour { [SerializeField] private Transform windTransform; // The object that will move (e.g., your LineRenderer GameObject) [SerializeField] private Transform windStart; // The starting point of the wind path [SerializeField] private Transform windEnd; // The ending point of the wind path [SerializeField] private float windSpeed = 1.0f; // Controls how fast the wind moves along the path [SerializeField] private float curveAmplitude = 1.0f; // How high/wide the sine curve is [SerializeField] private float curveFrequency = 1.0f; // How many waves are in the path [SerializeField] private TrailRenderer trailRenderer; // How many waves are in the path [SerializeField] private float initialPhaseOffset = 0f; // To offset the start time for multiple wind effects private float previousNormalizedTime = 0f; // To detect when the loop restarts // Start is called once before the first execution of Update after the MonoBehaviour is created void Start() { // Basic validation if (windTransform == null || windStart == null || windEnd == null) { Debug.LogError("WindVisualizer: 'windTransform', 'windStart', or 'windEnd' is not assigned. Please assign them in the Inspector.", this); enabled = false; // Disable the script if essential components are missing } } // Update is called once per frame void Update() { trailRenderer.enabled = true; if (windTransform == null || windStart == null || windEnd == null) { return; // Don't proceed if validation failed in Start } // Calculate the length of the path float pathLength = Vector3.Distance(windStart.position, windEnd.position); if (pathLength == 0) // Avoid division by zero if start and end are at the same position { windTransform.position = windStart.position; // Stay at start return; } // Calculate a normalized position along the path (0 to 1, then loops back to 0) float currentPathTime = (Time.time + initialPhaseOffset) * windSpeed / pathLength; float normalizedTime = Mathf.Repeat(currentPathTime, 1f); // Loops between 0 and 1 // --- Function Call Logic --- // If normalizedTime has wrapped around (i.e., it was high and now it's low), // it means the windTransform has logically reached the end and "jumped" back to the start. if (normalizedTime < previousNormalizedTime) { OnWindCycleComplete(); // Call your function here } previousNormalizedTime = normalizedTime; // Store for the next frame's comparison // --- End Function Call Logic --- // Get the straight-line position between start and end based on normalizedTime Vector3 straightLinePosition = Vector3.Lerp(windStart.position, windEnd.position, normalizedTime); // Calculate the direction vector from start to end Vector3 pathDirection = (windEnd.position - windStart.position).normalized; // Find a perpendicular direction for the sine wave offset Vector3 perpendicularDirection = Vector3.Cross(pathDirection, Vector3.forward); if (perpendicularDirection == Vector3.zero) { perpendicularDirection = Vector3.up; } perpendicularDirection.Normalize(); // Calculate the sine wave offset float sineInput = normalizedTime * curveFrequency * Mathf.PI * 2 + Time.time; float sineOffset = Mathf.Sin(sineInput) * curveAmplitude; // Apply the sine offset to the straight-line position windTransform.position = straightLinePosition + perpendicularDirection * sineOffset; } /// /// This function is called every time the wind visualizer completes a full cycle /// (i.e., it reaches the end position and resets to the start). /// private void OnWindCycleComplete() { trailRenderer.enabled = false; Instantiate(this.gameObject, transform.position, transform.rotation); Destroy(this.gameObject); } }