各种类型 图标 http://easings.net/zh-cn
官网 .http://www.robertpenner.com/easing/
unity3D 所用C#代码
easing.cs
using UnityEngine;
using System.Collections;
using System;
public static class Easing
{
// Adapted from source : http://www.robertpenner.com/easing/
public static float Ease(double linearStep, float acceleration, EasingType type)
{
float easedStep = acceleration > 0 ? EaseIn(linearStep, type) :
acceleration < 0 ? EaseOut(linearStep, type) :
(float) linearStep;
return MathHelper.Lerp(linearStep, easedStep, Math.Abs(acceleration));
}
public static float EaseIn(double linearStep, EasingType type)
{
switch (type)
{
case EasingType.Step: return linearStep < 0.5 ? 0 : 1;
case EasingType.Linear: return (float)linearStep;
case EasingType.Sine: return Sine.EaseIn(linearStep);
case EasingType.Quadratic: return Power.EaseIn(linearStep, 2);
case EasingType.Cubic: return Power.EaseIn(linearStep, 3);
case EasingType.Quartic: return Power.EaseIn(linearStep, 4);
case EasingType.Quintic: return Power.EaseIn(linearStep, 5);
}
throw new NotImplementedException();
}
public static float EaseOut(double linearStep, EasingType type)
{
switch (type)
{
case EasingType.Step: return linearStep < 0.5 ? 0 : 1;
case EasingType.Linear: return (float)linearStep;
case EasingType.Sine: return Sine.EaseOut(linearStep);
case EasingType.Quadratic: return Power.EaseOut(linearStep, 2);
case EasingType.Cubic: return Power.EaseOut(linearStep, 3);
case EasingType.Quartic: return Power.EaseOut(linearStep, 4);
case EasingType.Quintic: return Power.EaseOut(linearStep, 5);
}
throw new NotImplementedException();
}
public static float EaseInOut(double linearStep, EasingType easeInType, EasingType easeOutType)
{
return linearStep < 0.5 ? EaseInOut(linearStep, easeInType) : EaseInOut(linearStep, easeOutType);
}
public static float EaseInOut(double linearStep, EasingType type)
{
switch (type)
{
case EasingType.Step: return linearStep < 0.5 ? 0 : 1;
case EasingType.Linear: return (float)linearStep;
case EasingType.Sine: return Sine.EaseInOut(linearStep);
case EasingType.Quadratic: return Power.EaseInOut(linearStep, 2);
case EasingType.Cubic: return Power.EaseInOut(linearStep, 3);
case EasingType.Quartic: return Power.EaseInOut(linearStep, 4);
case EasingType.Quintic: return Power.EaseInOut(linearStep, 5);
}
throw new NotImplementedException();
}
static class Sine
{
public static float EaseIn(double s)
{
return (float)Math.Sin(s * MathHelper.HalfPi - MathHelper.HalfPi) + 1;
}
public static float EaseOut(double s)
{
return (float)Math.Sin(s * MathHelper.HalfPi);
}
public static float EaseInOut(double s)
{
return (float)(Math.Sin(s * MathHelper.Pi - MathHelper.HalfPi) + 1) / 2;
}
}
static class Power
{
public static float EaseIn(double s, int power)
{
return (float)Math.Pow(s, power);
}
public static float EaseOut(double s, int power)
{
var sign = power % 2 == 0 ? -1 : 1;
return (float)(sign * (Math.Pow(s - 1, power) + sign));
}
public static float EaseInOut(double s, int power)
{
s *= 2;
if (s < 1) return EaseIn(s, power) / 2;
var sign = power % 2 == 0 ? -1 : 1;
return (float)(sign / 2.0 * (Math.Pow(s - 2, power) + sign * 2));
}
}
}
public enum EasingType
{
Step,
Linear,
Sine,
Quadratic,
Cubic,
Quartic,
Quintic
}
public static class MathHelper
{
public const float Pi = (float)Math.PI;
public const float HalfPi = (float)(Math.PI / 2);
public static float Lerp(double from, double to, double step)
{
return (float)((to - from) * step + from);
}
}
Curves.CS
using UnityEngine;
using System.Collections;
using System.Linq;
using System.Collections.Generic;
public static class QuadBez {
public static Vector3 Interp(Vector3 st, Vector3 en, Vector3 ctrl, float t) {
float d = 1f - t;
return d * d * st + 2f * d * t * ctrl + t * t * en;
}
public static Vector3 Velocity(Vector3 st, Vector3 en, Vector3 ctrl, float t) {
return (2f * st - 4f * ctrl + 2f * en) * t + 2f * ctrl - 2f * st;
}
public static void GizmoDraw(Vector3 st, Vector3 en, Vector3 ctrl, float t) {
Gizmos.color = Color.red;
Gizmos.DrawLine(st, ctrl);
Gizmos.DrawLine(ctrl, en);
Gizmos.color = Color.white;
Vector3 prevPt = st;
for (int i = 1; i <= 20; i++) {
float pm = (float) i / 20f;
Vector3 currPt = Interp(st,en,ctrl,pm);
Gizmos.DrawLine(currPt, prevPt);
prevPt = currPt;
}
Gizmos.color = Color.blue;
Vector3 pos = Interp(st,en, ctrl,t);
Gizmos.DrawLine(pos, pos + Velocity(st,en,ctrl,t));
}
}
public static class CubicBez {
public static Vector3 Interp(Vector3 st, Vector3 en, Vector3 ctrl1, Vector3 ctrl2, float t) {
float d = 1f - t;
return d * d * d * st + 3f * d * d * t * ctrl1 + 3f * d * t * t * ctrl2 + t * t * t * en;
}
public static Vector3 Velocity(Vector3 st, Vector3 en, Vector3 ctrl1, Vector3 ctrl2,float t) {
return (-3f * st + 9f * ctrl1 - 9f * ctrl2 + 3f * en) * t * t
+ (6f * st - 12f * ctrl1 + 6f * ctrl2) * t
- 3f * st + 3f * ctrl1;
}
public static void GizmoDraw(Vector3 st, Vector3 en, Vector3 ctrl1, Vector3 ctrl2,float t) {
Gizmos.color = Color.red;
Gizmos.DrawLine(st, ctrl1);
Gizmos.DrawLine(ctrl2, en);
Gizmos.color = Color.white;
Vector3 prevPt = st;
for (int i = 1; i <= 20; i++) {
float pm = (float) i / 20f;
Vector3 currPt = Interp(st,en,ctrl1, ctrl2, pm);
Gizmos.DrawLine(currPt, prevPt);
prevPt = currPt;
}
Gizmos.color = Color.blue;
Vector3 pos = Interp(st,en,ctrl1, ctrl2, t);
Gizmos.DrawLine(pos, pos + Velocity(st,en,ctrl1,ctrl2,t));
}
}
public static class CRSpline {
public static Vector3 Interp(Vector3[] pts, float t) {
int numSections = pts.Length - 3;
int currPt = Mathf.Min(Mathf.FloorToInt(t * (float) numSections), numSections - 1);
float u = t * (float) numSections - (float) currPt;
Vector3 a = pts[currPt];
Vector3 b = pts[currPt + 1];
Vector3 c = pts[currPt + 2];
Vector3 d = pts[currPt + 3];
return .5f * (
(-a + 3f * b - 3f * c + d) * (u * u * u)
+ (2f * a - 5f * b + 4f * c - d) * (u * u)
+ (-a + c) * u
+ 2f * b
);
}
public static Vector3 InterpConstantSpeed(Vector3[] pts, float t) {
int numSections = pts.Length - 3;
float mag = 0;
float [] sizes = new float[pts.Length-1];
for(var i = 0; i < pts.Length-1; i++)
{
var m = (pts[i+1] - pts[i]).magnitude;
sizes[i] = m;
mag += m;
}
int currPt=1;
float s=0;
double u = 0;
do
{
double tAtBeginning = s/mag;
double tAtEnd = (s + sizes[currPt+0])/mag;
u = (t-tAtBeginning) / (tAtEnd - tAtBeginning);
if(u<0 || u>1)
{
s+=sizes[currPt];
currPt++;
}
else
break;
} while(currPt < numSections+1);
u = Mathf.Clamp01((float)u);
Vector3 a = pts[currPt-1];
Vector3 b = pts[currPt + 0];
Vector3 c = pts[currPt + 1];
Vector3 d = pts[currPt + 2];
return .5f * (
(-a + 3f * b - 3f * c + d) * (float)(u * u * u)
+ (2f * a - 5f * b + 4f * c - d) * (float)(u * u)
+ (-a + c) * (float)u
+ 2f * b
);
}
public static Vector3 Velocity(Vector3[] pts, float t) {
int numSections = pts.Length - 3;
int currPt = Mathf.Min(Mathf.FloorToInt(t * (float) numSections), numSections - 1);
float u = t * (float) numSections - (float) currPt;
Vector3 a = pts[currPt];
Vector3 b = pts[currPt + 1];
Vector3 c = pts[currPt + 2];
Vector3 d = pts[currPt + 3];
return 1.5f * (-a + 3f * b - 3f * c + d) * (u * u)
+ (2f * a -5f * b + 4f * c - d) * u
+ .5f * c - .5f * a;
}
public static void GizmoDraw(Vector3[] pts, float t) {
Gizmos.color = Color.white;
Vector3 prevPt = Interp(pts, 0);
for (int i = 1; i <= 20; i++) {
float pm = (float) i / 20f;
Vector3 currPt = Interp(pts, pm);
Gizmos.DrawLine(currPt, prevPt);
prevPt = currPt;
}
Gizmos.color = Color.blue;
Vector3 pos = Interp(pts, t);
Gizmos.DrawLine(pos, pos + Velocity(pts, t));
}
}
public class Interesting
{
}
public static class Spline
{
public static Vector3 Interp(Path pts, float t, EasingType ease = EasingType.Linear, bool easeIn = true, bool easeOut = true)
{
t = Ease(t, ease, easeIn, easeOut);
if(pts.Length == 0)
{
return Vector3.zero;
}
else if(pts.Length ==1 )
{
return pts[0];
}
else if(pts.Length == 2)
{
return Vector3.Lerp(pts[0], pts[1], t);
}
else if(pts.Length == 3)
{
return QuadBez.Interp(pts[0], pts[2], pts[1], t);
}
else if(pts.Length == 4)
{
return CubicBez.Interp(pts[0], pts[3], pts[1], pts[2], t);
}
else
{
return CRSpline.Interp(Wrap(pts), t);
}
}
private static float Ease(float t, EasingType ease = EasingType.Linear, bool easeIn = true, bool easeOut = true)
{
t = Mathf.Clamp01(t);
if(easeIn && easeOut)
{
t = Easing.EaseInOut(t, ease);
} else if(easeIn)
{
t = Easing.EaseIn(t, ease);
} else if(easeOut)
{
t = Easing.EaseOut(t, ease);
}
return t;
}
public static Vector3 InterpConstantSpeed(Path pts, float t, EasingType ease = EasingType.Linear, bool easeIn = true, bool easeOut = true)
{
t = Ease(t, ease, easeIn, easeOut);
if(pts.Length == 0)
{
return Vector3.zero;
}
else if(pts.Length ==1 )
{
return pts[0];
}
else if(pts.Length == 2)
{
return Vector3.Lerp(pts[0], pts[1], t);
}
else if(pts.Length == 3)
{
return QuadBez.Interp(pts[0], pts[2], pts[1], t);
}
else if(pts.Length == 4)
{
return CubicBez.Interp(pts[0], pts[3], pts[1], pts[2], t);
}
else
{
return CRSpline.InterpConstantSpeed(Wrap(pts), t);
}
}
public static Vector3 MoveOnPath(Path pts, Vector3 currentPosition, ref float pathPosition, float maxSpeed=1f, float smoothnessFactor=100, EasingType ease = EasingType.Linear, bool easeIn = true, bool easeOut = true)
{
maxSpeed *= Time.deltaTime;
pathPosition = Mathf.Clamp01(pathPosition);
var goal = Interp(pts, pathPosition, ease, easeIn, easeOut);
float distance;
while((distance = (goal - currentPosition).magnitude) <= maxSpeed && pathPosition < 1)
{
currentPosition = goal;
maxSpeed -= distance;
pathPosition = Mathf.Clamp01(pathPosition + 1/smoothnessFactor);
goal = Interp(pts, pathPosition, ease, easeIn, easeOut);
}
if(distance != 0)
{
currentPosition = Vector3.MoveTowards(currentPosition, goal, maxSpeed);
}
return currentPosition;
}
public static Vector3 MoveOnPath(Path pts, Vector3 currentPosition, ref float pathPosition, ref Quaternion rotation, float maxSpeed=1f, float smoothnessFactor=100, EasingType ease = EasingType.Linear, bool easeIn = true, bool easeOut = true)
{
var result = MoveOnPath(pts, currentPosition, ref pathPosition, maxSpeed, smoothnessFactor, ease, easeIn, easeOut);
rotation = result.Equals(currentPosition) ? Quaternion.identity : Quaternion.LookRotation(result - currentPosition);
return result;
}
public static Quaternion RotationBetween(Path pts, float t1, float t2, EasingType ease = EasingType.Linear, bool easeIn = true, bool easeOut = true)
{
return Quaternion.LookRotation(Interp(pts, t2, ease, easeIn, easeOut) - Interp(pts, t1, ease, easeIn, easeOut));
}
public static Vector3 Velocity(Path pts, float t, EasingType ease = EasingType.Linear, bool easeIn = true, bool easeOut = true)
{
t = Ease(t);
if(pts.Length == 0)
{
return Vector3.zero;
}
else if(pts.Length ==1 )
{
return pts[0];
}
else if(pts.Length == 2)
{
return Vector3.Lerp(pts[0], pts[1], t);
}
else if(pts.Length == 3)
{
return QuadBez.Velocity(pts[0], pts[2], pts[1], t);
}
else if(pts.Length == 4)
{
return CubicBez.Velocity(pts[0], pts[3], pts[1], pts[2], t);
}
else
{
return CRSpline.Velocity(Wrap(pts), t);
}
}
public static Vector3[] Wrap(Vector3[] path)
{
return (new Vector3[] { path[0] }).Concat(path).Concat(new Vector3[] { path[path.Length-1]}).ToArray();
}
public static void GizmoDraw(Vector3[] pts, float t,EasingType ease = EasingType.Linear, bool easeIn = true, bool easeOut = true) {
Gizmos.color = Color.white;
Vector3 prevPt = Interp(pts, 0);
for (int i = 1; i <= 20; i++) {
float pm = (float) i / 20f;
Vector3 currPt = Interp(pts, pm, ease, easeIn, easeOut);
Gizmos.DrawLine(currPt, prevPt);
prevPt = currPt;
}
Gizmos.color = Color.blue;
Vector3 pos = Interp(pts, t, ease, easeIn, easeOut);
Gizmos.DrawLine(pos, pos + Velocity(pts, t, ease, easeIn, easeOut));
}
public class Path
{
private Vector3[] _path;
public Vector3[] path
{
get
{
return _path;
}
set
{
_path = value;
}
}
public int Length
{
get
{
return path != null ? path.Length : 0;
}
}
public Vector3 this[int index]
{
get
{
return path[index];
}
}
public static implicit operator Path(Vector3[] path)
{
return new Path() {path = path};
}
public static implicit operator Vector3[](Path p)
{
return p != null ? p.path : new Vector3[0];
}
public static implicit operator Path(Transform[] path)
{
return new Path() {path = path.Select(p=>p.position).ToArray()};
}
public static implicit operator Path(GameObject[] path)
{
return new Path() {path = path.Select(p=>p.transform.position).ToArray()};
}
}
}