ease function 缓动函数 插值算法

各种类型 图标 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()};
		}
		
		
	}

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值