using UnityEngine; /// /// Adds a wobble (rocking and vertical movement) effect to the object, based on speed and time. /// public class WobbleBehavior : MonoBehaviour { [Header("Wobble Settings")] public float wobbleFrequency = 1.5f; /// /// Max degrees from horizontal. /// public float baseWobbleAmplitude = 8f; /// /// How much speed affects amplitude. /// public float speedToAmplitude = 2f; /// /// Maximum allowed rotation in degrees. /// public float maxRotationLimit = 45f; [Header("Vertical Movement Settings")] public float verticalFrequency = 0.5f; /// /// How far the object moves up/down. /// public float verticalAmplitude = 0.5f; [Header("Smoothing Settings")] public float velocitySmoothing = 10f; /// /// How quickly rotation is smoothed. /// public float rotationSmoothing = 10f; private Vector3 lastPosition; private float wobbleTime; private float velocity; private Vector3 basePosition; private float verticalOffset; private float smoothedVelocity; private float smoothedAngle; /// /// The current velocity of the object (horizontal only). /// public float Velocity => velocity; /// /// The current vertical offset due to wobble. /// 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; } }