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