using UnityEngine; namespace NextMind.Examples.Discovery { /// /// This component add a levitation effect to an object. /// It make it moves smoothly on its y axis following the given and . /// Moreover, the Y value around which this levitation effect happen can be set using . /// public class LevitationMovement : MonoBehaviour { [SerializeField] private Transform hostTransform = null; /// /// The levitation effect frequency. /// [SerializeField] private float frequency = 1f; /// /// The levitation effect amplitude. /// [SerializeField] private float amplitude = 0.02f; /// /// The distance between lowerY and upperY. /// [SerializeField] private float distanceBetweenPosisiton = 0.3f; /// /// Should we add a random rotation? /// [SerializeField] private bool rotateRandomly = true; /// /// The Y value to apply for SetCurrentPosition(0) /// private float lowerY; /// /// The Y value to apply for SetCurrentPosition(1) /// internal float upperY; /// /// The current Y value. /// private float targetY; /// /// The animation curve used to evaluate how the transition between lowerY and upperY is done. /// private AnimationCurve positionTransitionCurve; /// /// The random rotation euler angles. /// private Vector3 randomRotation; /// /// The current Y position between lowerY and upperY. /// private float currentWideOscillationY; /// /// The timer used to modulate the amplitude. /// private float amplitudeTimer = 0f; private void Start() { if (hostTransform == null) { hostTransform = this.transform; } positionTransitionCurve = AnimationCurve.EaseInOut(0, 0, 1, 1); // Compute the limit values lowerY = hostTransform.position.y; upperY = lowerY + distanceBetweenPosisiton; currentWideOscillationY = lowerY; SetCurrentPosition(0); randomRotation = 10 * new Vector3(0, Random.value - 0.5f, 0); } void Update() { var newPosition = hostTransform.position; // Lerp the position between lowerY and upperY. currentWideOscillationY = Mathf.Lerp(currentWideOscillationY, targetY, 10 * Time.deltaTime); // Add the levitation effect. newPosition.y = currentWideOscillationY + amplitude * Mathf.Sin(frequency * amplitudeTimer); amplitudeTimer += Time.deltaTime; // Finally set the position. hostTransform.position = newPosition; // Add a slight random rotation if needed. if (rotateRandomly) { hostTransform.Rotate(randomRotation * Time.deltaTime); } } /// /// Define the wanted position between lowerY and upperY. /// /// The value between 0 (lowerY) and 1 (upperY) public void SetCurrentPosition(float t) { targetY = Mathf.Lerp(lowerY, upperY, positionTransitionCurve.Evaluate(t)); } } }