using UnityEngine; /// /// Gentle underwater sway for a tank plant, pivoting at its base, plus a push from the wake of /// passing fish: a fish swimming close by nudges the plant along its direction of travel, and the /// plant springs back and wobbles out. Put this on a pivot object at the plant's base. /// public class PlantSway : MonoBehaviour { [Tooltip("Idle sway, degrees.")] public float idleDegrees = 2.5f; public float idleSpeed = 0.6f; [Tooltip("How far a fish's wake reaches, in world units.")] public float wakeRadius = 5f; [Tooltip("Tilt (degrees) from a fish passing at full speed right next to the plant.")] public float wakeDegrees = 18f; [Tooltip("Spring stiffness and damping for the wobble after a push.")] public float stiffness = 9f, damping = 2.2f; Quaternion rest; Vector2 tilt, tiltVel; // x = tilt about world X (toward/away from glass), y = tilt about world Z (left/right) float phase; void Start() { rest = transform.localRotation; phase = Random.value * 10f; } void Update() { float dt = Time.deltaTime; if (dt <= 0f) return; // Wake: fish moving past push the plant along their velocity, stronger the closer and faster they are Vector2 push = Vector2.zero; Vector3 top = transform.position + Vector3.up * wakeRadius * 0.3f; foreach (var f in PaperFishController.Swimmers) { Vector3 d = f.Position - top; float dist = d.magnitude; if (dist > wakeRadius) continue; float k = 1f - dist / wakeRadius; Vector3 v = f.Velocity; push += new Vector2(v.z, -v.x) * k * k; // lean along the flow } // Spring toward idle sway + wake push float t = Time.time * idleSpeed + phase; Vector2 idle = new Vector2(Mathf.Sin(t), Mathf.Sin(t * 0.77f + 1.3f)) * idleDegrees; Vector2 target = idle + Vector2.ClampMagnitude(push * 1.2f, wakeDegrees); Vector2 accel = (target - tilt) * stiffness - tiltVel * damping; tiltVel += accel * dt; tilt += tiltVel * dt; transform.localRotation = Quaternion.Euler(tilt.x, 0f, tilt.y) * rest; } }