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;
}
}