Change position (hover) over time with easing?

Howdy, I've got a bunch of objects i'd like to animate floating (moving up then back down their respective Y position) smoothly. The following is what I'm using to also rotate the objects slightly over time:

private var rotating1 = false;

function RotateObject1 (thisTransform : Transform, degrees : Vector3, seconds : float) {
if (rotating1) return;
rotating1 = true;

var startRotation = thisTransform.rotation;
var endRotation = thisTransform.rotation * Quaternion.Euler(degrees);
var t = 0.0;
var rate = 1.0/seconds;

while (t < 1.0) {
    t += Time.deltaTime * rate;
    thisTransform.rotation = Quaternion.Slerp(startRotation, endRotation, Mathf.SmoothStep(0.0, 1.0, t));
    yield;
}

rotating1 = false;

}

as seen here: http://answers.unity3d.com/questions/7380/rotate-90-degrees-over-time-with-parabolic-easing

I've tried to modify the code above to serve my translation needs, but I don't really know what I'm doing. Any suggestions?

I want the amount to lift to be flexible (a variable) so I can assign it differently to different objects.

Thanks,

Richard

If you just want to hover, you can take the same code and apply it to position.

private var floating : bool = false;

function Float(objTransform : Transform, amplitude : Vector3, duration : float) {
    if (floating) return;
    floating = true;

    var startPosition : Vector3 = objTransform.position;
    var endPosition : Vector3 = objTransform.position + amplitude;
    var t : float = 0.0;
    var halfRate = 2 / duration; //we need the rate for each half

    while (t < 1.0) { //Rise
        t += Time.deltaTime * halfRate;
        objTransform.position = Vector3.Lerp(startPosition, endPosition, 
                                             Mathf.SmoothStep(0.0, 1.0, t));
        yield;
    }
    while (t > 0.0) { //Fall
        t -= Time.deltaTime * halfRate;
        objTransform.position = Vector3.Lerp(startPosition, endPosition,
                                             Mathf.SmoothStep(0.0, 1.0, t));
        yield;
    }

    floating = false;
}

Since this script is only able to run one at a time because of the boolean, if you are making the object it is attached to float, you don't need to pass the Transform. Also, this seems to be written to run as a co-routine so that it will finish the duration, meaning that in order to keep floating, you would have to call this after the duration every time. All of this seems sort of needless - why not try:

private var floating : bool = false;
private var floatTime : float;
private var floatOrigin : float;
private var floatPeak : Vector3;

//These are public so you can set/tweak them, etc.
var floatAmplitude : Vector3 = Vector3.up * 5;
var floatFrequency : float = 0.5;
var floatDuration : float = Mathf.Infinity;

function Update() { if(floating) Float(); }

function StartFloating() { //Setup
    floating = true;
    floatTime = 0.0;
    floatOrigin = transform.position;
    floatPeak = transform.position + floatAmplitude;
}

function Float() {
    if (!floating) return;

    floatTime += Time.deltaTime;
    var t = ((floatTime * floatFrequency) % 1) * 2;
    if(t >= 1) t = 2 - t; //float back down
    transform.position = Vector3.Lerp(floatOrigin, floatPeak,
                                      Mathf.SmoothStep(0.0, 1.0, t));

    if (floatTime >= floatDuration) floating = false;
}

In either case, you could also use localPosition if you want it orientation relative.

The real problem is if we want to float while performing other motion. We want to be adding to position, not setting it. The problem is that if we simply add to position, it is possible that we might float too little or too far in a given direction. One solution is to only float on one axis and then only set that value using for example:

    var floatOrigin : float = transform.position.y;
    var floatPeak : float = transform.position.y + floatAmplitude;
    //and
    transform.position.y = Mathf.SmoothStep(floatOrigin, floatPeak, t);

But that just avoids the problem. What you really need to do in order to solve this is find the adjustment needed to get to the target position, which might look like so:

private var floating : bool = false;
private var floatTime : float;
private var floatPosition : float;

//These are public so you can set/tweak them, etc.
var floatAmplitude : Vector3 = Vector3.up * 5;
var floatFrequency : float = 0.5;
var floatDuration : float = Mathf.Infinity;

function Update() { if(floating) Float(); }

function StartFloating() { //Setup
    floating = true;
    floatTime = 0.0;
    floatPosition = Vector3.zero;
}

function Float() {
    if (!floating) return;

    floatTime += Time.deltaTime;
    var t = ((floatTime * floatFrequency) % 1) * 2;
    if(t >= 1) t = 2 - t; //float back down
    var floatDesination : Vector3 = Vector3.Lerp(Vector3.zero, floatAmplitude,
                                                 Mathf.SmoothStep(0.0, 1.0, t));
    var FloatAdjustment : Vector3 = floatDestination - floatPosition;
    transform.position += FloatAdjustment;
    floatPosition = floatDestination;

    if (floatTime >= floatDuration) floating = false;
}

or with the other code:

private var floating : bool = false;

function Float(objTransform : Transform, amplitude : Vector3, duration : float) {
    if (floating) return;
    floating = true;

    var currentPosition : Vector3 = Vector3.zero;
    var targetPosition : Vector3;
    var adjustment : Vector3;
    var t : float = 0.0;
    var halfRate = 2 / duration; //we need the rate for each half

    while (t < 1.0) { //Rise
        t += Time.deltaTime * halfRate;
        targetPosition = Vector3.Lerp(Vector3.zero, amplitude, 
                                             Mathf.SmoothStep(0.0, 1.0, t));
        adjustment = targetPosition - currentPosition;
        objTransform.position += FloatAdjustment;
        currentPosition = targerPosition;
        yield;
    }
    while (t > 0.0) { //Fall
        t -= Time.deltaTime * halfRate;
        targetPosition = Vector3.Lerp(Vector3.zero, amplitude, 
                                             Mathf.SmoothStep(0.0, 1.0, t));
        adjustment = targetPosition - currentPosition;
        objTransform.position += FloatAdjustment;
        currentPosition = targerPosition;
        yield;
    }

    floating = false;
}