Unity游戏开发中会用到的插值方法,取自项目中的Interpolate.cs

来源:互联网 发布:农村淘宝面试和答案 编辑:程序博客网 时间:2024/06/05 20:03
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/**
 * Interpolation utility functionseasingbezierand catmull-rom.
 * Consider using Unity's Animation curve editor and AnimationCurve class
 * before scripting the desired behaviour using this utility.
 *
 * Interpolation functionality available at different levels of abstraction.
 * Low level access via individual easing functions (exEaseInOutCirc),
 * Bezier(), and CatmullRom(). High level access using sequence generators,
 * NewEase(), NewBezier(), and NewCatmullRom().
 *
 * Sequence generators are typically used as follows:
 *
 * IEnumerable<Vector3sequence = Interpolate.New[Ease|Bezier|CatmulRom](configuration);
 * foreach (Vector3 newPoint in sequence) {
 *   transform.position = newPoint;
 *   yield return WaitForSeconds(1.0f);
 * }
 *
 * Or:
 *
 * IEnumerator<Vector3sequence = Interpolate.New[Ease|Bezier|CatmulRom](configuration).GetEnumerator();
 * function Update() {
 *   if (sequence.MoveNext()) {
 *     transform.position = sequence.Current;
 *   }
 * }
 *
 * The low level functions work similarly to Unity's built in Lerp and it is
 * up to you to track and pass in elapsedTime and duration on every callThe
 * functions take this form (or the logical equivalent for Bezier() and CatmullRom()).
 *
 * transform.position = ease(startdistanceelapsedTimeduration);
 *
 * For convenience in configuration you can use the Ease(EaseTypefunction to
 * look up a concrete easing function:
 * 
 *  [SerializeField]
 *  Interpolate.EaseType easeType// set using Unity's property inspector
 *  Interpolate.Function ease// easing of a particular EaseType
 * function Awake() {
 *   ease = Interpolate.Ease(easeType);
 * }
 *
 * @author Fernando Zapata (fernando@cpudreams.com)
 * @Traduzione Andrea85cs (andrea85cs@dynematica.it)
 */
//实现老虎机效果
public class Interpolate {


    /**
 * Different methods of easing interpolation.
 */
    public enum EaseType {
        Linear,
        EaseInQuad,
        EaseOutQuad,
        EaseInOutQuad,
        EaseInCubic,
        EaseOutCubic,
        EaseInOutCubic,
        EaseInQuart,
        EaseOutQuart,
        EaseInOutQuart,
        EaseInQuint,
        EaseOutQuint,
        EaseInOutQuint,
        EaseInSine,
        EaseOutSine,
        EaseInOutSine,
        EaseInExpo,
        EaseOutExpo,
        EaseInOutExpo,
        EaseInCirc,
        EaseOutCirc,
        EaseInOutCirc
    }

    /**
    * Sequence of eleapsedTimes until elapsedTime is >= duration.
    *
    * NoteelapsedTimes are calculated using the value of Time.deltatTime each
    * time a value is requested.
    */
    static Vector3 Identity(Vector3 v) {
        return v;
    }

    static Vector3 TransformDotPosition(Transform t) {
        return t.position;
    }


    static IEnumerable<floatNewTimer(float duration) {
        float elapsedTime = 0.0f;
        while (elapsedTime < duration) {
            yield return elapsedTime;
            elapsedTime += Time.deltaTime;
            // make sure last value is never skipped
            if (elapsedTime >= duration) {
                yield return elapsedTime;
            }
        }
    }

    public delegate Vector3 ToVector3<T>(T v);
    public delegate float Function(float afloat bfloat cfloat d);

    /**
     * Generates sequence of integers from start to end (inclusiveone step
     * at a time.
     */
    static IEnumerable<floatNewCounter(int startint endint step) {
        for (int i = starti <= endi += step) {
            yield return i;
        }
    }

    /**
     * Returns sequence generator from start to end over duration using the
     * given easing functionThe sequence is generated as it is accessed
     * using the Time.deltaTime to calculate the portion of duration that has
     * elapsed.
     */
    public static IEnumerator NewEase(Function easeVector3 startVector3 endfloat duration) {
        IEnumerable<floattimer = Interpolate.NewTimer(duration);
        return NewEase(easestartenddurationtimer);
    }

    /**
     * Instead of easing based on timegenerate n interpolated points (slices)
     * between the start and end positions.
     */
    public static IEnumerator NewEase(Function easeVector3 startVector3 endint slices) {
        IEnumerable<floatcounter = Interpolate.NewCounter(0slices + 11);
        return NewEase(easestartendslices + 1counter);
    }



    /**
     * Generic easing sequence generator used to implement the time and
     * slice variantsNormally you would not use this function directly.
     */
    static IEnumerator NewEase(Function easeVector3 startVector3 endfloat totalIEnumerable<floatdriver) {
        Vector3 distance = end - start;
        foreach (float i in driver) {
            yield return Ease(easestartdistanceitotal);
        }
    }

    /**
     * Vector3 interpolation using given easing methodEasing is done independently
     * on all three vector axis.
     */
    static Vector3 Ease(Function easeVector3 startVector3 distancefloat elapsedTimefloat duration) {
        start.x = ease(start.xdistance.xelapsedTimeduration);
        start.y = ease(start.ydistance.yelapsedTimeduration);
        start.z = ease(start.zdistance.zelapsedTimeduration);
        return start;
    }

    /**
     * Returns the static method that implements the given easing type for scalars.
     * Use this method to easily switch between easing interpolation types.
     *
     * All easing methods clamp elapsedTime so that it is always <= duration.
     *
     * var ease = Interpolate.Ease(EaseType.EaseInQuad);
     * i = ease(startdistanceelapsedTimeduration);
     */
    public static Function Ease(EaseType type) {
        // Source Flash easing functions:
        // http://gizma.com/easing/
        // http://www.robertpenner.com/easing/easing_demo.html
        //
        // Changed to use more friendly variable namesthat follow my Lerp
        // conventions:
        // start = b (start value)
        // distance = c (change in value)
        // elapsedTime = t (current time)
        // duration = d (time duration)

        Function f = null;
        switch (type) {
            case EaseType.Linearf = Interpolate.Linearbreak;
            case EaseType.EaseInQuadf = Interpolate.EaseInQuadbreak;
            case EaseType.EaseOutQuadf = Interpolate.EaseOutQuadbreak;
            case EaseType.EaseInOutQuadf = Interpolate.EaseInOutQuadbreak;
            case EaseType.EaseInCubicf = Interpolate.EaseInCubicbreak;
            case EaseType.EaseOutCubicf = Interpolate.EaseOutCubicbreak;
            case EaseType.EaseInOutCubicf = Interpolate.EaseInOutCubicbreak;
            case EaseType.EaseInQuartf = Interpolate.EaseInQuartbreak;
            case EaseType.EaseOutQuartf = Interpolate.EaseOutQuartbreak;
            case EaseType.EaseInOutQuartf = Interpolate.EaseInOutQuartbreak;
            case EaseType.EaseInQuintf = Interpolate.EaseInQuintbreak;
            case EaseType.EaseOutQuintf = Interpolate.EaseOutQuintbreak;
            case EaseType.EaseInOutQuintf = Interpolate.EaseInOutQuintbreak;
            case EaseType.EaseInSinef = Interpolate.EaseInSinebreak;
            case EaseType.EaseOutSinef = Interpolate.EaseOutSinebreak;
            case EaseType.EaseInOutSinef = Interpolate.EaseInOutSinebreak;
            case EaseType.EaseInExpof = Interpolate.EaseInExpobreak;
            case EaseType.EaseOutExpof = Interpolate.EaseOutExpobreak;
            case EaseType.EaseInOutExpof = Interpolate.EaseInOutExpobreak;
            case EaseType.EaseInCircf = Interpolate.EaseInCircbreak;
            case EaseType.EaseOutCircf = Interpolate.EaseOutCircbreak;
            case EaseType.EaseInOutCircf = Interpolate.EaseInOutCircbreak;
        }
        return f;
    }

    /**
     * Returns sequence generator from the first node to the last node over
     * duration time using the points in-between the first and last node
     * as control points of a bezier curve used to generate the interpolated points
     * in the sequenceIf there are no control points (ieonly two nodesfirst
     * and lastthen this behaves exactly the same as NewEase(). In other words
     * a zero-degree bezier spline curve is just the easing methodThe sequence
     * is generated as it is accessed using the Time.deltaTime to calculate the
     * portion of duration that has elapsed.
     */
    public static IEnumerable<Vector3NewBezier(Function easeTransform[] nodesfloat duration) {
        IEnumerable<floattimer = Interpolate.NewTimer(duration);
        return NewBezier<Transform>(easenodesTransformDotPositiondurationtimer);
    }

    /**
     * Instead of interpolating based on timegenerate n interpolated points
     * (slicesbetween the first and last node.
     */
    public static IEnumerable<Vector3NewBezier(Function easeTransform[] nodesint slices) {
        IEnumerable<floatcounter = NewCounter(0slices + 11);
        return NewBezier<Transform>(easenodesTransformDotPositionslices + 1counter);
    }

    /**
     * A Vector3[] variation of the Transform[] NewBezier() function.
     * Same functionality but using Vector3s to define bezier curve.
     */
    public static IEnumerable<Vector3NewBezier(Function easeVector3[] pointsfloat duration) {
        IEnumerable<floattimer = NewTimer(duration);
        return NewBezier<Vector3>(easepointsIdentitydurationtimer);
    }

    /**
     * A Vector3[] variation of the Transform[] NewBezier() function.
     * Same functionality but using Vector3s to define bezier curve.
     */
    public static IEnumerable<Vector3NewBezier(Function easeVector3[] pointsint slices) {
        IEnumerable<floatcounter = NewCounter(0slices + 11);
        return NewBezier<Vector3>(easepointsIdentityslices + 1counter);
    }

    /**
     * Generic bezier spline sequence generator used to implement the time and
     * slice variantsNormally you would not use this function directly.
     */
    static IEnumerable<Vector3NewBezier<T>(Function easeIList nodesToVector3<TtoVector3float maxStepIEnumerable<floatsteps) {
        // need at least two nodes to spline between
        if (nodes.Count >= 2) {
            // copy nodes array since Bezier is destructive
            Vector3[] points = new Vector3[nodes.Count];

            foreach (float step in steps) {
                // re-initialize copy before each destructive call to Bezier
                for (int i = 0i < nodes.Counti++) {
                    points[i] = toVector3((T)nodes[i]);
                }
                yield return Bezier(easepointsstepmaxStep);
                // make sure last value is always generated
            }
        }
    }

    /**
     * A Vector3 n-degree bezier spline.
     *
     * WARNINGThe points array is modified by BezierSee NewBezier() for a
     * safe and user friendly alternative.
     *
     * You can pass zero control pointsjust the start and end pointsfor just
     * plain easingIn other words a zero-degree bezier spline curve is just the
     * easing method.
     *
     * @param points start pointn control pointsend point
     */
    static Vector3 Bezier(Function easeVector3[] pointsfloat elapsedTimefloat duration) {
        // Referencehttp://ibiblio.org/e-notes/Splines/Bezier.htm
        // Interpolate the n starting points to generate the next j = (n - 1points,
        // then interpolate those n - 1 points to generate the next n - 2 points,
        // continue this until we have generated the last point (n - (n - 1)), j = 1.
        // We store the next set of output points in the same array as the
        // input points used to generate themThis works because we store the
        // result in the slot of the input point that is no longer used for this
        // iteration.
        for (int j = points.Length - 1j > 0j--) {
            for (int i = 0i < ji++) {
                points[i].x = ease(points[i].xpoints[i + 1].x - points[i].xelapsedTimeduration);
                points[i].y = ease(points[i].ypoints[i + 1].y - points[i].yelapsedTimeduration);
                points[i].z = ease(points[i].zpoints[i + 1].z - points[i].zelapsedTimeduration);
            }
        }
        return points[0];
    }

    /**
     * Returns sequence generator from the first nodethrough each control point,
     * and to the last nodeN points are generated between each node (slices)
     * using Catmull-Rom.
     */
    public static IEnumerable<Vector3NewCatmullRom(Transform[] nodesint slicesbool loop) {
        return NewCatmullRom<Transform>(nodesTransformDotPositionslicesloop);
    }

    /**
     * A Vector3[] variation of the Transform[] NewCatmullRom() function.
     * Same functionality but using Vector3s to define curve.
     */
    public static IEnumerable<Vector3NewCatmullRom(Vector3[] pointsint slicesbool loop) {
        return NewCatmullRom<Vector3>(pointsIdentityslicesloop);
    }

    /**
     * Generic catmull-rom spline sequence generator used to implement the
     * Vector3[] and Transform[] variantsNormally you would not use this
     * function directly.
     */
    static IEnumerable<Vector3NewCatmullRom<T>(IList nodesToVector3<TtoVector3int slicesbool loop) {
        // need at least two nodes to spline between
        if (nodes.Count >= 2) {

            // yield the first point explicitlyif looping the first point
            // will be generated again in the step for loop when interpolating
            // from last point back to the first point
            yield return toVector3((T)nodes[0]);

            int last = nodes.Count - 1;
            for (int current = 0loop || current < lastcurrent++) {
                // wrap around when looping
                if (loop && current > last) {
                    current = 0;
                }
                // handle edge cases for looping and non-looping scenarios
                // when looping we wrap aroundwhen not looping use start for previous
                // and end for next when you at the ends of the nodes array
                int previous = (current == 0) ? ((loop) ? last : current) : current - 1;
                int start = current;
                int end = (current == last) ? ((loop) ? 0 : current) : current + 1;
                int next = (end == last) ? ((loop) ? 0 : end) : end + 1;

                // adding one guarantees yielding at least the end point
                int stepCount = slices + 1;
                for (int step = 1step <= stepCountstep++) {
                    yield return CatmullRom(toVector3((T)nodes[previous]),
                                     toVector3((T)nodes[start]),
                                     toVector3((T)nodes[end]),
                                     toVector3((T)nodes[next]),
                                     stepstepCount);
                }
            }
        }
    }

    /**
     * A Vector3 Catmull-Rom splineCatmull-Rom splines are similar to bezier
     * splines but have the useful property that the generated curve will go
     * through each of the control points.
     *
     * NOTEThe NewCatmullRom() functions are an easier to use alternative to this
     * raw Catmull-Rom implementation.
     *
     * @param previous the point just before the start point or the start point
     *                 itself if no previous point is available
     * @param start generated when elapsedTime == 0
     * @param end generated when elapsedTime >= duration
     * @param next the point just after the end point or the end point itself if no
     *             next point is available
     */
    static Vector3 CatmullRom(Vector3 previousVector3 startVector3 endVector3 next
                                float elapsedTimefloat duration) {
        // References used:
        // p.266 GemsV1
        //
        // tension is often set to 0.5 but you can use any reasonable value:
        // http://www.cs.cmu.edu/~462/projects/assn2/assn2/catmullRom.pdf
        //
        // bias and tension controls:
        // http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/interpolation/

        float percentComplete = elapsedTime / duration;
        float percentCompleteSquared = percentComplete * percentComplete;
        float percentCompleteCubed = percentCompleteSquared * percentComplete;

        return previous * (-0.5f * percentCompleteCubed +
                                   percentCompleteSquared -
                            0.5f * percentComplete) +
                start   * ( 1.5f * percentCompleteCubed +
                           -2.5f * percentCompleteSquared + 1.0f) +
                end     * (-1.5f * percentCompleteCubed +
                            2.0f * percentCompleteSquared +
                            0.5f * percentComplete) +
                next    * ( 0.5f * percentCompleteCubed -
                            0.5f * percentCompleteSquared);
    }




    /**
     * Linear interpolation (same as Mathf.Lerp)
     */
    static float Linear(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime to be <= duration
        if (elapsedTime > duration) { elapsedTime = duration; }
        return distance * (elapsedTime / duration) + start;
    }

    /**
     * quadratic easing in - accelerating from zero velocity
     */
    static float EaseInQuad(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        return distance * elapsedTime * elapsedTime + start;
    }

    /**
     * quadratic easing out - decelerating to zero velocity
     */
    static float EaseOutQuad(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        return -distance * elapsedTime * (elapsedTime - 2) + start;
    }

    /**
     * quadratic easing in/out - acceleration until halfwaythen deceleration
     */
    static float EaseInOutQuad(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
        if (elapsedTime < 1return distance / 2 * elapsedTime * elapsedTime + start;
        elapsedTime--;
        return -distance / 2 * (elapsedTime * (elapsedTime - 2) - 1) + start;
    }

    /**
     * cubic easing in - accelerating from zero velocity
     */
    static float EaseInCubic(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        return distance * elapsedTime * elapsedTime * elapsedTime + start;
    }

    /**
     * cubic easing out - decelerating to zero velocity
     */
    static float EaseOutCubic(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        elapsedTime--;
        return distance * (elapsedTime * elapsedTime * elapsedTime + 1) + start;
    }

    /**
     * cubic easing in/out - acceleration until halfwaythen deceleration
     */
    static float EaseInOutCubic(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
        if (elapsedTime < 1return distance / 2 * elapsedTime * elapsedTime * elapsedTime + start;
        elapsedTime -= 2;
        return distance / 2 * (elapsedTime * elapsedTime * elapsedTime + 2) + start;
    }

    /**
     * quartic easing in - accelerating from zero velocity
     */
    static float EaseInQuart(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        return distance * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
    }

    /**
     * quartic easing out - decelerating to zero velocity
     */
    static float EaseOutQuart(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        elapsedTime--;
        return -distance * (elapsedTime * elapsedTime * elapsedTime * elapsedTime - 1) + start;
    }

    /**
     * quartic easing in/out - acceleration until halfwaythen deceleration
     */
    static float EaseInOutQuart(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
        if (elapsedTime < 1return distance / 2 * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
        elapsedTime -= 2;
        return -distance / 2 * (elapsedTime * elapsedTime * elapsedTime * elapsedTime - 2) + start;
    }


    /**
     * quintic easing in - accelerating from zero velocity
     */
    static float EaseInQuint(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        return distance * elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
    }

    /**
     * quintic easing out - decelerating to zero velocity
     */
    static float EaseOutQuint(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        elapsedTime--;
        return distance * (elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + 1) + start;
    }

    /**
     * quintic easing in/out - acceleration until halfwaythen deceleration
     */
    static float EaseInOutQuint(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2f);
        if (elapsedTime < 1return distance / 2 * elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + start;
        elapsedTime -= 2;
        return distance / 2 * (elapsedTime * elapsedTime * elapsedTime * elapsedTime * elapsedTime + 2) + start;
    }

    /**
     * sinusoidal easing in - accelerating from zero velocity
     */
    static float EaseInSine(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime to be <= duration
        if (elapsedTime > duration) { elapsedTime = duration; }
        return -distance * Mathf.Cos(elapsedTime / duration * (Mathf.PI / 2)) + distance + start;
    }

    /**
     * sinusoidal easing out - decelerating to zero velocity
     */
    static float EaseOutSine(float startfloat distancefloat elapsedTimefloat duration) {
        if (elapsedTime > duration) { elapsedTime = duration; }
        return distance * Mathf.Sin(elapsedTime / duration * (Mathf.PI / 2)) + start;
    }

    /**
     * sinusoidal easing in/out - accelerating until halfwaythen decelerating
     */
    static float EaseInOutSine(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime to be <= duration
        if (elapsedTime > duration) { elapsedTime = duration; }
        return -distance / 2 * (Mathf.Cos(Mathf.PI * elapsedTime / duration) - 1) + start;
    }

    /**
     * exponential easing in - accelerating from zero velocity
     */
    static float EaseInExpo(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime to be <= duration
        if (elapsedTime > duration) { elapsedTime = duration; }
        return distance * Mathf.Pow(210 * (elapsedTime / duration - 1)) + start;
    }

    /**
     * exponential easing out - decelerating to zero velocity
     */
    static float EaseOutExpo(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime to be <= duration
        if (elapsedTime > duration) { elapsedTime = duration; }
        return distance * (-Mathf.Pow(2, -10 * elapsedTime / duration) + 1) + start;
    }

    /**
     * exponential easing in/out - accelerating until halfwaythen decelerating
     */
    static float EaseInOutExpo(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
        if (elapsedTime < 1return distance / 2 *  Mathf.Pow(210 * (elapsedTime - 1)) + start;
        elapsedTime--;
        return distance / 2 * (-Mathf.Pow(2, -10 * elapsedTime) + 2) + start;
    }

    /**
     * circular easing in - accelerating from zero velocity
     */
    static float EaseInCirc(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        return -distance * (Mathf.Sqrt(1 - elapsedTime * elapsedTime) - 1) + start;
    }

    /**
     * circular easing out - decelerating to zero velocity
     */
    static float EaseOutCirc(float startfloat distancefloat elapsedTimefloat duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 1.0f : elapsedTime / duration;
        elapsedTime--;
        return distance * Mathf.Sqrt(1 - elapsedTime * elapsedTime) + start;
    }

    /**
     * circular easing in/out - acceleration until halfwaythen deceleration
     */
    static float EaseInOutCirc(float startfloat distancefloat
                         elapsedTimefloat duration) {
        // clamp elapsedTime so that it cannot be greater than duration
        elapsedTime = (elapsedTime > duration) ? 2.0f : elapsedTime / (duration / 2);
        if (elapsedTime < 1return -distance / 2 * (Mathf.Sqrt(1 - elapsedTime * elapsedTime) - 1) + start;
        elapsedTime -= 2;
        return distance / 2 * (Mathf.Sqrt(1 - elapsedTime * elapsedTime) + 1) + start;
    }
}
0 0