using UnityEngine; public class WobbleBehavior : MonoBehaviour { [Header("Wobble Settings")] public float wobbleFrequency = 1.5f; // How fast the bottle rocks public float baseWobbleAmplitude = 8f; // Max degrees from horizontal public float speedToAmplitude = 2f; // How much speed affects amplitude public float maxRotationLimit = 45f; // Maximum allowed rotation in degrees [Header("Vertical Movement Settings")] public float verticalFrequency = 0.5f; // How fast the bottle moves up/down public float verticalAmplitude = 0.5f; // How far the bottle moves up/down [Header("Smoothing Settings")] public float velocitySmoothing = 10f; // How quickly velocity is smoothed public float rotationSmoothing = 10f; // How quickly rotation is smoothed private Vector3 lastPosition; private float wobbleTime; private float velocity; private Vector3 basePosition; private float verticalOffset; private float smoothedVelocity; private float smoothedAngle; public float Velocity => velocity; public float VerticalOffset => verticalOffset; void Start() { lastPosition = transform.position; smoothedVelocity = 0f; smoothedAngle = 0f; } void Update() { // Calculate movement speed (exclude vertical wobble from velocity calculation) Vector3 horizontalPosition = transform.position; horizontalPosition.y = 0f; // Ignore Y for velocity if only horizontal movement matters Vector3 horizontalLastPosition = lastPosition; horizontalLastPosition.y = 0f; velocity = (horizontalPosition - horizontalLastPosition).magnitude / Time.deltaTime; lastPosition = transform.position; // Smooth velocity to prevent jitter smoothedVelocity = Mathf.Lerp(smoothedVelocity, velocity, velocitySmoothing * Time.deltaTime); // Wobble amplitude scales with smoothed speed, but always has a base value float amplitude = baseWobbleAmplitude + smoothedVelocity * speedToAmplitude; amplitude = Mathf.Min(amplitude, maxRotationLimit); // Prevent amplitude from exceeding limit // Oscillate around horizontal (0 degrees) wobbleTime += Time.deltaTime * wobbleFrequency; float targetAngle = Mathf.Sin(wobbleTime) * amplitude; targetAngle = Mathf.Clamp(targetAngle, -maxRotationLimit, maxRotationLimit); // Smooth the rotation angle smoothedAngle = Mathf.Lerp(smoothedAngle, targetAngle, rotationSmoothing * Time.deltaTime); // Apply rotation (Z axis for 2D) transform.localRotation = Quaternion.Euler(0f, 0f, smoothedAngle); // Calculate vertical up/down movement (wave riding) only once verticalOffset = Mathf.Sin(wobbleTime * verticalFrequency) * verticalAmplitude; } }